From 3669057997e7665735626fd29a40bd10e160c88f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 14 Apr 2008 12:10:00 +0200 Subject: provided ability to discard non-kernel messages present in the kernel msg buffer This obviously happens on BSD (<118> markers seen). We now have the ability to allow or prevent it, with the default being not permitted. Should not at all affect other drivers, but it is implemented on a common code basis, not on the driver layer. --- plugins/imklog/bsd.c | 2 +- plugins/imklog/imklog.c | 95 ++++++++++++++++++++++++++++++------------------- rsyslog.h | 1 + 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/plugins/imklog/bsd.c b/plugins/imklog/bsd.c index 9989d5fb..c12103f3 100644 --- a/plugins/imklog/bsd.c +++ b/plugins/imklog/bsd.c @@ -84,7 +84,7 @@ static int fklog = -1; /* /dev/klog */ #endif /* open the kernel log - will be called inside the willRun() imklog - * entry point. -- rgerhards, 20080-04-09 + * entry point. -- rgerhards, 2008-04-09 */ rsRetVal klogWillRun(void) diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c index 754d655d..a5832658 100644 --- a/plugins/imklog/imklog.c +++ b/plugins/imklog/imklog.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "syslogd.h" #include "cfsysline.h" @@ -68,6 +69,7 @@ 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; +int bPermitNonKernel = 0; /* permit logging of messages not having LOG_KERN facility */ /* 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 @@ -121,57 +123,77 @@ finalize_it: RETiRet; } +/* parse the PRI from a kernel message. At least BSD seems to have + * non-kernel messages inside the kernel log... + * Expected format: "". piPri is only valid if the function + * successfully returns. If there was a proper pri ppSz is advanced to the + * position right after ">". + * rgerhards, 2008-04-14 + */ +static rsRetVal +parsePRI(uchar **ppSz, int *piPri) +{ + DEFiRet; + int i; + uchar *pSz; + + assert(ppSz != NULL); + pSz = *ppSz; + assert(pSz != NULL); + assert(piPri != NULL); + + if(*pSz != '<' || !isdigit(*(pSz+1))) + ABORT_FINALIZE(RS_RET_INVALID_PRI); + + ++pSz; + i = 0; + while(isdigit(*pSz)) { + i = i * 10 + *pSz - '0'; + } + + if(*pSz != '>') + ABORT_FINALIZE(RS_RET_INVALID_PRI); + + /* OK, we have a valid PRI */ + *piPri = i; + +finalize_it: + RETiRet; +} + rsRetVal Syslog(int priority, char *fmt, ...) __attribute__((format(printf,2, 3))); rsRetVal Syslog(int priority, char *fmt, ...) { DEFiRet; va_list ap; - char *argl; - char msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ + uchar msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ + uchar *pLogMsg; + rsRetVal localRet; /* 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 = enqMsg((uchar*)argl, LOG_KERN, priority); + pLogMsg = va_arg(ap, uchar *); + localRet = parsePRI(&pLogMsg, &priority); + if(localRet != RS_RET_INVALID_PRI && localRet != RS_RET_OK) + FINALIZE; + /* if we don't get the pri, we use whatever we were supplied */ va_end(ap); - } else { + } else { /* TODO: I think we can remove this once we pull in the errmsg object -- rgerhards, 2008-04-14 */ va_start(ap, fmt); - vsnprintf(msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap); + vsnprintf((char*)msgBuf, sizeof(msgBuf) / sizeof(char), fmt, ap); + pLogMsg = msgBuf; va_end(ap); - iRet = enqMsg((uchar*)msgBuf, LOG_KERN, priority); } + /* ignore non-kernel messages if not permitted */ + if(bPermitNonKernel == 0 && LOG_FAC(priority) != LOG_KERN) + FINALIZE; /* silently ignore */ + + iRet = enqMsg((uchar*)pLogMsg, LOG_FAC(priority), LOG_PRI(priority)); + +finalize_it: RETiRet; } @@ -237,6 +259,7 @@ CODEmodInit_QueryRegCFSLineHdlr 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 *)"klogpermitnonkernelfacility", 0, eCmdHdlrBinary, NULL, &bPermitNonKernel, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit /* vim:set ai: diff --git a/rsyslog.h b/rsyslog.h index 93b5c149..2249e040 100644 --- a/rsyslog.h +++ b/rsyslog.h @@ -171,6 +171,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_SMTP_ERROR = -2070, /**< error during SMTP transation */ RS_RET_MAIL_NO_TO = -2071, /**< recipient for mail destination is missing */ RS_RET_MAIL_NO_FROM = -2072, /**< sender for mail destination is missing */ + RS_RET_INVALID_PRI = -2073, /**< PRI value is invalid */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ -- cgit