/* The kernel log module. * * This is an abstracted module. As Linux and BSD kernel log is conceptually the * same, we do not do different input plugins for them but use * imklog in both cases, just with different "backend drivers" for * the different platforms. This also enables a rsyslog.conf to * be used on multiple platforms without the need to take care of * what the kernel log is coming from. * * See platform-specific files (e.g. linux.c, bsd.c) in the plugin's * working directory. For other systems with similar kernel logging * functionality, no new input plugin shall be written but rather a * driver be developed for imklog. Please note that imklog itself is * mostly concerned with handling the interface. Any real action happens * in the drivers, as things may be pretty different on different * platforms. * * Please note that this file replaces the klogd daemon that was * also present in pre-v3 versions of rsyslog. * * Copyright (C) 2008 by Rainer Gerhards and Adiscon GmbH * * This file is part of rsyslog. * * Rsyslog is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rsyslog is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Rsyslog. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include "syslogd.h" #include "cfsysline.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "imklog.h" MODULE_TYPE_INPUT /* Module static data */ DEF_IMOD_STATIC_DATA /* configuration settings TODO: move to instance data? */ int dbgPrintSymbols = 0; /* this one is extern so the helpers can access it! */ int symbols_twice = 0; int use_syscall = 0; int symbol_lookup = 1; /* TODO: configuration for the following directives must be implemented. It * was not done yet because we either do not yet have a config handler for * that type or I thought it was acceptable to push it to a later stage when * I gained more handson experience with the input module interface (and the * changes resulting from that). -- rgerhards, 2007-12-20 */ char *symfile = NULL; int console_log_level = -1; /* Includes. */ #include #include #include #include #if HAVE_TIME_H # include #endif #include #include #define __LIBRARY__ #include /* Write a message to the message queue. * returns -1 if it fails, something else otherwise */ static rsRetVal writeSyslogV(int iPRI, const char *szFmt, va_list va) { DEFiRet; int iChars; int iLen; time_t tNow; char msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ assert(szFmt != NULL); /* build the message */ time(&tNow); /* we can use sprintf safely below, because we know the size of the constants. * By doing so, we save some cpu cycles and code complexity (for unnecessary * error checking). */ iLen = sprintf(msgBuf, "<%d>%.15s kernel: ", iPRI, ctime(&tNow) + 4); iChars = vsnprintf(msgBuf + iLen, sizeof(msgBuf) / sizeof(char) - iLen, szFmt, va); /* here we must create our message object and supply it to the message queue */ CHKiRet(parseAndSubmitMessage(LocalHostName, msgBuf, strlen(msgBuf), MSG_DONT_PARSE_HOSTNAME, NOFLAG, eFLOWCTL_LIGHT_DELAY)); finalize_it: RETiRet; } /* And now the same with variable arguments */ static int writeSyslog(int iPRI, const char *szFmt, ...) { int iRet; va_list va; assert(szFmt != NULL); va_start(va, szFmt); iRet = writeSyslogV(iPRI, szFmt, va); va_end(va); return(iRet); } rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); rsRetVal Syslog(int priority, char *fmt, ...) { DEFiRet; va_list ap; char *argl; /* Output using syslog. */ if(!strcmp(fmt, "%s")) { va_start(ap, fmt); argl = va_arg(ap, char *); if (argl[0] == '<' && argl[1] && argl[2] == '>') { switch ( argl[1] ) { case '0': priority = LOG_EMERG; break; case '1': priority = LOG_ALERT; break; case '2': priority = LOG_CRIT; break; case '3': priority = LOG_ERR; break; case '4': priority = LOG_WARNING; break; case '5': priority = LOG_NOTICE; break; case '6': priority = LOG_INFO; break; case '7': default: priority = LOG_DEBUG; } argl += 3; } iRet = writeSyslog(priority, fmt, argl); va_end(ap); } else { va_start(ap, fmt); iRet = writeSyslogV(priority, fmt, ap); va_end(ap); } RETiRet; } BEGINrunInput CODESTARTrunInput /* this is an endless loop - it is terminated when the thread is * signalled to do so. This, however, is handled by the framework, * right into the sleep below. */ while(!pThrd->bShallStop) { /* klogLogKMsg() waits for the next kernel message, obtains it * and then submits it to the rsyslog main queue. * rgerhards, 2008-04-09 */ CHKiRet(klogLogKMsg()); } finalize_it: ENDrunInput BEGINwillRun CODESTARTwillRun iRet = klogWillRun(); ENDwillRun BEGINafterRun CODESTARTafterRun iRet = klogAfterRun(); ENDafterRun BEGINmodExit CODESTARTmodExit ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_IMOD_QUERIES ENDqueryEtryPt static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) { dbgPrintSymbols = 0; symbols_twice = 0; use_syscall = 0; symfile = NULL; symbol_lookup = 1; return RS_RET_OK; } BEGINmodInit() CODESTARTmodInit *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(omsdRegCFSLineHdlr((uchar *)"debugprintkernelsymbols", 0, eCmdHdlrBinary, NULL, &dbgPrintSymbols, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrBinary, NULL, &symbol_lookup, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrBinary, NULL, &symbols_twice, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrBinary, NULL, &use_syscall, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit /* vim:set ai: */