diff options
Diffstat (limited to 'plugins/omruleset/omruleset.c')
-rw-r--r-- | plugins/omruleset/omruleset.c | 274 |
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: + */ |