summaryrefslogtreecommitdiffstats
path: root/plugins/omruleset/omruleset.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/omruleset/omruleset.c')
-rw-r--r--plugins/omruleset/omruleset.c274
1 files changed, 274 insertions, 0 deletions
diff --git a/plugins/omruleset/omruleset.c b/plugins/omruleset/omruleset.c
new file mode 100644
index 0000000..fd0bcef
--- /dev/null
+++ b/plugins/omruleset/omruleset.c
@@ -0,0 +1,274 @@
+/* omruleset.c
+ * This is a very special output module. It permits to pass a message object
+ * to another rule set. While this is a very simple action, it enables very
+ * complex configurations, e.g. it supports high-speed "and" conditions, sending
+ * data to the same file in a non-racy way, include functionality as well as
+ * some high-performance optimizations (in case the rule sets have the necessary
+ * queue definitions). So while this code is small, it is pretty important.
+ *
+ * NOTE: read comments in module-template.h for details on the calling interface!
+ *
+ * File begun on 2009-11-02 by RGerhards
+ *
+ * Copyright 2009-2016 Rainer Gerhards and Adiscon GmbH.
+ *
+ * This file is part of rsyslog.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * -or-
+ * see COPYING.ASL20 in the source distribution
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "config.h"
+#include "rsyslog.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include "conf.h"
+#include "syslogd-types.h"
+#include "template.h"
+#include "module-template.h"
+#include "errmsg.h"
+#include "ruleset.h"
+#include "cfsysline.h"
+#include "dirty.h"
+
+MODULE_TYPE_OUTPUT
+MODULE_TYPE_NOKEEP
+MODULE_CNFNAME("omruleset")
+
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
+
+/* static data */
+DEFobjCurrIf(ruleset);
+
+/* internal structures
+ */
+DEF_OMOD_STATIC_DATA
+
+/* config variables */
+
+
+typedef struct _instanceData {
+ ruleset_t *pRuleset; /* ruleset to enqueue to */
+ uchar *pszRulesetName; /* primarily for debugging/display purposes */
+} instanceData;
+
+typedef struct wrkrInstanceData {
+ instanceData *pData;
+} wrkrInstanceData_t;
+
+typedef struct configSettings_s {
+ ruleset_t *pRuleset; /* ruleset to enqueue message to (NULL = Default, not recommended) */
+ uchar *pszRulesetName;
+} configSettings_t;
+static configSettings_t cs;
+
+BEGINinitConfVars /* (re)set config variables to default values */
+CODESTARTinitConfVars
+ resetConfigVariables(NULL, NULL);
+ENDinitConfVars
+
+
+BEGINcreateInstance
+CODESTARTcreateInstance
+ENDcreateInstance
+
+
+BEGINcreateWrkrInstance
+CODESTARTcreateWrkrInstance
+ENDcreateWrkrInstance
+
+
+BEGINisCompatibleWithFeature
+CODESTARTisCompatibleWithFeature
+ENDisCompatibleWithFeature
+
+
+BEGINfreeWrkrInstance
+CODESTARTfreeWrkrInstance
+ENDfreeWrkrInstance
+
+
+BEGINfreeInstance
+CODESTARTfreeInstance
+ free(pData->pszRulesetName);
+ENDfreeInstance
+
+
+BEGINdbgPrintInstInfo
+CODESTARTdbgPrintInstInfo
+ dbgprintf("omruleset target %s[%p]\n", (char*) pData->pszRulesetName, pData->pRuleset);
+ENDdbgPrintInstInfo
+
+
+BEGINtryResume
+CODESTARTtryResume
+ENDtryResume
+
+/* Note that we change the flow control type to "no delay", because at this point in
+ * rsyslog procesing we can not really slow down the producer any longer, as we already
+ * work off a queue. So a delay would just block out execution for longer than needed.
+ */
+BEGINdoAction_NoStrings
+ smsg_t **ppMsg = (smsg_t **) pMsgData;
+ smsg_t *pMsg;
+CODESTARTdoAction
+ CHKmalloc(pMsg = MsgDup(ppMsg[0]));
+ DBGPRINTF(":omruleset: forwarding message %p to ruleset %s[%p]\n", pMsg,
+ (char*) pWrkrData->pData->pszRulesetName, pWrkrData->pData->pRuleset);
+ MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY);
+ MsgSetRuleset(pMsg, pWrkrData->pData->pRuleset);
+ /* Note: we intentionally use submitMsg2() here, as we process messages
+ * that were already run through the rate-limiter. So it is (at least)
+ * questionable if they were rate-limited again.
+ */
+ submitMsg2(pMsg);
+finalize_it:
+ENDdoAction
+
+/* set the ruleset name */
+static rsRetVal
+setRuleset(void __attribute__((unused)) *pVal, uchar *pszName)
+{
+ rsRetVal localRet;
+ DEFiRet;
+
+ localRet = ruleset.GetRuleset(ourConf, &cs.pRuleset, pszName);
+ if(localRet == RS_RET_NOT_FOUND) {
+ LogError(0, RS_RET_RULESET_NOT_FOUND, "error: ruleset '%s' not found - ignored", pszName);
+ }
+ CHKiRet(localRet);
+ cs.pszRulesetName = pszName; /* save for later display purposes */
+
+finalize_it:
+ if(iRet != RS_RET_OK) { /* cleanup needed? */
+ free(pszName);
+ }
+ RETiRet;
+}
+
+
+BEGINparseSelectorAct
+ int iTplOpts;
+CODESTARTparseSelectorAct
+CODE_STD_STRING_REQUESTparseSelectorAct(1)
+ /* first check if this config line is actually for us */
+ if(strncmp((char*) p, ":omruleset:", sizeof(":omruleset:") - 1)) {
+ ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
+ }
+
+ if(cs.pRuleset == NULL) {
+ LogError(0, RS_RET_NO_RULESET, "error: no ruleset was specified, use "
+ "$ActionOmrulesetRulesetName directive first!");
+ ABORT_FINALIZE(RS_RET_NO_RULESET);
+ }
+
+ /* ok, if we reach this point, we have something for us */
+ p += sizeof(":omruleset:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
+ CHKiRet(createInstance(&pData));
+
+ LogMsg(0, RS_RET_DEPRECATED, LOG_WARNING,
+ "warning: omruleset is deprecated, consider "
+ "using the 'call' statement instead");
+
+ /* check if a non-standard template is to be applied */
+ if(*(p-1) == ';')
+ --p;
+ iTplOpts = OMSR_TPL_AS_MSG;
+ /* we call the message below because we need to call it via our interface definition. However,
+ * the format specified (if any) is always ignored.
+ */
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, iTplOpts, (uchar*) "RSYSLOG_FileFormat"));
+ pData->pRuleset = cs.pRuleset;
+ pData->pszRulesetName = cs.pszRulesetName;
+ cs.pRuleset = NULL;
+/* re-set, because there is a high risk of unwanted behavior if we leave it in! */
+ cs.pszRulesetName = NULL;
+/* note: we must not free, as we handed over this pointer to the instanceDat to the instanceDataa! */
+CODE_STD_FINALIZERparseSelectorAct
+ENDparseSelectorAct
+
+
+BEGINmodExit
+CODESTARTmodExit
+ free(cs.pszRulesetName);
+ objRelease(ruleset, CORE_COMPONENT);
+ENDmodExit
+
+
+BEGINqueryEtryPt
+CODESTARTqueryEtryPt
+CODEqueryEtryPt_STD_OMOD_QUERIES
+CODEqueryEtryPt_STD_OMOD8_QUERIES
+CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES
+ENDqueryEtryPt
+
+
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ cs.pRuleset = NULL;
+ free(cs.pszRulesetName);
+ cs.pszRulesetName = NULL;
+ RETiRet;
+}
+
+
+BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bMsgPassingSupported; /* does core support template passing as an array? */
+CODESTARTmodInit
+INITLegCnfVars
+ *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
+CODEmodInit_QueryRegCFSLineHdlr
+ /* check if the rsyslog core supports parameter passing code */
+ bMsgPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts", &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ /* found entry point, so let's see if core supports msg passing */
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_MSG)
+ bMsgPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, what is not acceptable */
+ }
+
+ if(!bMsgPassingSupported) {
+ DBGPRINTF("omruleset: msg-passing is not supported by rsyslog core, can not continue.\n");
+ ABORT_FINALIZE(RS_RET_NO_MSG_PASSING);
+ }
+
+ CHKiRet(objUse(ruleset, CORE_COMPONENT));
+
+ LogMsg(0, RS_RET_DEPRECATED, LOG_WARNING,
+ "warning: omruleset is deprecated, consider "
+ "using the 'call' statement instead");
+
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomrulesetrulesetname", 0, eCmdHdlrGetWord,
+ setRuleset, NULL, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
+ENDmodInit
+
+/* vi:set ai:
+ */