From effa35d1ae33c1ac825317802b6e970e68f98af2 Mon Sep 17 00:00:00 2001
From: Tomas Heinrich <theinric@redhat.com>
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.
</ul>
+<li><b>DefaultSeverity</b> <severity><br>
+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'.
+
+<li><b>DefaultFacility</b> <facility><br>
+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'.
+
<b>Caveats/Known Bugs:</b>
<p>
<ul>
@@ -105,6 +117,10 @@ Equivalent to: ratelimit.interval</li>
Equivalent to: ratelimit.burst</li>
<li><strong>$ImjournalIgnorePreviousMessages</strong><br>
Equivalent to: ignorePreviousMessages</li>
+<li><strong>$ImjournalDefaultSeverity</strong><br>
+Equivalent to: DefaultSeverity</li>
+<li><strong>$ImjournalDefaultFacility</strong><br>
+Equivalent to: DefaultFacility</li>
</ul>
</body>
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