From effa35d1ae33c1ac825317802b6e970e68f98af2 Mon Sep 17 00:00:00 2001 From: Tomas Heinrich Date: Fri, 31 Jan 2014 11:35:55 +0100 Subject: [PATCH] Improve handling of messages without syslog properties * Don't drop messages without the MESSAGE field * Set default severity for all messages Some messages comming from journald don't have the SYSLOG_PRIORITY field. These are typically the messages logged through journald's native API. Set the default severity for these messages to 'notice'. * Set default facility for all messages Some messages comming from journald don't have the SYSLOG_FACILITY field. These are typically the messages logged through journald's native API. Set the default facility for these messages to 'user'. * Make default priority configurable --- doc/imjournal.html | 16 ++++++ plugins/imjournal/imjournal.c | 124 +++++++++++++++++++++++++++++++----------- 2 files changed, 109 insertions(+), 31 deletions(-) diff --git a/doc/imjournal.html b/doc/imjournal.html index 8f29169..b4d2105 100644 --- a/doc/imjournal.html +++ b/doc/imjournal.html @@ -69,6 +69,18 @@ journal and read only new messages. This option is only used when there is no StateFile to avoid message loss. +
  • DefaultSeverity <severity>
    +Some messages comming from journald don't have the SYSLOG_PRIORITY +field. These are typically the messages logged through journald's +native API. This option specifies the default severity for these +messages. Defaults to 'notice'. + +
  • DefaultFacility <facility>
    +Some messages comming from journald don't have the SYSLOG_FACILITY +field. These are typically the messages logged through journald's +native API. This option specifies the default facility for these +messages. Defaults to 'user'. + Caveats/Known Bugs:

    diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c index 36c7e04..7d42b84 100755 --- a/plugins/imjournal/imjournal.c +++ b/plugins/imjournal/imjournal.c @@ -68,15 +68,21 @@ static struct configSettings_s { int ratelimitInterval; int ratelimitBurst; int bIgnorePrevious; + int iDfltSeverity; + int iDfltFacility; } cs; +static rsRetVal facilityHdlr(uchar **pp, void *pVal); + /* module-global parameters */ static struct cnfparamdescr modpdescr[] = { { "statefile", eCmdHdlrGetWord, 0 }, { "ratelimit.interval", eCmdHdlrInt, 0 }, { "ratelimit.burst", eCmdHdlrInt, 0 }, { "persiststateinterval", eCmdHdlrInt, 0 }, - { "ignorepreviousmessages", eCmdHdlrBinary, 0 } + { "ignorepreviousmessages", eCmdHdlrBinary, 0 }, + { "defaultseverity", eCmdHdlrSeverity, 0 }, + { "defaultfacility", eCmdHdlrString, 0 } }; static struct cnfparamblk modpblk = { CNFPARAMBLK_VERSION, @@ -85,6 +91,8 @@ static struct cnfparamblk modpblk = }; #define DFLT_persiststateinterval 10 +#define DFLT_SEVERITY LOG_PRI(LOG_NOTICE) +#define DFLT_FACILITY LOG_FAC(LOG_USER) static int bLegacyCnfModGlobalsPermitted = 1;/* are legacy module-global config parameters permitted? */ @@ -94,6 +102,37 @@ static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1 static ratelimit_t *ratelimiter = NULL; static sd_journal *j; +/* ugly workaround to handle facility numbers; values + derived from names need to be eight times smaller */ +static rsRetVal facilityHdlr(uchar **pp, void *pVal) +{ + DEFiRet; + char *p; + + skipWhiteSpace(pp); + p = (char *) *pp; + + if (isdigit((int) *p)) { + *((int *) pVal) = (int) strtol(p, (char **) pp, 10); + } else { + int len; + syslogName_t *c; + + for (len = 0; p[len] && !isspace((int) p[len]); len++) + /* noop */; + for (c = syslogFacNames; c->c_name; c++) { + if (!strncasecmp(p, (char *) c->c_name, len)) { + *((int *) pVal) = LOG_FAC(c->c_val); + break; + } + } + *pp += len; + } + + RETiRet; +} + + /* enqueue the the journal message into the message queue. * The provided msg string is not freed - thus must be done * by the caller. @@ -158,7 +197,6 @@ readjournal() { const void *get; const void *pidget; char *parse; - char *get2; size_t length; size_t pidlength; @@ -170,45 +208,52 @@ readjournal() { long prefixlen = 0; - int priority = 0; - int facility = 0; + int severity = cs.iDfltSeverity; + int facility = cs.iDfltFacility; /* Get message text */ if (sd_journal_get_data(j, "MESSAGE", &get, &length) < 0) { - logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar *)"log message from journal doesn't have MESSAGE", 0); - iRet = RS_RET_OK; - goto ret; - } - message = strndup(get+8, length-8); - if (message == NULL) { - iRet = RS_RET_OUT_OF_MEMORY; - goto ret; + message = strdup(""); + } else { + message = strndup(get+8, length-8); + if (message == NULL) { + iRet = RS_RET_OUT_OF_MEMORY; + goto ret; + } } - /* Get message priority */ + /* Get message severity ("priority" in journald's terminology) */ if (sd_journal_get_data(j, "PRIORITY", &get, &length) >= 0) { - get2 = strndup(get, length); - priority = ((char *)get2)[9] - '0'; - free (get2); + if (length == 10) { + severity = ((char *)get)[9] - '0'; + if (severity < 0 || 7 < severity) { + dbgprintf("The value of the 'PRIORITY' field is " + "out of bounds: %d, resetting\n", severity); + severity = cs.iDfltSeverity; + } + } else { + dbgprintf("The value of the 'PRIORITY' field has an " + "unexpected length: %d\n", length); + } } /* Get syslog facility */ if (sd_journal_get_data(j, "SYSLOG_FACILITY", &get, &length) >= 0) { - get2 = strndup(get, length); - char f = ((char *)get2)[16]; - if (f >= '0' && f <= '9') { - facility += f - '0'; - } - f = ((char *)get2)[17]; - if (f >= '0' && f <= '9') { - facility *= 10; - facility += (f - '0'); + if (length == 17 || length == 18) { + facility = ((char *)get)[16] - '0'; + if (length == 18) { + facility *= 10; + facility += ((char *)get)[17] - '0'; + } + if (facility < 0 || 23 < facility) { + dbgprintf("The value of the 'FACILITY' field is " + "out of bounds: %d, resetting\n", facility); + facility = cs.iDfltFacility; + } + } else { + dbgprintf("The value of the 'FACILITY' field has an " + "unexpected length: %d\n", length); } - free (get2); - } else { - /* message is missing facility -> internal systemd journal msg, drop */ - iRet = RS_RET_OK; - goto free_message; } /* Get message identifier, client pid and add ':' */ @@ -349,7 +394,7 @@ readjournal() { } /* submit message */ - enqMsg((uchar *)message, (uchar *) sys_iden_help, facility, priority, &tv, json); + enqMsg((uchar *)message, (uchar *) sys_iden_help, facility, severity, &tv, json); finalize_it: free(sys_iden_help); @@ -569,6 +614,8 @@ CODESTARTbeginCnfLoad cs.stateFile = NULL; cs.ratelimitBurst = 20000; cs.ratelimitInterval = 600; + cs.iDfltSeverity = DFLT_SEVERITY; + cs.iDfltFacility = DFLT_FACILITY; ENDbeginCnfLoad @@ -657,6 +704,17 @@ CODESTARTsetModCnf cs.ratelimitInterval = (int) pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "ignorepreviousmessages")) { cs.bIgnorePrevious = (int) pvals[i].val.d.n; + } else if (!strcmp(modpblk.descr[i].name, "defaultseverity")) { + cs.iDfltSeverity = (int) pvals[i].val.d.n; + } else if (!strcmp(modpblk.descr[i].name, "defaultfacility")) { + /* ugly workaround to handle facility numbers; values + derived from names need to be eight times smaller */ + + char *fac, *p; + + fac = p = es_str2cstr(pvals[i].val.d.estr, NULL); + facilityHdlr((uchar **) &p, (void *) &cs.iDfltFacility); + free(fac); } else { dbgprintf("imjournal: program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); @@ -710,6 +768,10 @@ CODEmodInit_QueryRegCFSLineHdlr NULL, &cs.stateFile, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalignorepreviousmessages", 0, eCmdHdlrBinary, NULL, &cs.bIgnorePrevious, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournaldefaultseverity", 0, eCmdHdlrSeverity, + NULL, &cs.iDfltSeverity, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournaldefaultfacility", 0, eCmdHdlrCustomHandler, + facilityHdlr, &cs.iDfltFacility, STD_LOADABLE_MODULE_ID)); ENDmodInit -- 1.8.4.3