From 16db662d9fac0f9636eea873d690a629641be5bc Mon Sep 17 00:00:00 2001
From: Rainer Gerhards <rgerhards@adiscon.com>
Date: Tue, 2 Feb 2016 08:52:31 +0100
Subject: [PATCH] imuxsock: add support for rulesets

ruleset parameter is added at listener level
 
implements https://github.com/rsyslog/rsyslog/issues/765
---
 plugins/imuxsock/imuxsock.c                   | 32 ++++++++++++++++++++++++---
 tests/Makefile.am                             |  3 +++
 tests/imuxsock_logger_ruleset.sh              | 20 +++++++++++++++++
 tests/testsuites/imuxsock_logger_ruleset.conf | 13 +++++++++++
 4 files changed, 65 insertions(+), 3 deletions(-)
 create mode 100755 tests/imuxsock_logger_ruleset.sh
 create mode 100644 tests/testsuites/imuxsock_logger_ruleset.conf

diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c
index d99bed8..140ec68 100644
--- a/plugins/imuxsock/imuxsock.c
+++ b/plugins/imuxsock/imuxsock.c
@@ -50,6 +50,7 @@
 #include "parser.h"
 #include "prop.h"
 #include "debug.h"
+#include "ruleset.h"
 #include "unlimited_select.h"
 #include "sd-daemon.h"
 #include "statsobj.h"
@@ -98,6 +99,7 @@ DEFobjCurrIf(net)
 DEFobjCurrIf(parser)
 DEFobjCurrIf(datetime)
 DEFobjCurrIf(statsobj)
+DEFobjCurrIf(ruleset)
 
 
 statsobj_t *modStats;
@@ -146,6 +148,7 @@ typedef struct lstn_s {
 	sbool bDiscardOwnMsgs;	/* discard messages that originated from ourselves */
 	sbool bUseSysTimeStamp;	/* use timestamp from system (instead of from message) */
 	sbool bUnlink;		/* unlink&re-create socket at start and end of processing */
+	ruleset_t *pRuleset;
 } lstn_t;
 static lstn_t *listeners;
 
@@ -204,6 +207,9 @@ struct instanceConf_s {
 	int bParseTrusted;		/* parse trusted properties */
 	sbool bDiscardOwnMsgs;		/* discard messages that originated from our own pid? */
 	sbool bUnlink;
+	uchar *pszBindRuleset;		/* name of ruleset to bind to */
+	ruleset_t *pBindRuleset;	/* ruleset to bind listener to (use system default if unspecified) */
+
 	struct instanceConf_s *next;
 };
 
@@ -263,6 +269,7 @@ static struct cnfparamdescr inppdescr[] = {
 	{ "usesystimestamp", eCmdHdlrBinary, 0 },
 	{ "annotate", eCmdHdlrBinary, 0 },
 	{ "usepidfromsystem", eCmdHdlrBinary, 0 },
+	{ "ruleset", eCmdHdlrString, 0 },
 	{ "ratelimit.interval", eCmdHdlrInt, 0 },
 	{ "ratelimit.burst", eCmdHdlrInt, 0 },
 	{ "ratelimit.severity", eCmdHdlrInt, 0 }
@@ -273,8 +280,7 @@ static struct cnfparamblk inppblk =
 	  inppdescr
 	};
 
-/* we do not use this, because we do not bind to a ruleset so far
- * enable when this is changed: #include "im-helper.h" */ /* must be included AFTER the type definitions! */
+#include "im-helper.h" /* must be included AFTER the type definitions! */
 
 static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
 
@@ -290,6 +296,8 @@ createInstance(instanceConf_t **pinst)
 	CHKmalloc(inst = MALLOC(sizeof(instanceConf_t)));
 	inst->sockName = NULL;
 	inst->pLogHostName = NULL;
+	inst->pszBindRuleset = NULL;
+	inst->pBindRuleset = NULL;
 	inst->ratelimitInterval = DFLT_ratelimitInterval;
 	inst->ratelimitBurst = DFLT_ratelimitBurst;
 	inst->ratelimitSeverity = DFLT_ratelimitSeverity;
@@ -405,6 +413,7 @@ addListner(instanceConf_t *inst)
 	listeners[nfd].bUnlink = inst->bUnlink;
 	listeners[nfd].bWritePid = inst->bWritePid;
 	listeners[nfd].bUseSysTimeStamp = inst->bUseSysTimeStamp;
