/* mmsnmptrapd.c
* This is a message modification module. It takes messages generated
* from snmptrapd and modifies them so that the look like they
* originated from the real originator.
*
* NOTE: read comments in module-template.h for details on the calling interface!
*
* File begun on 2011-05-05 by RGerhards
*
* Copyright 2011 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of rsyslog.
*
* Rsyslog is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rsyslog is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Rsyslog. If not, see .
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
*/
#include "config.h"
#include "rsyslog.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "conf.h"
#include "msg.h"
#include "syslogd-types.h"
#include "template.h"
#include "module-template.h"
#include "errmsg.h"
#include "cfsysline.h"
#include "unicode-helper.h"
#include "dirty.h"
MODULE_TYPE_OUTPUT
MODULE_TYPE_NOKEEP
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal);
/* static data */
DEFobjCurrIf(errmsg);
/* internal structures
*/
DEF_OMOD_STATIC_DATA
typedef struct _instanceData {
uchar *pszTagName;
uchar *pszTagID; /* chaced: name plus trailig shlash (for compares) */
int lenTagID; /* cached length of tag ID, for performance reasons */
} instanceData;
typedef struct configSettings_s {
uchar *pszTagName; /**< name of tag start value that indicates snmptrapd initiated message */
} configSettings_t;
configSettings_t cs;
//TODO: enable for v6
#if 0
SCOPING_SUPPORT; /* must be set AFTER configSettings_t is defined */
BEGINinitConfVars /* (re)set config variables to default values */
CODESTARTinitConfVars
cs.pszTagName = NULL;
resetConfigVariables(NULL, NULL);
ENDinitConfVars
#endif
BEGINcreateInstance
CODESTARTcreateInstance
ENDcreateInstance
BEGINisCompatibleWithFeature
CODESTARTisCompatibleWithFeature
ENDisCompatibleWithFeature
BEGINfreeInstance
CODESTARTfreeInstance
free(pData->pszTagName);
free(pData->pszTagID);
ENDfreeInstance
BEGINdbgPrintInstInfo
CODESTARTdbgPrintInstInfo
dbgprintf("mmsnmptrapd\n");
ENDdbgPrintInstInfo
BEGINtryResume
CODESTARTtryResume
ENDtryResume
/* get string up to the next SP or '/'. Stops at max size.
* dst, lenDst (receive buffer) must be given. lenDst is
* max length on entry and actual length on exit.
*/
static int
getTagComponent(uchar *tag, uchar *dst, int *lenDst)
{
int end = *lenDst - 1; /* -1 for NUL-char! */
int i;
i = 0;
dbgprintf("XXXX: getTagComponent tag on input: '%s'(%p)\n", tag, tag);
if(tag[i] != '/')
goto done;
++tag;
while(i < end && tag[i] != '\0' && tag[i] != ' ' && tag[i] != '/') {
dst[i] = tag[i];
++i;
}
dst[i] = '\0';
dbgprintf("XXXX: getTagComponent dst on output: '%s', len %d\n", dst, i);
*lenDst = i;
done:
return i;
}
BEGINdoAction
int lenTAG;
int lenSever;
int lenHost;
msg_t *pMsg;
uchar *pszTag;
uchar pszSever[512];
uchar pszHost[512];
CODESTARTdoAction
pMsg = (msg_t*) ppString[0];
dbgprintf("XXXX: mmsnmptrapd called with pMsg %p\n", pMsg);
getTAG(pMsg, &pszTag, &lenTAG);
if(strncmp((char*)pszTag, (char*)pData->pszTagID, pData->lenTagID)) {
DBGPRINTF("tag '%s' not matching, mmsnmptrapd ignoring this message\n",
pszTag);
FINALIZE;
}
lenSever = sizeof(pszSever);
dbgprintf("XXXX: pszTag: '%s', lenID %d\n", pszTag, pData->lenTagID);
getTagComponent(pszTag+pData->lenTagID-1, pszSever, &lenSever);
lenHost = sizeof(pszHost);
getTagComponent(pszTag+pData->lenTagID+lenSever, pszHost, &lenHost);
dbgprintf("XXXX: mmsnmptrapd sever '%s'(%d), host '%s'(%d)\n", pszSever, lenSever, pszHost,lenHost);
if(pszHost[lenHost-1] == ':') {
pszHost[lenHost-1] = '\0';
--lenHost;
}
/* now apply new settings */
MsgSetTAG(pMsg, pData->pszTagName, pData->lenTagID);
MsgSetHOSTNAME(pMsg, pszHost, lenHost);
finalize_it:
ENDdoAction
BEGINparseSelectorAct
CODESTARTparseSelectorAct
CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* first check if this config line is actually for us */
if(strncmp((char*) p, ":mmsnmptrapd:", sizeof(":mmsnmptrapd:") - 1)) {
ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED);
}
/* ok, if we reach this point, we have something for us */
p += sizeof(":mmsnmptrapd:") - 1; /* eat indicator sequence (-1 because of '\0'!) */
CHKiRet(createInstance(&pData));
/* check if a non-standard template is to be applied */
if(*(p-1) == ';')
--p;
/* we call the function 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, OMSR_TPL_AS_MSG, (uchar*) "RSYSLOG_FileFormat"));
/* finally build the instance */
if(cs.pszTagName == NULL) {
pData->pszTagName = (uchar*) strdup("snmptrapd:");
pData->pszTagID = (uchar*) strdup("snmptrapd/");
} else {
int lenTag = ustrlen(cs.pszTagName);
/* new tag value (with colon at the end) */
CHKmalloc(pData->pszTagName = MALLOC(lenTag + 2));
memcpy(pData->pszTagName, cs.pszTagName, lenTag);
memcpy(pData->pszTagName+lenTag, ":", 2);
/* tag ID for comparisions */
CHKmalloc(pData->pszTagID = MALLOC(lenTag + 2));
memcpy(pData->pszTagID, cs.pszTagName, lenTag);
memcpy(pData->pszTagID+lenTag, "/", 2);
free(cs.pszTagName); /* no longer needed */
}
pData->lenTagID = ustrlen(pData->pszTagID);
/* all config vars auto-reset! */
cs.pszTagName = NULL;
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
BEGINmodExit
CODESTARTmodExit
objRelease(errmsg, CORE_COMPONENT);
ENDmodExit
BEGINqueryEtryPt
CODESTARTqueryEtryPt
CODEqueryEtryPt_STD_OMOD_QUERIES
ENDqueryEtryPt
/* Reset config variables for this module to default values.
*/
static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
{
DEFiRet;
free(cs.pszTagName);
cs.pszTagName = NULL;
RETiRet;
}
BEGINmodInit()
rsRetVal localRet;
rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
unsigned long opts;
int bMsgPassingSupported;
CODESTARTmodInit
//TODO v6: add SCOPINGmodInit
*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, not acceptable */
}
if(!bMsgPassingSupported) {
DBGPRINTF("mmsnmptrapd: msg-passing is not supported by rsyslog core, "
"can not continue.\n");
ABORT_FINALIZE(RS_RET_NO_MSG_PASSING);
}
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"mmsnmptrapdtag", 0, eCmdHdlrInt,
NULL, &cs.pszTagName, STD_LOADABLE_MODULE_ID));
CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
/* vi:set ai:
*/