pmrfc3164: try to detected headerless message

headerless is indicated by whitespace followed by either '{' or '['.
This follows the trend to send JSON messages via syslog without any
header. We use default header values in this case.

This right now is a bit experimental; we may roll it back if
problems show up in practice.

closes https://github.com/rsyslog/rsyslog/issues/2030
This commit is contained in:
Rainer Gerhards 2017-12-12 18:25:16 +01:00
parent fdbed029ca
commit a9601ebaec
3 changed files with 58 additions and 12 deletions

View File

@ -107,6 +107,7 @@ TESTS += \
pmrfc3164-AtSignsInHostname_off.sh \
pmrfc3164-tagEndingByColon.sh \
pmrfc3164-defaultTag.sh \
pmrfc3164-json.sh \
tcp_forwarding_tpl.sh \
tcp_forwarding_dflt_tpl.sh \
tcp_forwarding_retries.sh \
@ -763,6 +764,7 @@ EXTRA_DIST= \
pmrfc3164-AtSignsInHostname_off.sh \
pmrfc3164-tagEndingByColon.sh \
pmrfc3164-defaultTag.sh \
pmrfc3164-json.sh \
hostname-with-slash-dflt-invld.sh \
hostname-with-slash-dflt-slash-valid.sh \
glbl-umask.sh \

32
tests/pmrfc3164-json.sh Executable file
View File

@ -0,0 +1,32 @@
#!/bin/bash
# add 2017-12-12 by Rainer Gerhards, released under ASL 2.0
. $srcdir/diag.sh init
. $srcdir/diag.sh generate-conf
. $srcdir/diag.sh add-conf '
module(load="../plugins/imtcp/.libs/imtcp")
input(type="imtcp" port="13514" ruleset="rs")
template(name="outfmt" type="string" string="%msg%---%rawmsg%\n")
ruleset(name="rs") {
action(type="omfile" template="outfmt" file="rsyslog.out.log")
}
'
. $srcdir/diag.sh startup
. $srcdir/diag.sh tcpflood -m1 -M "\"{ \\\"c1\\\":1 }\""
. $srcdir/diag.sh tcpflood -m1 -M "\" { \\\"c2\\\":2 }\""
. $srcdir/diag.sh tcpflood -m1 -M "\" [{ \\\"c3\\\":3 }]\""
. $srcdir/diag.sh shutdown-when-empty
. $srcdir/diag.sh wait-shutdown
EXPECTED='{ "c1":1 }---{ "c1":1 }
{ "c2":2 }--- { "c2":2 }
[{ "c3":3 }]--- [{ "c3":3 }]'
echo "$EXPECTED" | cmp - rsyslog.out.log
if [ ! $? -eq 0 ]; then
echo "invalid response generated, rsyslog.out.log is:"
cat rsyslog.out.log
printf "expected was\n"
echo "$EXPECTED"
. $srcdir/diag.sh error-exit 1
fi;
. $srcdir/diag.sh exit

View File

@ -6,7 +6,7 @@
*
* File begun on 2009-11-04 by RGerhards
*
* Copyright 2007-2015 Rainer Gerhards and Adiscon GmbH.
* Copyright 2007-2017 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
@ -42,8 +42,6 @@
#include "parser.h"
#include "datetime.h"
#include "unicode-helper.h"
#ifdef _AIX
#endif
MODULE_TYPE_PARSER
MODULE_TYPE_NOKEEP
PARSER_NAME("rsyslog.rfc3164")
@ -182,15 +180,30 @@ BEGINparse2
uchar bufParseTAG[CONF_TAG_MAXSIZE];
uchar bufParseHOSTNAME[CONF_HOSTNAME_MAXSIZE];
CODESTARTparse
DBGPRINTF("Message will now be parsed by the legacy syslog parser (one size fits all... ;)).\n");
assert(pMsg != NULL);
assert(pMsg->pszRawMsg != NULL);
lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI;
DBGPRINTF("Message will now be parsed by the legacy syslog parser (offAfterPRI=%d, lenMsg=%d.\n",
pMsg->offAfterPRI, lenMsg);
/* note: offAfterPRI is already the number of PRI chars (do not add one!) */
p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */
setProtocolVersion(pMsg, MSG_LEGACY_PROTOCOL);
if(pMsg->iFacility == (LOG_INVLD>>3))
FINALIZE; /* don't parse out from invalid messages! */
if(pMsg->iFacility == (LOG_INVLD>>3)) {
DBGPRINTF("facility LOG_INVLD, do not parse\n");
FINALIZE;
}
/* now check if we have a completely headerless message. This is indicated
* by spaces or tabs followed '{' or '['.
*/
i = 0;
while(i < lenMsg && (p2parse[i] == ' ' || p2parse[i] == ' ')) {
++i;
}
if(i < lenMsg && (p2parse[i] == '{' || p2parse[i] == '[')) {
DBGPRINTF("msg seems to be headerless, treating it as such\n");
FINALIZE;
}
/* Check to see if msg contains a timestamp. We start by assuming
@ -201,8 +214,8 @@ CODESTARTparse
*/
if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) {
/* we are done - parse pointer is moved by ParseTIMESTAMP3339 */;
} else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg, NO_PARSE3164_TZSTRING,
pInst->bDetectYearAfterTimestamp) == RS_RET_OK) {
} else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg,
NO_PARSE3164_TZSTRING, pInst->bDetectYearAfterTimestamp) == RS_RET_OK) {
if(pMsg->dfltTZ[0] != '\0')
applyDfltTZ(&pMsg->tTIMESTAMP, pMsg->dfltTZ);
/* we are done - parse pointer is moved by ParseTIMESTAMP3164 */;
@ -210,8 +223,8 @@ CODESTARTparse
/* try to see if it is slighly malformed - HP procurve seems to do that sometimes */
++p2parse; /* move over space */
--lenMsg;
if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg, NO_PARSE3164_TZSTRING,
pInst->bDetectYearAfterTimestamp) == RS_RET_OK) {
if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg,
NO_PARSE3164_TZSTRING, pInst->bDetectYearAfterTimestamp) == RS_RET_OK) {
/* indeed, we got it! */
/* we are done - parse pointer is moved by ParseTIMESTAMP3164 */;
} else {/* parse pointer needs to be restored, as we moved it off-by-one
@ -361,8 +374,7 @@ CODESTARTparse
finalize_it:
if (pInst->bRemoveMsgFirstSpace && *p2parse == ' ') {
/* Bypass first space found in MSG part
*/
/* Bypass first space found in MSG part */
p2parse++;
lenMsg--;
}