+	listeners[nfd].pRuleset = inst->pBindRuleset;
 	CHKiRet(ratelimitNew(&listeners[nfd].dflt_ratelimiter, "imuxsock", NULL));
 	ratelimitSetLinuxLike(listeners[nfd].dflt_ratelimiter,
 			      listeners[nfd].ratelimitInterval,
@@ -940,6 +949,7 @@ SubmitMsg(uchar *pRcv, int lenRcv, lstn_t *pLstn, struct ucred *cred, struct tim
 
 	MsgSetRcvFrom(pMsg, pLstn->hostName == NULL ? glbl.GetLocalHostNameProp() : pLstn->hostName);
 	CHKiRet(MsgSetRcvFromIP(pMsg, pLocalHostIP));
+	MsgSetRuleset(pMsg, pLstn->pRuleset);
 	ratelimitAddMsg(ratelimiter, NULL, pMsg);
 	STATSCOUNTER_INC(ctrSubmit, mutCtrSubmit);
 finalize_it:
@@ -1252,6 +1262,8 @@ CODESTARTnewInpInst
 			inst->bAnnotate = (int) pvals[i].val.d.n;
 		} else if(!strcmp(inppblk.descr[i].name, "usepidfromsystem")) {
 			inst->bWritePid = (int) pvals[i].val.d.n;
+		} else if(!strcmp(inppblk.descr[i].name, "ruleset")) {
+			inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
 		} else if(!strcmp(inppblk.descr[i].name, "ratelimit.interval")) {
 			inst->ratelimitInterval = (int) pvals[i].val.d.n;
 		} else if(!strcmp(inppblk.descr[i].name, "ratelimit.burst")) {
@@ -1295,8 +1307,22 @@ CODESTARTendCnfLoad
 ENDendCnfLoad
 
 
+/* function to generate error message if framework does not find requested ruleset */
+static void
+std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst)
+{
+	errmsg.LogError(0, NO_ERRCODE, "imuxsock: ruleset '%s' for socket %s not found - "
+			"using default ruleset instead", inst->pszBindRuleset,
+			inst->sockName);
+}
+
+
 BEGINcheckCnf
+	instanceConf_t *inst;
 CODESTARTcheckCnf
+for(inst = pModConf->root ; inst != NULL ; inst = inst->next) {
+		std_checkRuleset(pModConf, inst);
+	}
 ENDcheckCnf
 
 
@@ -1351,6 +1377,7 @@ CODESTARTfreeCnf
 	free(pModConf->pLogSockName);
 	for(inst = pModConf->root ; inst != NULL ; ) {
 		free(inst->sockName);
+		free(inst->pszBindRuleset);
 		free(inst->pLogHostName);
 		del = inst;
 		inst = inst->next;
@@ -1479,6 +1506,7 @@ CODESTARTmodExit
 	objRelease(prop, CORE_COMPONENT);
 	objRelease(statsobj, CORE_COMPONENT);
 	objRelease(datetime, CORE_COMPONENT);
+	objRelease(ruleset, CORE_COMPONENT);
 ENDmodExit
 
 
@@ -1540,6 +1568,7 @@ CODEmodInit_QueryRegCFSLineHdlr
 	CHKiRet(objUse(statsobj, CORE_COMPONENT));
 	CHKiRet(objUse(datetime, CORE_COMPONENT));
 	CHKiRet(objUse(parser, CORE_COMPONENT));
+	CHKiRet(objUse(ruleset, CORE_COMPONENT));
 
 	DBGPRINTF("imuxsock version %s initializing\n", PACKAGE_VERSION);
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b5d6f53..0c722c1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -58,6 +58,7 @@ TESTS +=  \
 	imuxsock_traillf_root.sh \
 	imuxsock_ccmiddle_root.sh \
 	udp-msgreduc-vg.sh \
+	imuxsock_logger_ruleset.sh \
 	udp-msgreduc-orgmsg-vg.sh \
 	queue-persist.sh \
 	discard-rptdmsg.sh \
@@ -558,6 +559,8 @@ EXTRA_DIST= 1.rstest 2.rstest 3.rstest err1.rstest \
 	   imuxsock_ccmiddle_root.sh \
 	   testsuites/imuxsock_ccmiddle_root.conf \
 	   resultdata/imuxsock_ccmiddle.log \
+	   imuxsock_logger_ruleset.sh \
+	   testsuites/imuxsock_logger_ruleset.conf \
 	   testsuites/mysql-truncate.sql \
 	   testsuites/mysql-select-msg.sql \
 	   libdbi-basic.sh \
diff --git a/tests/imuxsock_logger_ruleset.sh b/tests/imuxsock_logger_ruleset.sh
new file mode 100644
index 0000000..666eb34
--- /dev/null
+++ b/tests/imuxsock_logger_ruleset.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+# rgerhards, 2016-02-02 released under ASL 2.0
+echo \[imuxsock_logger_ruleset.sh\]: test imuxsock with ruleset definition
+. $srcdir/diag.sh init
+. $srcdir/diag.sh startup imuxsock_logger_ruleset.conf
+# send a message with trailing LF
+logger -d -u testbench_socket test
+# the sleep below is needed to prevent too-early termination of rsyslogd
+./msleep 100
+. $srcdir/diag.sh shutdown-when-empty # shut down rsyslogd when done processing messages
+. $srcdir/diag.sh wait-shutdown	# we need to wait until rsyslogd is finished!
+cmp rsyslog.out.log $srcdir/resultdata/imuxsock_logger.log
+  echo \"`cat rsyslog.out.log`\"
+if [ ! $? -eq 0 ]; then
+  echo "imuxsock_logger.sh failed"
+  echo contents of rsyslog.out.log:
+  echo \"`cat rsyslog.out.log`\"
+  exit 1
+fi;
+. $srcdir/diag.sh exit
diff --git a/tests/testsuites/imuxsock_logger_ruleset.conf b/tests/testsuites/imuxsock_logger_ruleset.conf
new file mode 100644
index 0000000..8a1760d
--- /dev/null
+++ b/tests/testsuites/imuxsock_logger_ruleset.conf
@@ -0,0 +1,13 @@
+# rgerhards, 2016-02-02
+$IncludeConfig diag-common.conf
+
+module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off")
+input(	type="imuxsock" socket="testbench_socket"
+	useSpecialParser="off"
+	ruleset="testruleset"
+	parseHostname="on")
+template(name="outfmt" type="string" string="%msg:%\n")
+
+ruleset(name="testruleset") {
+	./rsyslog.out.log;outfmt
+}
-- 
2.6.2

