diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | grammar/rainerscript.c | 129 | ||||
-rw-r--r-- | plugins/imfile/imfile.c | 550 | ||||
-rw-r--r-- | plugins/imptcp/imptcp.c | 135 | ||||
-rw-r--r-- | plugins/imrelp/imrelp.c | 86 | ||||
-rw-r--r-- | plugins/imtcp/imtcp.c | 98 | ||||
-rw-r--r-- | plugins/imudp/imudp.c | 117 | ||||
-rw-r--r-- | plugins/imuxsock/imuxsock.c | 129 | ||||
-rw-r--r-- | runtime/module-template.h | 28 | ||||
-rw-r--r-- | runtime/modules.c | 70 | ||||
-rw-r--r-- | runtime/modules.h | 5 | ||||
-rw-r--r-- | runtime/rsconf.c | 58 | ||||
-rw-r--r-- | runtime/rsyslog.h | 1 | ||||
-rw-r--r-- | runtime/typedefs.h | 2 |
14 files changed, 1181 insertions, 241 deletions
@@ -1,4 +1,5 @@ --------------------------------------------------------------------------- +<<<<<<< HEAD Version 7.1.5 [devel] 2012-09-25 - implemented RainerScript prifield() function - implemented RainerScript field() function @@ -27,6 +28,17 @@ Version 7.1.4 [devel] 2012-09-19 --------------------------------------------------------------------------- Version 7.1.3 [devel] 2012-09-17 - introduced "set" and "unset" config statements +======= +Version 6.5.1 [devel] 2012-08-?? +- imfile ported to new v6 config interface +- imfile now supports config parameter for maximum number of submits + which is a fine-tuning parameter in regard to input baching +- added pure JSON output plugin parameter passing mode +- ommongodb now supports templates +- bugfix: imtcp could abort on exit due to invalid free() +- bugfix: remove invalid socket option call from imuxsock + Thanks to Cristian Ionescu-Idbohrn and Jonny Törnbom +>>>>>>> 53df5066688c8472a9f7be5c86bbc253378e6572 - bugfix: missing support for escape sequences in RainerScript only \' was supported. Now the usual set is supported. Note that v5 used \x as escape where x was any character (e.g. "\n" meant "n" and NOT @@ -81,6 +93,8 @@ Version 6.5.1 [devel] 2012-08-?? these were one-time memory leaks during startup, so they did NOT grow during runtime - bugfix: config validation run did not always return correct return state +- bugfix: config errors did not always cause statement to fail + This could lead to startup with invalid parameters. --------------------------------------------------------------------------- Version 6.5.0 [devel] 2012-08-28 - imrelp now supports non-cancel thread termination diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index a2455755..1a14b212 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -323,13 +323,14 @@ nvlstChkUnused(struct nvlst *lst) } -static inline void +static inline int doGetSize(struct nvlst *valnode, struct cnfparamdescr *param, struct cnfparamvals *val) { unsigned char *c; es_size_t i; long long n; + int r; c = es_getBufAddr(valnode->val.d.estr); n = 0; i = 0; @@ -363,17 +364,21 @@ doGetSize(struct nvlst *valnode, struct cnfparamdescr *param, if(i == es_strlen(valnode->val.d.estr)) { val->val.datatype = 'N'; val->val.d.n = n; + r = 1; } else { parser_errmsg("parameter '%s' does not contain a valid size", param->name); + r = 0; } + return r; } -static inline void +static inline int doGetBinary(struct nvlst *valnode, struct cnfparamdescr *param, struct cnfparamvals *val) { + int r = 1; val->val.datatype = 'N'; if(!es_strbufcmp(valnode->val.d.estr, (unsigned char*) "on", 2)) { val->val.d.n = 1; @@ -383,14 +388,17 @@ doGetBinary(struct nvlst *valnode, struct cnfparamdescr *param, parser_errmsg("parameter '%s' must be \"on\" or \"off\" but " "is neither. Results unpredictable.", param->name); val->val.d.n = 0; + r = 0; } + return r; } -static inline void +static inline int doGetQueueType(struct nvlst *valnode, struct cnfparamdescr *param, struct cnfparamvals *val) { char *cstr; + int r = 1; if(!es_strcasebufcmp(valnode->val.d.estr, (uchar*)"fixedarray", 10)) { val->val.d.n = QUEUETYPE_FIXED_ARRAY; } else if(!es_strcasebufcmp(valnode->val.d.estr, (uchar*)"linkedlist", 10)) { @@ -404,15 +412,17 @@ doGetQueueType(struct nvlst *valnode, struct cnfparamdescr *param, parser_errmsg("param '%s': unknown queue type: '%s'", param->name, cstr); free(cstr); + r = 0; } val->val.datatype = 'N'; + return r; } /* A file create-mode must be a four-digit octal number * starting with '0'. */ -static inline void +static inline int doGetFileCreateMode(struct nvlst *valnode, struct cnfparamdescr *param, struct cnfparamvals *val) { @@ -441,13 +451,15 @@ doGetFileCreateMode(struct nvlst *valnode, struct cnfparamdescr *param, param->name, cstr); free(cstr); } + return fmtOK; } -static inline void +static inline int doGetGID(struct nvlst *valnode, struct cnfparamdescr *param, struct cnfparamvals *val) { char *cstr; + int r; struct group *resultBuf; struct group wrkBuf; char stringBuf[2048]; /* 2048 has been proven to be large enough */ @@ -457,20 +469,24 @@ doGetGID(struct nvlst *valnode, struct cnfparamdescr *param, if(resultBuf == NULL) { parser_errmsg("parameter '%s': ID for group %s could not " "be found", param->name, cstr); + r = 0; } else { val->val.datatype = 'N'; val->val.d.n = resultBuf->gr_gid; dbgprintf("param '%s': uid %d obtained for group '%s'\n", param->name, (int) resultBuf->gr_gid, cstr); + r = 1; } free(cstr); + return r; } -static inline void +static inline int doGetUID(struct nvlst *valnode, struct cnfparamdescr *param, struct cnfparamvals *val) { char *cstr; + int r; struct passwd *resultBuf; struct passwd wrkBuf; char stringBuf[2048]; /* 2048 has been proven to be large enough */ @@ -480,19 +496,22 @@ doGetUID(struct nvlst *valnode, struct cnfparamdescr *param, if(resultBuf == NULL) { parser_errmsg("parameter '%s': ID for user %s could not " "be found", param->name, cstr); + r = 0; } else { val->val.datatype = 'N'; val->val.d.n = resultBuf->pw_uid; dbgprintf("param '%s': uid %d obtained for user '%s'\n", param->name, (int) resultBuf->pw_uid, cstr); + r = 1; } free(cstr); + return r; } /* note: we support all integer formats that es_str2num support, * so hex and octal representations are also valid. */ -static inline void +static inline int doGetInt(struct nvlst *valnode, struct cnfparamdescr *param, struct cnfparamvals *val) { @@ -506,13 +525,47 @@ doGetInt(struct nvlst *valnode, struct cnfparamdescr *param, } val->val.datatype = 'N'; val->val.d.n = n; + return bSuccess; } -static inline void +static inline int +doGetNonNegInt(struct nvlst *valnode, struct cnfparamdescr *param, + struct cnfparamvals *val) +{ + int bSuccess; + + if((bSuccess = doGetInt(valnode, param, val))) { + if(val->val.d.n < 0) { + parser_errmsg("parameter '%s' cannot be less than zero (was %lld)", + param->name, val->val.d.n); + bSuccess = 0; + } + } + return bSuccess; +} + +static inline int +doGetPositiveInt(struct nvlst *valnode, struct cnfparamdescr *param, + struct cnfparamvals *val) +{ + int bSuccess; + + if((bSuccess = doGetInt(valnode, param, val))) { + if(val->val.d.n < 1) { + parser_errmsg("parameter '%s' cannot be less than one (was %lld)", + param->name, val->val.d.n); + bSuccess = 0; + } + } + return bSuccess; +} + +static inline int doGetWord(struct nvlst *valnode, struct cnfparamdescr *param, struct cnfparamvals *val) { es_size_t i; + int r = 1; unsigned char *c; val->val.datatype = 'S'; val->val.d.estr = es_newStr(32); @@ -524,30 +577,36 @@ doGetWord(struct nvlst *valnode, struct cnfparamdescr *param, parser_errmsg("parameter '%s' contains whitespace, which is not " "permitted - data after first whitespace ignored", param->name); + r = 0; } + return r; } -static inline void +static inline int doGetChar(struct nvlst *valnode, struct cnfparamdescr *param, struct cnfparamvals *val) { + int r = 1; if(es_strlen(valnode->val.d.estr) != 1) { parser_errmsg("parameter '%s' must contain exactly one character " "but contains %d - cannot be processed", param->name, es_strlen(valnode->val.d.estr)); + r = 0; } val->val.datatype = 'S'; val->val.d.estr = es_strdup(valnode->val.d.estr); + return r; } /* get a single parameter according to its definition. Helper to - * nvlstGetParams. + * nvlstGetParams. returns 1 if success, 0 otherwise */ -static inline void +static inline int nvlstGetParam(struct nvlst *valnode, struct cnfparamdescr *param, struct cnfparamvals *val) { uchar *cstr; + int r; dbgprintf("XXXX: in nvlstGetParam, name '%s', type %d, valnode->bUsed %d\n", param->name, (int) param->type, valnode->bUsed); @@ -555,56 +614,68 @@ nvlstGetParam(struct nvlst *valnode, struct cnfparamdescr *param, val->bUsed = 1; switch(param->type) { case eCmdHdlrQueueType: - doGetQueueType(valnode, param, val); + r = doGetQueueType(valnode, param, val); break; case eCmdHdlrUID: - doGetUID(valnode, param, val); + r = doGetUID(valnode, param, val); break; case eCmdHdlrGID: - doGetGID(valnode, param, val); + r = doGetGID(valnode, param, val); break; case eCmdHdlrBinary: - doGetBinary(valnode, param, val); + r = doGetBinary(valnode, param, val); break; case eCmdHdlrFileCreateMode: - doGetFileCreateMode(valnode, param, val); + r = doGetFileCreateMode(valnode, param, val); break; case eCmdHdlrInt: - doGetInt(valnode, param, val); + r = doGetInt(valnode, param, val); + break; + case eCmdHdlrNonNegInt: + r = doGetPositiveInt(valnode, param, val); + break; + case eCmdHdlrPositiveInt: + r = doGetPositiveInt(valnode, param, val); break; case eCmdHdlrSize: - doGetSize(valnode, param, val); + r = doGetSize(valnode, param, val); break; case eCmdHdlrGetChar: - doGetChar(valnode, param, val); + r = doGetChar(valnode, param, val); break; case eCmdHdlrFacility: cstr = (uchar*) es_str2cstr(valnode->val.d.estr, NULL); val->val.datatype = 'N'; val->val.d.n = decodeSyslogName(cstr, syslogFacNames); free(cstr); + r = 1; break; case eCmdHdlrSeverity: cstr = (uchar*) es_str2cstr(valnode->val.d.estr, NULL); val->val.datatype = 'N'; val->val.d.n = decodeSyslogName(cstr, syslogPriNames); free(cstr); + r = 1; break; case eCmdHdlrGetWord: - doGetWord(valnode, param, val); + r = doGetWord(valnode, param, val); break; case eCmdHdlrString: val->val.datatype = 'S'; val->val.d.estr = es_strdup(valnode->val.d.estr); + r = 1; break; case eCmdHdlrGoneAway: parser_errmsg("parameter '%s' is no longer supported", param->name); + r = 1; /* this *is* valid! */ break; default: dbgprintf("error: invalid param type\n"); + r = 0; break; } + return r; } @@ -619,6 +690,8 @@ nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params, struct cnfparamvals *vals) { int i; + int bValsWasNULL; + int bInError = 0; struct nvlst *valnode; struct cnfparamdescr *param; @@ -630,9 +703,12 @@ nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params, } if(vals == NULL) { + bValsWasNULL = 1; if((vals = calloc(params->nParams, sizeof(struct cnfparamvals))) == NULL) return NULL; + } else { + bValsWasNULL = 0; } for(i = 0 ; i < params->nParams ; ++i) { @@ -644,8 +720,19 @@ nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params, "one instance is ignored. Fix config", param->name); continue; } - nvlstGetParam(valnode, param, vals + i); + if(!nvlstGetParam(valnode, param, vals + i)) { + bInError = 1; + } } + + + if(bInError) { + if(bValsWasNULL) + cnfparamvalsDestruct(vals, params); + vals = NULL; + } + +dbgprintf("DDDD: vals %p\n", vals); return vals; } diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c index 440f5991..462a5e78 100644 --- a/plugins/imfile/imfile.c +++ b/plugins/imfile/imfile.c @@ -64,7 +64,11 @@ DEFobjCurrIf(strm) DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) -#define NUM_MULTISUB 1024 /* max number of submits -- TODO: make configurable */ +static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */ + +#define NUM_MULTISUB 1024 /* default max number of submits */ +#define DFLT_PollInterval 10 + typedef struct fileInfo_s { uchar *pszFileName; uchar *pszTag; @@ -81,25 +85,49 @@ typedef struct fileInfo_s { multi_submit_t multiSub; } fileInfo_t; +static struct configSettings_s { + uchar *pszFileName; + uchar *pszFileTag; + uchar *pszStateFile; + uchar *pszBindRuleset; + int iPollInterval; + int iPersistStateInterval; /* how often if state file to be persisted? (default 0->never) */ + int iFacility; /* local0 */ + int iSeverity; /* notice, as of rfc 3164 */ + int readMode; /* mode to use for ReadMultiLine call */ + int maxLinesAtOnce; /* how many lines to process in a row? */ + ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ +} cs; + +struct instanceConf_s { + uchar *pszFileName; + uchar *pszTag; + uchar *pszStateFile; + uchar *pszBindRuleset; + int nMultiSub; + int iPersistStateInterval; + int iFacility; + int iSeverity; + int readMode; + int maxLinesAtOnce; + ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ + struct instanceConf_s *next; +}; + /* forward definitions */ static rsRetVal persistStrmState(fileInfo_t *pInfo); +static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal); /* config variables */ struct modConfData_s { - EMPTY_STRUCT; + rsconf_t *pConf; /* our overall config object */ + int iPollInterval; /* number of seconds to sleep when there was no file activity */ + instanceConf_t *root, *tail; + sbool configSetViaV2Method; }; - -static uchar *pszFileName = NULL; -static uchar *pszFileTag = NULL; -static uchar *pszStateFile = NULL; -static int iPollInterval = 10; /* number of seconds to sleep when there was no file activity */ -static int iPersistStateInterval = 0; /* how often if state file to be persisted? (default 0->never) */ -static int iFacility = 128; /* local0 */ -static int iSeverity = 5; /* notice, as of rfc 3164 */ -static int readMode = 0; /* mode to use for ReadMultiLine call */ -static int maxLinesAtOnce = 10240; /* how many lines to process in a row? */ -static ruleset_t *pBindRuleset = NULL; /* ruleset to bind listener to (use system default if unspecified) */ +static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ +static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */ static int iFilPtr = 0; /* number of files to be monitored; pointer to next free spot during config */ #define MAX_INPUT_FILES 100 @@ -107,6 +135,37 @@ static fileInfo_t files[MAX_INPUT_FILES]; static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ +/* module-global parameters */ +static struct cnfparamdescr modpdescr[] = { + { "pollinginterval", eCmdHdlrPositiveInt, 0 } +}; +static struct cnfparamblk modpblk = + { CNFPARAMBLK_VERSION, + sizeof(modpdescr)/sizeof(struct cnfparamdescr), + modpdescr + }; + +/* input instance parameters */ +static struct cnfparamdescr inppdescr[] = { + { "file", eCmdHdlrString, CNFPARAM_REQUIRED }, + { "statefile", eCmdHdlrString, CNFPARAM_REQUIRED }, + { "tag", eCmdHdlrString, CNFPARAM_REQUIRED }, + { "severity", eCmdHdlrSeverity, 0 }, + { "facility", eCmdHdlrFacility, 0 }, + { "ruleset", eCmdHdlrString, 0 }, + { "readmode", eCmdHdlrInt, 0 }, + { "maxlinesatonce", eCmdHdlrInt, 0 }, + { "maxsubmitatonce", eCmdHdlrInt, 0 }, + { "persiststateinterval", eCmdHdlrInt, 0 } +}; +static struct cnfparamblk inppblk = + { CNFPARAMBLK_VERSION, + sizeof(inppdescr)/sizeof(struct cnfparamdescr), + inppdescr + }; + +#include "im-helper.h" /* must be included AFTER the type definitions! */ + /* enqueue the read file line as a message. The provided string is * not freed - thuis must be done by the caller. */ @@ -268,6 +327,309 @@ finalize_it: #pragma GCC diagnostic warning "-Wempty-body" +/* create input instance, set default paramters, and + * add it to the list of instances. + */ +static rsRetVal +createInstance(instanceConf_t **pinst) +{ + instanceConf_t *inst; + DEFiRet; + CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + inst->next = NULL; + inst->pBindRuleset = NULL; + + inst->pszBindRuleset = NULL; + inst->pszFileName = NULL; + inst->pszTag = NULL; + inst->pszStateFile = NULL; + inst->nMultiSub = NUM_MULTISUB; + inst->iSeverity = 5; + inst->iFacility = 128; + inst->maxLinesAtOnce = 10240; + inst->iPersistStateInterval = 0; + inst->readMode = 0; + + /* node created, let's add to config */ + if(loadModConf->tail == NULL) { + loadModConf->tail = loadModConf->root = inst; + } else { + loadModConf->tail->next = inst; + loadModConf->tail = inst; + } + + *pinst = inst; +finalize_it: + RETiRet; +} + + +/* add a new monitor */ +static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) +{ + instanceConf_t *inst; + DEFiRet; + + if(cs.pszFileName == NULL) { + errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no file name given, file monitor can not be created"); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } + if(cs.pszFileTag == NULL) { + errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no tag value given , file monitor can not be created"); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } + if(cs.pszStateFile == NULL) { + errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: not state file name given, file monitor can not be created"); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } + + CHKiRet(createInstance(&inst)); + if((cs.pszBindRuleset == NULL) || (cs.pszBindRuleset[0] == '\0')) { + inst->pszBindRuleset = NULL; + } else { + CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset)); + } + inst->pszFileName = (uchar*) strdup((char*) cs.pszFileName); + inst->pszTag = (uchar*) strdup((char*) cs.pszFileTag); + inst->pszStateFile = (uchar*) strdup((char*) cs.pszStateFile); + inst->iSeverity = cs.iSeverity; + inst->iFacility = cs.iFacility; + inst->maxLinesAtOnce = cs.maxLinesAtOnce; + inst->iPersistStateInterval = cs.iPersistStateInterval; + inst->readMode = cs.readMode; + + /* reset legacy system */ + cs.iPersistStateInterval = 0; + resetConfigVariables(NULL, NULL); /* values are both dummies */ + +finalize_it: + free(pNewVal); /* we do not need it, but we must free it! */ + RETiRet; +} + + +/* This function is called when a new listener (monitor) shall be added. */ +static inline rsRetVal +addListner(instanceConf_t *inst) +{ + DEFiRet; + fileInfo_t *pThis; + + if(iFilPtr < MAX_INPUT_FILES) { + pThis = &files[iFilPtr]; + //TODO: optimize, save strdup? + pThis->pszFileName = (uchar*) strdup((char*) inst->pszFileName); + pThis->pszTag = (uchar*) strdup((char*) inst->pszTag); + pThis->lenTag = ustrlen(pThis->pszTag); + pThis->pszStateFile = (uchar*) strdup((char*) inst->pszStateFile); + + CHKmalloc(pThis->multiSub.ppMsgs = MALLOC(inst->nMultiSub * sizeof(msg_t*))); + pThis->multiSub.maxElem = inst->nMultiSub; + pThis->multiSub.nElem = 0; + pThis->iSeverity = inst->iSeverity; + pThis->iFacility = inst->iFacility; + pThis->maxLinesAtOnce = inst->maxLinesAtOnce; + pThis->iPersistStateInterval = inst->iPersistStateInterval; + pThis->readMode = inst->readMode; + pThis->pRuleset = inst->pBindRuleset; + pThis->nRecords = 0; + } else { + errmsg.LogError(0, RS_RET_OUT_OF_DESRIPTORS, + "Too many file monitors configured - ignoring %s", + inst->pszFileName); + ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); + } + ++iFilPtr; /* we got a new file to monitor */ + + resetConfigVariables(NULL, NULL); /* values are both dummies */ +finalize_it: + RETiRet; +} + + +BEGINnewInpInst + struct cnfparamvals *pvals; + instanceConf_t *inst; + int i; +CODESTARTnewInpInst + DBGPRINTF("newInpInst (imfile)\n"); + + pvals = nvlstGetParams(lst, &inppblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, + "imfile: required parameter are missing\n"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("input param blk in imfile:\n"); + cnfparamsPrint(&inppblk, pvals); + } + + CHKiRet(createInstance(&inst)); + + for(i = 0 ; i < inppblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(inppblk.descr[i].name, "file")) { + inst->pszFileName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "statefile")) { + inst->pszStateFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "tag")) { + inst->pszTag = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } 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, "severity")) { + inst->iSeverity = pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "facility")) { + inst->iSeverity = pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "readmode")) { + inst->readMode = pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "maxlinesatonce")) { + inst->maxLinesAtOnce = pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "persistStateInterval")) { + inst->iPersistStateInterval = pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "maxsubmitatonce")) { + inst->nMultiSub = pvals[i].val.d.n; + } else { + dbgprintf("imfile: program error, non-handled " + "param '%s'\n", inppblk.descr[i].name); + } + } +finalize_it: +CODE_STD_FINALIZERnewInpInst + cnfparamvalsDestruct(pvals, &inppblk); +ENDnewInpInst + +BEGINbeginCnfLoad +CODESTARTbeginCnfLoad + loadModConf = pModConf; + pModConf->pConf = pConf; + /* init our settings */ + loadModConf->iPollInterval = DFLT_PollInterval; + loadModConf->configSetViaV2Method = 0; + bLegacyCnfModGlobalsPermitted = 1; + /* init legacy config vars */ + cs.pszFileName = NULL; + cs.pszFileTag = NULL; + cs.pszStateFile = NULL; + cs.iPollInterval = DFLT_PollInterval; + cs.iPersistStateInterval = 0; + cs.iFacility = 128; + cs.iSeverity = 5; + cs.readMode = 0; + cs.maxLinesAtOnce = 10240; + cs.pBindRuleset = NULL; +ENDbeginCnfLoad + + +BEGINsetModCnf + struct cnfparamvals *pvals = NULL; + int i; +CODESTARTsetModCnf + pvals = nvlstGetParams(lst, &modpblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "imfile: error processing module " + "config parameters [module(...)]"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("module (global) param blk for imfile:\n"); + cnfparamsPrint(&modpblk, pvals); + } + + for(i = 0 ; i < modpblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(modpblk.descr[i].name, "pollinginterval")) { + loadModConf->iPollInterval = (int) pvals[i].val.d.n; + } else { + dbgprintf("imfile: program error, non-handled " + "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); + } + } + + /* remove all of our legacy handlers, as they can not used in addition + * the the new-style config method. + */ + bLegacyCnfModGlobalsPermitted = 0; + loadModConf->configSetViaV2Method = 1; + +finalize_it: + if(pvals != NULL) + cnfparamvalsDestruct(pvals, &modpblk); +ENDsetModCnf + + + +BEGINendCnfLoad +CODESTARTendCnfLoad + if(!loadModConf->configSetViaV2Method) { + /* persist module-specific settings from legacy config system */ + loadModConf->iPollInterval = cs.iPollInterval; + } + dbgprintf("imfile: polling interval is %d\n", loadModConf->iPollInterval); + + loadModConf = NULL; /* done loading */ + /* free legacy config vars */ + free(cs.pszFileName); + free(cs.pszFileTag); + free(cs.pszStateFile); +ENDendCnfLoad + + +BEGINcheckCnf + instanceConf_t *inst; +CODESTARTcheckCnf + for(inst = pModConf->root ; inst != NULL ; inst = inst->next) { + std_checkRuleset(pModConf, inst); + } + if(pModConf->root == NULL) { + errmsg.LogError(0, RS_RET_NO_LISTNERS, + "imfile: no files configured to be monitored - " + "no input will be gathered"); + iRet = RS_RET_NO_LISTNERS; + } +ENDcheckCnf + + +/* note: we do access files AFTER we have dropped privileges. This is + * intentional, user must make sure the files have the right permissions. + */ +BEGINactivateCnf + instanceConf_t *inst; +CODESTARTactivateCnf + runModConf = pModConf; + for(inst = runModConf->root ; inst != NULL ; inst = inst->next) { + addListner(inst); + } + /* if we could not set up any listners, there is no point in running... */ + if(iFilPtr == 0) { + errmsg.LogError(0, NO_ERRCODE, "imfile: no file monitors could be started, " + "input not activated.\n"); + ABORT_FINALIZE(RS_RET_NO_RUN); + } +finalize_it: +ENDactivateCnf + + +BEGINfreeCnf + instanceConf_t *inst, *del; +CODESTARTfreeCnf + for(inst = pModConf->root ; inst != NULL ; ) { + free(inst->pszBindRuleset); + free(inst->pszFileName); + free(inst->pszTag); + free(inst->pszStateFile); + del = inst; + inst = inst->next; + free(del); + } +ENDfreeCnf + + + /* This function is the cancel cleanup handler. It is called when rsyslog decides the * module must be stopped, what most probably happens during shutdown of rsyslogd. When * this function is called, the runInput() function (below) is already terminated - somewhere @@ -328,7 +690,7 @@ CODESTARTrunInput * other valid scenario. So do not remove. -- rgerhards, 2008-02-14 */ if(glbl.GetGlobalInputTermState() == 0) - srSleep(iPollInterval, 10); + srSleep(runModConf->iPollInterval, 10); } DBGPRINTF("imfile: terminating upon request of rsyslog core\n"); @@ -350,16 +712,6 @@ ENDrunInput */ BEGINwillRun CODESTARTwillRun - /* free config variables we do no longer needed */ - free(pszFileName); - free(pszFileTag); - free(pszStateFile); - - if(iFilPtr == 0) { - errmsg.LogError(0, RS_RET_NO_RUN, "No files configured to be monitored"); - ABORT_FINALIZE(RS_RET_NO_RUN); - } - /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imfile"), sizeof("imfile") - 1)); @@ -458,6 +810,9 @@ ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_IMOD_QUERIES +CODEqueryEtryPt_STD_CONF2_QUERIES +CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES +CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES ENDqueryEtryPt @@ -468,119 +823,37 @@ ENDqueryEtryPt * but in general this is not necessary. Once runInput() has been called, this * function here is never again called. */ -static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) +static rsRetVal +resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) { DEFiRet; - if(pszFileName != NULL) { - free(pszFileName); - pszFileName = NULL; - } - - if(pszFileTag != NULL) { - free(pszFileTag); - pszFileTag = NULL; - } - - if(pszStateFile != NULL) { - free(pszFileTag); - pszFileTag = NULL; - } - + free(cs.pszFileName); + cs.pszFileName = NULL; + free(cs.pszFileTag); + cs.pszFileTag = NULL; + free(cs.pszFileTag); + cs.pszFileTag = NULL; /* set defaults... */ - iPollInterval = 10; - iFacility = 128; /* local0 */ - iSeverity = 5; /* notice, as of rfc 3164 */ - readMode = 0; - pBindRuleset = NULL; - maxLinesAtOnce = 10240; - - RETiRet; -} - - -/* add a new monitor */ -static rsRetVal addMonitor(void __attribute__((unused)) *pVal, uchar *pNewVal) -{ - DEFiRet; - fileInfo_t *pThis; - - free(pNewVal); /* we do not need it, but we must free it! */ - - if(iFilPtr < MAX_INPUT_FILES) { - pThis = &files[iFilPtr]; - /* TODO: check for strdup() NULL return */ - if(pszFileName == NULL) { - errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no file name given, file monitor can not be created"); - ABORT_FINALIZE(RS_RET_CONFIG_ERROR); - } else { - pThis->pszFileName = (uchar*) strdup((char*) pszFileName); - } - - if(pszFileTag == NULL) { - errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: no tag value given , file monitor can not be created"); - ABORT_FINALIZE(RS_RET_CONFIG_ERROR); - } else { - pThis->pszTag = (uchar*) strdup((char*) pszFileTag); - pThis->lenTag = ustrlen(pThis->pszTag); - } - - if(pszStateFile == NULL) { - errmsg.LogError(0, RS_RET_CONFIG_ERROR, "imfile error: not state file name given, file monitor can not be created"); - ABORT_FINALIZE(RS_RET_CONFIG_ERROR); - } else { - pThis->pszStateFile = (uchar*) strdup((char*) pszStateFile); - } - - CHKmalloc(pThis->multiSub.ppMsgs = MALLOC(NUM_MULTISUB * sizeof(msg_t*))); - pThis->multiSub.maxElem = NUM_MULTISUB; - pThis->multiSub.nElem = 0; - pThis->iSeverity = iSeverity; - pThis->iFacility = iFacility; - pThis->maxLinesAtOnce = maxLinesAtOnce; - pThis->iPersistStateInterval = iPersistStateInterval; - pThis->nRecords = 0; - pThis->readMode = readMode; - pThis->pRuleset = pBindRuleset; - iPersistStateInterval = 0; - } else { - errmsg.LogError(0, RS_RET_OUT_OF_DESRIPTORS, "Too many file monitors configured - ignoring this one"); - ABORT_FINALIZE(RS_RET_OUT_OF_DESRIPTORS); - } - - CHKiRet(resetConfigVariables((uchar*) "dummy", (void*) pThis)); /* values are both dummies */ - -finalize_it: - if(iRet == RS_RET_OK) - ++iFilPtr; /* we got a new file to monitor */ + cs.iPollInterval = DFLT_PollInterval; + cs.iFacility = 128; /* local0 */ + cs.iSeverity = 5; /* notice, as of rfc 3164 */ + cs.readMode = 0; + cs.pBindRuleset = NULL; + cs.maxLinesAtOnce = 10240; RETiRet; } - -/* accept a new ruleset to bind. Checks if it exists and complains, if not */ -static rsRetVal -setRuleset(void __attribute__((unused)) *pVal, uchar *pszName) +static inline void +std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst) { - ruleset_t *pRuleset; - rsRetVal localRet; - DEFiRet; - - localRet = ruleset.GetRuleset(ourConf, &pRuleset, pszName); - if(localRet == RS_RET_NOT_FOUND) { - errmsg.LogError(0, NO_ERRCODE, "error: ruleset '%s' not found - ignored", pszName); - } - CHKiRet(localRet); - pBindRuleset = pRuleset; - DBGPRINTF("imfile current bind ruleset %p: '%s'\n", pRuleset, pszName); - -finalize_it: - free(pszName); /* no longer needed */ - RETiRet; + errmsg.LogError(0, NO_ERRCODE, "imfile: ruleset '%s' for %s not found - " + "using default ruleset instead", inst->pszBindRuleset, + inst->pszFileName); } - /* modInit() is called once the module is loaded. It must perform all module-wide * initialization tasks. There are also a number of housekeeping tasks that the * framework requires. These are handled by the macros. Please note that the @@ -603,28 +876,31 @@ CODEmodInit_QueryRegCFSLineHdlr DBGPRINTF("imfile: version %s initializing\n", VERSION); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilename", 0, eCmdHdlrGetWord, - NULL, &pszFileName, STD_LOADABLE_MODULE_ID)); + NULL, &cs.pszFileName, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfiletag", 0, eCmdHdlrGetWord, - NULL, &pszFileTag, STD_LOADABLE_MODULE_ID)); + NULL, &cs.pszFileTag, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilestatefile", 0, eCmdHdlrGetWord, - NULL, &pszStateFile, STD_LOADABLE_MODULE_ID)); + NULL, &cs.pszStateFile, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfileseverity", 0, eCmdHdlrSeverity, - NULL, &iSeverity, STD_LOADABLE_MODULE_ID)); + NULL, &cs.iSeverity, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilefacility", 0, eCmdHdlrFacility, - NULL, &iFacility, STD_LOADABLE_MODULE_ID)); - CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, - NULL, &iPollInterval, STD_LOADABLE_MODULE_ID)); + NULL, &cs.iFacility, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilereadmode", 0, eCmdHdlrInt, - NULL, &readMode, STD_LOADABLE_MODULE_ID)); + NULL, &cs.readMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilemaxlinesatonce", 0, eCmdHdlrSize, - NULL, &maxLinesAtOnce, STD_LOADABLE_MODULE_ID)); + NULL, &cs.maxLinesAtOnce, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilepersiststateinterval", 0, eCmdHdlrInt, - NULL, &iPersistStateInterval, STD_LOADABLE_MODULE_ID)); + NULL, &cs.iPersistStateInterval, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputfilebindruleset", 0, eCmdHdlrGetWord, - setRuleset, NULL, STD_LOADABLE_MODULE_ID)); + NULL, &cs.pszBindRuleset, STD_LOADABLE_MODULE_ID)); /* that command ads a new file! */ CHKiRet(omsdRegCFSLineHdlr((uchar *)"inputrunfilemonitor", 0, eCmdHdlrGetWord, - addMonitor, NULL, STD_LOADABLE_MODULE_ID)); + addInstance, NULL, STD_LOADABLE_MODULE_ID)); + /* module-global config params - will be disabled in configs that are loaded + * via module(...). + */ + CHKiRet(regCfSysLineHdlr2((uchar *)"inputfilepollinterval", 0, eCmdHdlrInt, + NULL, &cs.iPollInterval, STD_LOADABLE_MODULE_ID, &bLegacyCnfModGlobalsPermitted)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit diff --git a/plugins/imptcp/imptcp.c b/plugins/imptcp/imptcp.c index aa1ad81e..9992ee20 100644 --- a/plugins/imptcp/imptcp.c +++ b/plugins/imptcp/imptcp.c @@ -132,6 +132,26 @@ struct modConfData_s { static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */ +/* input instance parameters */ +static struct cnfparamdescr inppdescr[] = { + { "port", eCmdHdlrString, CNFPARAM_REQUIRED }, /* legacy: InputTCPServerRun */ + { "address", eCmdHdlrString, 0 }, + { "name", eCmdHdlrString, 0 }, + { "ruleset", eCmdHdlrString, 0 }, + { "supportoctetcountedframing", eCmdHdlrBinary, 0 }, + { "notifyonconnectionclose", eCmdHdlrBinary, 0 }, + { "keepalive", eCmdHdlrBinary, 0 }, + { "keepalive.probes", eCmdHdlrInt, 0 }, + { "keepalive.time", eCmdHdlrInt, 0 }, + { "keepalive.interval", eCmdHdlrInt, 0 }, + { "addtlframedelimiter", eCmdHdlrInt, 0 }, +}; +static struct cnfparamblk inppblk = + { CNFPARAMBLK_VERSION, + sizeof(inppdescr)/sizeof(struct cnfparamdescr), + inppdescr + }; + #include "im-helper.h" /* must be included AFTER the type definitions! */ /* data elements describing our running config */ typedef struct ptcpsrv_s ptcpsrv_t; @@ -379,7 +399,7 @@ startupSrv(ptcpsrv_t *pSrv) #endif ) { /* TODO: check if *we* bound the socket - else we *have* an error! */ - DBGPRINTF("error %d while binding tcp socket", errno); + DBGPRINTF("error %d while binding tcp socket\n", errno); close(sock); sock = -1; continue; @@ -986,7 +1006,45 @@ closeSess(ptcpsess_t *pSess) destructSess(pSess); finalize_it: - DBGPRINTF("imtcp: session on socket %d closed with iRet %d.\n", sock, iRet); + DBGPRINTF("imptcp: session on socket %d closed with iRet %d.\n", sock, iRet); + RETiRet; +} + + +/* create input instance, set default paramters, and + * add it to the list of instances. + */ +static rsRetVal +createInstance(instanceConf_t **pinst) +{ + instanceConf_t *inst; + DEFiRet; + CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + inst->next = NULL; + + inst->pszBindPort = NULL; + inst->pszBindAddr = NULL; + inst->pszBindRuleset = NULL; + inst->pszInputName = NULL; + inst->bSuppOctetFram = 1; + inst->bKeepAlive = 0; + inst->iKeepAliveIntvl = 0; + inst->iKeepAliveProbes = 0; + inst->iKeepAliveTime = 0; + inst->bEmitMsgOnClose = 0; + inst->iAddtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER; + inst->pBindRuleset = NULL; + + /* node created, let's add to config */ + if(loadModConf->tail == NULL) { + loadModConf->tail = loadModConf->root = inst; + } else { + loadModConf->tail->next = inst; + loadModConf->tail = inst; + } + + *pinst = inst; +finalize_it: RETiRet; } @@ -1000,7 +1058,7 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) instanceConf_t *inst; DEFiRet; - CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + CHKiRet(createInstance(&inst)); if(pNewVal == NULL || *pNewVal == '\0') { errmsg.LogError(0, NO_ERRCODE, "imptcp: port number must be specified, listener ignored"); } @@ -1032,15 +1090,6 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) inst->iKeepAliveTime = cs.iKeepAliveTime; inst->bEmitMsgOnClose = cs.bEmitMsgOnClose; inst->iAddtlFrameDelim = cs.iAddtlFrameDelim; - inst->next = NULL; - - /* node created, let's add to config */ - if(loadModConf->tail == NULL) { - loadModConf->tail = loadModConf->root = inst; - } else { - loadModConf->tail->next = inst; - loadModConf->tail = inst; - } finalize_it: free(pNewVal); @@ -1213,7 +1262,7 @@ sessActivity(ptcpsess_t *pSess) if(lenRcv > 0) { /* have data, process it */ - DBGPRINTF("imtcp: data(%d) on socket %d: %s\n", lenBuf, pSess->sock, rcvBuf); + DBGPRINTF("imptcp: data(%d) on socket %d: %s\n", lenBuf, pSess->sock, rcvBuf); CHKiRet(DataRcvd(pSess, rcvBuf, lenRcv)); } else if (lenRcv == 0) { /* session was closed, do clean-up */ @@ -1229,7 +1278,7 @@ sessActivity(ptcpsess_t *pSess) } else { if(errno == EAGAIN || errno == EWOULDBLOCK) break; - DBGPRINTF("imtcp: error on session socket %d - closed.\n", pSess->sock); + DBGPRINTF("imptcp: error on session socket %d - closed.\n", pSess->sock); closeSess(pSess); /* try clean-up by dropping session */ break; } @@ -1345,6 +1394,63 @@ wrkr(void *myself) } +BEGINnewInpInst + struct cnfparamvals *pvals; + instanceConf_t *inst; + int i; +CODESTARTnewInpInst + DBGPRINTF("newInpInst (imptcp)\n"); + + pvals = nvlstGetParams(lst, &inppblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, + "imptcp: required parameter are missing\n"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("input param blk in imptcp:\n"); + cnfparamsPrint(&inppblk, pvals); + } + + CHKiRet(createInstance(&inst)); + + for(i = 0 ; i < inppblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(inppblk.descr[i].name, "port")) { + inst->pszBindPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "address")) { + inst->pszBindAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "name")) { + inst->pszInputName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } 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, "supportOctetCountedFraming")) { + inst->bSuppOctetFram = (int) pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "keepalive")) { + inst->bKeepAlive = (int) pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "keepalive.probes")) { + inst->iKeepAliveProbes = (int) pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "keepalive.time")) { + inst->iKeepAliveTime = (int) pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "keepalive.interval")) { + inst->iKeepAliveIntvl = (int) pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "addtlframedelimiter")) { + inst->iAddtlFrameDelim = (int) pvals[i].val.d.n; + } else if(!strcmp(inppblk.descr[i].name, "notifyonconnectionclose")) { + inst->bEmitMsgOnClose = (int) pvals[i].val.d.n; + } else { + dbgprintf("imptcp: program error, non-handled " + "param '%s'\n", inppblk.descr[i].name); + } + } +finalize_it: +CODE_STD_FINALIZERnewInpInst + cnfparamvalsDestruct(pvals, &inppblk); +ENDnewInpInst + + BEGINbeginCnfLoad CODESTARTbeginCnfLoad loadModConf = pModConf; @@ -1568,6 +1674,7 @@ CODESTARTqueryEtryPt CODEqueryEtryPt_STD_IMOD_QUERIES CODEqueryEtryPt_STD_CONF2_QUERIES CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES +CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES ENDqueryEtryPt diff --git a/plugins/imrelp/imrelp.c b/plugins/imrelp/imrelp.c index a3209fbe..fe987a50 100644 --- a/plugins/imrelp/imrelp.c +++ b/plugins/imrelp/imrelp.c @@ -88,6 +88,17 @@ struct modConfData_s { static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */ +/* input instance parameters */ +static struct cnfparamdescr inppdescr[] = { + { "port", eCmdHdlrString, CNFPARAM_REQUIRED } +}; +static struct cnfparamblk inppblk = + { CNFPARAMBLK_VERSION, + sizeof(inppdescr)/sizeof(struct cnfparamdescr), + inppdescr + }; + + /* ------------------------------ callbacks ------------------------------ */ @@ -114,6 +125,32 @@ onSyslogRcv(uchar *pHostname, uchar *pIP, uchar *pMsg, size_t lenMsg) /* ------------------------------ end callbacks ------------------------------ */ +/* create input instance, set default paramters, and + * add it to the list of instances. + */ +static rsRetVal +createInstance(instanceConf_t **pinst) +{ + instanceConf_t *inst; + DEFiRet; + CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + inst->next = NULL; + + inst->pszBindPort = NULL; + + /* node created, let's add to config */ + if(loadModConf->tail == NULL) { + loadModConf->tail = loadModConf->root = inst; + } else { + loadModConf->tail->next = inst; + loadModConf->tail = inst; + } + + *pinst = inst; +finalize_it: + RETiRet; +} + /* modified to work for module, not instance (as usual) */ static inline void @@ -134,21 +171,12 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) instanceConf_t *inst; DEFiRet; - CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + CHKiRet(createInstance(&inst)); if(pNewVal == NULL || *pNewVal == '\0') { errmsg.LogError(0, NO_ERRCODE, "imrelp: port number must be specified, listener ignored"); } inst->pszBindPort = pNewVal; - inst->next = NULL; - - /* node created, let's add to config */ - if(loadModConf->tail == NULL) { - loadModConf->tail = loadModConf->root = inst; - } else { - loadModConf->tail->next = inst; - loadModConf->tail = inst; - } finalize_it: RETiRet; @@ -176,6 +204,43 @@ finalize_it: } +BEGINnewInpInst + struct cnfparamvals *pvals; + instanceConf_t *inst; + int i; +CODESTARTnewInpInst + DBGPRINTF("newInpInst (imrelp)\n"); + + pvals = nvlstGetParams(lst, &inppblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, + "imrelp: required parameter are missing\n"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("input param blk in imrelp:\n"); + cnfparamsPrint(&inppblk, pvals); + } + + CHKiRet(createInstance(&inst)); + + for(i = 0 ; i < inppblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(inppblk.descr[i].name, "port")) { + inst->pszBindPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else { + dbgprintf("imrelp: program error, non-handled " + "param '%s'\n", inppblk.descr[i].name); + } + } +finalize_it: +CODE_STD_FINALIZERnewInpInst + cnfparamvalsDestruct(pvals, &inppblk); +ENDnewInpInst + + BEGINbeginCnfLoad CODESTARTbeginCnfLoad loadModConf = pModConf; @@ -328,6 +393,7 @@ CODESTARTqueryEtryPt CODEqueryEtryPt_STD_IMOD_QUERIES CODEqueryEtryPt_STD_CONF2_QUERIES CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES +CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES ENDqueryEtryPt diff --git a/plugins/imtcp/imtcp.c b/plugins/imtcp/imtcp.c index f021307b..a00d4ebe 100644 --- a/plugins/imtcp/imtcp.c +++ b/plugins/imtcp/imtcp.c @@ -128,6 +128,19 @@ struct modConfData_s { static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current load process */ +/* input instance parameters */ +static struct cnfparamdescr inppdescr[] = { + { "port", eCmdHdlrString, CNFPARAM_REQUIRED }, /* legacy: InputTCPServerRun */ + { "name", eCmdHdlrString, 0 }, + { "ruleset", eCmdHdlrString, 0 }, + { "supportOctetCountedFraming", eCmdHdlrBinary, 0 } +}; +static struct cnfparamblk inppblk = + { CNFPARAMBLK_VERSION, + sizeof(inppdescr)/sizeof(struct cnfparamdescr), + inppdescr + }; + #include "im-helper.h" /* must be included AFTER the type definitions! */ /* callbacks */ @@ -201,6 +214,36 @@ finalize_it: } +/* create input instance, set default paramters, and + * add it to the list of instances. + */ +static rsRetVal +createInstance(instanceConf_t **pinst) +{ + instanceConf_t *inst; + DEFiRet; + CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + inst->next = NULL; + inst->pszBindRuleset = NULL; + inst->pszInputName = NULL; + inst->bSuppOctetFram = 1; + + /* node created, let's add to config */ + if(loadModConf->tail == NULL) { + loadModConf->tail = loadModConf->root = inst; + } else { + loadModConf->tail->next = inst; + loadModConf->tail = inst; + } + + *pinst = inst; +finalize_it: + RETiRet; +} + + + + /* This function is called when a new listener instace shall be added to * the current config object via the legacy config system. It just shuffles * all parameters to the listener in-memory instance. @@ -211,7 +254,7 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) instanceConf_t *inst; DEFiRet; - CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + CHKiRet(createInstance(&inst)); CHKmalloc(inst->pszBindPort = ustrdup((pNewVal == NULL || *pNewVal == '\0') ? (uchar*) "10514" : pNewVal)); @@ -226,15 +269,6 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) CHKmalloc(inst->pszInputName = ustrdup(cs.pszInputName)); } inst->bSuppOctetFram = cs.bSuppOctetFram; - inst->next = NULL; - - /* node created, let's add to config */ - if(loadModConf->tail == NULL) { - loadModConf->tail = loadModConf->root = inst; - } else { - loadModConf->tail->next = inst; - loadModConf->tail = inst; - } finalize_it: free(pNewVal); @@ -288,6 +322,49 @@ finalize_it: } +BEGINnewInpInst + struct cnfparamvals *pvals; + instanceConf_t *inst; + int i; +CODESTARTnewInpInst + DBGPRINTF("newInpInst (imtcp)\n"); + + pvals = nvlstGetParams(lst, &inppblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, + "imtcp: required parameter are missing\n"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("input param blk in imtcp:\n"); + cnfparamsPrint(&inppblk, pvals); + } + + CHKiRet(createInstance(&inst)); + + for(i = 0 ; i < inppblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(inppblk.descr[i].name, "port")) { + inst->pszBindPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "name")) { + inst->pszInputName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } 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, "supportOctetCountedFraming")) { + inst->bSuppOctetFram = (int) pvals[i].val.d.n; + } else { + dbgprintf("imtcp: program error, non-handled " + "param '%s'\n", inppblk.descr[i].name); + } + } +finalize_it: +CODE_STD_FINALIZERnewInpInst + cnfparamvalsDestruct(pvals, &inppblk); +ENDnewInpInst + + BEGINbeginCnfLoad CODESTARTbeginCnfLoad loadModConf = pModConf; @@ -451,6 +528,7 @@ CODESTARTqueryEtryPt CODEqueryEtryPt_STD_IMOD_QUERIES CODEqueryEtryPt_STD_CONF2_QUERIES CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES +CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES ENDqueryEtryPt diff --git a/plugins/imudp/imudp.c b/plugins/imudp/imudp.c index 9c92ddde..158d30b8 100644 --- a/plugins/imudp/imudp.c +++ b/plugins/imudp/imudp.c @@ -136,9 +136,48 @@ static struct cnfparamblk modpblk = modpdescr }; +/* input instance parameters */ +static struct cnfparamdescr inppdescr[] = { + { "port", eCmdHdlrString, CNFPARAM_REQUIRED }, /* legacy: InputTCPServerRun */ + { "address", eCmdHdlrString, 0 }, + { "ruleset", eCmdHdlrString, 0 } +}; +static struct cnfparamblk inppblk = + { CNFPARAMBLK_VERSION, + sizeof(inppdescr)/sizeof(struct cnfparamdescr), + inppdescr + }; + #include "im-helper.h" /* must be included AFTER the type definitions! */ +/* create input instance, set default paramters, and + * add it to the list of instances. + */ +static rsRetVal +createInstance(instanceConf_t **pinst) +{ + instanceConf_t *inst; + DEFiRet; + CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + inst->next = NULL; + inst->pBindRuleset = NULL; + + inst->pszBindPort = NULL; + inst->pszBindAddr = NULL; + inst->pszBindRuleset = NULL; + + /* node created, let's add to config */ + if(loadModConf->tail == NULL) { + loadModConf->tail = loadModConf->root = inst; + } else { + loadModConf->tail->next = inst; + loadModConf->tail = inst; + } + *pinst = inst; +finalize_it: + RETiRet; +} /* This function is called when a new listener instace shall be added to * the current config object via the legacy config system. It just shuffles @@ -150,7 +189,7 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) instanceConf_t *inst; DEFiRet; - CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + CHKiRet(createInstance(&inst)); CHKmalloc(inst->pszBindPort = ustrdup((pNewVal == NULL || *pNewVal == '\0') ? (uchar*) "514" : pNewVal)); if((cs.pszBindAddr == NULL) || (cs.pszBindAddr[0] == '\0')) { @@ -163,16 +202,6 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) } else { CHKmalloc(inst->pszBindRuleset = ustrdup(cs.pszBindRuleset)); } - inst->pBindRuleset = NULL; - inst->next = NULL; - - /* node created, let's add to config */ - if(loadModConf->tail == NULL) { - loadModConf->tail = loadModConf->root = inst; - } else { - loadModConf->tail->next = inst; - loadModConf->tail = inst; - } finalize_it: free(pNewVal); @@ -635,6 +664,47 @@ rsRetVal rcvMainLoop(thrdInfo_t *pThrd) #endif /* #if HAVE_EPOLL_CREATE1 */ +BEGINnewInpInst + struct cnfparamvals *pvals; + instanceConf_t *inst; + int i; +CODESTARTnewInpInst + DBGPRINTF("newInpInst (imudp)\n"); + + pvals = nvlstGetParams(lst, &inppblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, + "imudp: required parameter are missing\n"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("input param blk in imudp:\n"); + cnfparamsPrint(&inppblk, pvals); + } + + CHKiRet(createInstance(&inst)); + + for(i = 0 ; i < inppblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(inppblk.descr[i].name, "port")) { + inst->pszBindPort = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "address")) { + inst->pszBindAddr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(inppblk.descr[i].name, "ruleset")) { + inst->pszBindRuleset = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else { + dbgprintf("imudp: program error, non-handled " + "param '%s'\n", inppblk.descr[i].name); + } + } +finalize_it: +CODE_STD_FINALIZERnewInpInst + cnfparamvalsDestruct(pvals, &inppblk); +ENDnewInpInst + + BEGINbeginCnfLoad CODESTARTbeginCnfLoad loadModConf = pModConf; @@ -660,13 +730,13 @@ BEGINsetModCnf CODESTARTsetModCnf pvals = nvlstGetParams(lst, &modpblk, NULL); if(pvals == NULL) { - errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module " + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "imudp: error processing module " "config parameters [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if(Debug) { - dbgprintf("module (global) param blk for impstats:\n"); + dbgprintf("module (global) param blk for imudp:\n"); cnfparamsPrint(&modpblk, pvals); } @@ -680,7 +750,7 @@ CODESTARTsetModCnf } else if(!strcmp(modpblk.descr[i].name, "schedulingpolicy")) { loadModConf->pszSchedPolicy = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else { - dbgprintf("impstats: program error, non-handled " + dbgprintf("imudp: program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); } } @@ -839,23 +909,18 @@ CODEqueryEtryPt_STD_IMOD_QUERIES CODEqueryEtryPt_STD_CONF2_QUERIES CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES +CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES ENDqueryEtryPt static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal) { - if(cs.pszBindAddr != NULL) { - free(cs.pszBindAddr); - cs.pszBindAddr = NULL; - } - if(cs.pszSchedPolicy != NULL) { - free(cs.pszSchedPolicy); - cs.pszSchedPolicy = NULL; - } - if(cs.pszBindRuleset != NULL) { - free(cs.pszBindRuleset); - cs.pszBindRuleset = NULL; - } + free(cs.pszBindAddr); + cs.pszBindAddr = NULL; + free(cs.pszSchedPolicy); + cs.pszSchedPolicy = NULL; + free(cs.pszBindRuleset); + cs.pszBindRuleset = NULL; cs.iSchedPrio = SCHED_PRIO_UNSET; cs.iTimeRequery = TIME_REQUERY_DFLT;/* the default is to query only every second time */ return RS_RET_OK; diff --git a/plugins/imuxsock/imuxsock.c b/plugins/imuxsock/imuxsock.c index a2c53b52..a4933115 100644 --- a/plugins/imuxsock/imuxsock.c +++ b/plugins/imuxsock/imuxsock.c @@ -247,10 +247,30 @@ static struct cnfparamblk modpblk = modpdescr }; +/* input instance parameters */ +static struct cnfparamdescr inppdescr[] = { + { "socket", eCmdHdlrString, CNFPARAM_REQUIRED }, /* legacy: addunixlistensocket */ + { "createpath", eCmdHdlrBinary, 0 }, + { "parsetrusted", eCmdHdlrBinary, 0 }, + { "hostname", eCmdHdlrString, 0 }, + { "ignoretimestamp", eCmdHdlrBinary, 0 }, + { "flowcontrol", eCmdHdlrBinary, 0 }, + { "usesystimestamp", eCmdHdlrBinary, 0 }, + { "annotate", eCmdHdlrBinary, 0 }, + { "usepidfromsystem", eCmdHdlrBinary, 0 }, + { "ratelimit.interval", eCmdHdlrInt, 0 }, + { "ratelimit.burst", eCmdHdlrInt, 0 }, + { "ratelimit.severity", eCmdHdlrInt, 0 } +}; +static struct cnfparamblk inppblk = + { CNFPARAMBLK_VERSION, + sizeof(inppdescr)/sizeof(struct cnfparamdescr), + 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! */ - static void initRatelimitState(struct rs_ratelimit_state *rs, unsigned short interval, unsigned short burst) { @@ -319,6 +339,43 @@ finalize_it: } +/* create input instance, set default paramters, and + * add it to the list of instances. + */ +static rsRetVal +createInstance(instanceConf_t **pinst) +{ + instanceConf_t *inst; + DEFiRet; + CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + inst->sockName = NULL; + inst->pLogHostName = NULL; + inst->ratelimitInterval = DFLT_ratelimitInterval; + inst->ratelimitBurst = DFLT_ratelimitSeverity; + inst->ratelimitSeverity = DFLT_ratelimitSeverity; + inst->bUseFlowCtl = 0; + inst->bIgnoreTimestamp = 1; + inst->bCreatePath = DFLT_bCreatePath; + inst->bUseSysTimeStamp = 1; + inst->bWritePid = 0; + inst->bAnnotate = 0; + inst->bParseTrusted = 0; + inst->next = NULL; + + /* node created, let's add to config */ + if(loadModConf->tail == NULL) { + loadModConf->tail = loadModConf->root = inst; + } else { + loadModConf->tail->next = inst; + loadModConf->tail = inst; + } + + *pinst = inst; +finalize_it: + RETiRet; +} + + /* This function is called when a new listen socket instace shall be added to * the current config object via the legacy config system. It just shuffles * all parameters to the listener in-memory instance. @@ -337,7 +394,7 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) ABORT_FINALIZE(RS_RET_SOCKNAME_MISSING); } - CHKmalloc(inst = MALLOC(sizeof(instanceConf_t))); + CHKiRet(createInstance(&inst)); inst->sockName = pNewVal; inst->ratelimitInterval = cs.ratelimitInterval; inst->pLogHostName = cs.pLogHostName; @@ -352,14 +409,6 @@ static rsRetVal addInstance(void __attribute__((unused)) *pVal, uchar *pNewVal) inst->bParseTrusted = cs.bParseTrusted; inst->next = NULL; - /* node created, let's add to config */ - if(loadModConf->tail == NULL) { - loadModConf->tail = loadModConf->root = inst; - } else { - loadModConf->tail->next = inst; - loadModConf->tail = inst; - } - /* some legacy conf processing */ free(cs.pLogHostName); /* reset hostname for next socket */ cs.pLogHostName = NULL; @@ -1181,6 +1230,65 @@ finalize_it: ENDsetModCnf +BEGINnewInpInst + struct cnfparamvals *pvals; + instanceConf_t *inst; + int i; +CODESTARTnewInpInst + DBGPRINTF("newInpInst (imuxsock)\n"); + + pvals = nvlstGetParams(lst, &inppblk, NULL); + if(pvals == NULL) { + errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, + "imuxsock: required parameter are missing\n"); + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("input param blk in imuxsock:\n"); + cnfparamsPrint(&inppblk, pvals); + } + + CHKiRet(createInstance(&inst)); + + for(i = 0 ; i < inppblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(inppblk.descr[i].name, "socket")) { + inst->sockName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(modpblk.descr[i].name, "createpath")) { + inst->bCreatePath = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "parsetrusted")) { + inst->bParseTrusted = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "hostname")) { + inst->pLogHostName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(modpblk.descr[i].name, "ignoretimestamp")) { + inst->bIgnoreTimestamp = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "flowcontrol")) { + inst->bUseFlowCtl = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "usesystimestamp")) { + inst->bUseSysTimeStamp = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "annotate")) { + inst->bAnnotate = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "usepidfromsystem")) { + inst->bWritePid = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "ratelimit.interval")) { + inst->ratelimitInterval = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "ratelimit.burst")) { + inst->ratelimitBurst = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "ratelimit.severity")) { + inst->ratelimitSeverity = (int) pvals[i].val.d.n; + } else { + dbgprintf("imuxsock: program error, non-handled " + "param '%s'\n", inppblk.descr[i].name); + } + } +finalize_it: +CODE_STD_FINALIZERnewInpInst + cnfparamvalsDestruct(pvals, &inppblk); +ENDnewInpInst + + BEGINendCnfLoad CODESTARTendCnfLoad if(!loadModConf->configSetViaV2Method) { @@ -1366,6 +1474,7 @@ CODEqueryEtryPt_STD_IMOD_QUERIES CODEqueryEtryPt_STD_CONF2_QUERIES CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES +CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES ENDqueryEtryPt diff --git a/runtime/module-template.h b/runtime/module-template.h index 5d32b909..9dd759a5 100644 --- a/runtime/module-template.h +++ b/runtime/module-template.h @@ -353,6 +353,24 @@ finalize_it:\ } +/* newInpInst() + * This is basically the equivalent to newActInst() for creating input + * module (listener) instances. + */ +#define BEGINnewInpInst \ +static rsRetVal newInpInst(struct nvlst *lst)\ +{\ + DEFiRet; + +#define CODESTARTnewInpInst \ + +#define CODE_STD_FINALIZERnewInpInst + +#define ENDnewInpInst \ + RETiRet;\ +} + + /* tryResume() * This entry point is called to check if a module can resume operations. This * happens when a module requested that it be suspended. In suspended state, @@ -521,6 +539,16 @@ static rsRetVal queryEtryPt(uchar *name, rsRetVal (**pEtryPoint)())\ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES +/* the following block is to be added for input modules that support the v2 + * config system. The config name is also provided. + */ +#define CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES \ + else if(!strcmp((char*) name, "newInpInst")) {\ + *pEtryPoint = newInpInst;\ + } \ + CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES + + /* the following block is to be added for modules that require * pre priv drop activation support. */ diff --git a/runtime/modules.c b/runtime/modules.c index 8675e414..9f7ff31c 100644 --- a/runtime/modules.c +++ b/runtime/modules.c @@ -350,11 +350,13 @@ addModToGlblList(modInfo_t *pThis) } -/* Add a module to the config module list for current loadConf and - * provide its config params to it. +/* ready module for config processing. this includes checking if the module + * is already in the config, so this function may return errors. Returns a + * pointer to the last module inthe current config. That pointer needs to + * be passed to addModToCnfLst() when it is called later in the process. */ rsRetVal -addModToCnfList(modInfo_t *pThis) +readyModForCnf(modInfo_t *pThis, cfgmodules_etry_t **ppNew, cfgmodules_etry_t **ppLast) { cfgmodules_etry_t *pNew; cfgmodules_etry_t *pLast; @@ -362,8 +364,7 @@ addModToCnfList(modInfo_t *pThis) assert(pThis != NULL); if(loadConf == NULL) { - /* we are in an early init state */ - FINALIZE; + FINALIZE; /* we are in an early init state */ } /* check for duplicates and, as a side-activity, identify last node */ @@ -399,6 +400,36 @@ addModToCnfList(modInfo_t *pThis) CHKiRet(pThis->beginCnfLoad(&pNew->modCnf, loadConf)); } + *ppLast = pLast; + *ppNew = pNew; +finalize_it: + RETiRet; +} + + +/* abort the creation of a module entry without adding it to the + * module list. Needed to prevent mem leaks. + */ +static inline void +abortCnfUse(cfgmodules_etry_t *pNew) +{ + free(pNew); +} + + +/* Add a module to the config module list for current loadConf. + * Requires last pointer obtained by readyModForCnf(). + */ +rsRetVal +addModToCnfList(cfgmodules_etry_t *pNew, cfgmodules_etry_t *pLast) +{ + DEFiRet; + assert(pNew != NULL); + + if(loadConf == NULL) { + FINALIZE; /* we are in an early init state */ + } + if(pLast == NULL) { loadConf->modules.root = pNew; } else { @@ -608,6 +639,12 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"willRun", &pNew->mod.im.willRun)); CHKiRet((*pNew->modQueryEtryPt)((uchar*)"afterRun", &pNew->mod.im.afterRun)); pNew->mod.im.bCanRun = 0; + localRet = (*pNew->modQueryEtryPt)((uchar*)"newInpInst", &pNew->mod.im.newInpInst); + if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { + pNew->mod.om.newActInst = NULL; + } else if(localRet != RS_RET_OK) { + ABORT_FINALIZE(localRet); + } break; case eMOD_OUT: CHKiRet((*pNew->modQueryEtryPt)((uchar*)"freeInstance", &pNew->freeInstance)); @@ -626,7 +663,8 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_ else if(localRet != RS_RET_OK) ABORT_FINALIZE(localRet); - localRet = (*pNew->modQueryEtryPt)((uchar*)"endTransaction", &pNew->mod.om.endTransaction); + localRet = (*pNew->modQueryEtryPt)((uchar*)"endTransaction", + &pNew->mod.om.endTransaction); if(localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->mod.om.endTransaction = dummyEndTransaction; } else if(localRet != RS_RET_OK) { @@ -965,6 +1003,8 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst) int bHasExtension; void *pModHdlr, *pModInit; modInfo_t *pModInfo; + cfgmodules_etry_t *pNew; + cfgmodules_etry_t *pLast; uchar *pModDirCurr, *pModDirNext; int iLoadCnt; struct dlhandle_s *pHandle = NULL; @@ -999,8 +1039,9 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst) if(pModInfo != NULL) { DBGPRINTF("Module '%s' already loaded\n", pModName); if(bConfLoad) { - localRet = addModToCnfList(pModInfo); + localRet = readyModForCnf(pModInfo, &pNew, &pLast); if(pModInfo->setModCnf != NULL && localRet == RS_RET_OK) { + addModToCnfList(pNew, pLast); if(!strncmp((char*)pModName, "builtin:", sizeof("builtin:")-1)) { if(pModInfo->bSetModCnfCalled) { errmsg.LogError(0, RS_RET_DUP_PARAM, @@ -1128,12 +1169,21 @@ Load(uchar *pModName, sbool bConfLoad, struct nvlst *lst) } if(bConfLoad) { - addModToCnfList(pModInfo); + readyModForCnf(pModInfo, &pNew, &pLast); if(pModInfo->setModCnf != NULL) { - if(lst != NULL) - pModInfo->setModCnf(lst); + if(lst != NULL) { + localRet = pModInfo->setModCnf(lst); + if(localRet != RS_RET_OK) { + errmsg.LogError(0, localRet, + "module '%s', failed processing config parameters", + pPathBuf); + abortCnfUse(pNew); + ABORT_FINALIZE(localRet); + } + } pModInfo->bSetModCnfCalled = 1; } + addModToCnfList(pNew, pLast); } finalize_it: diff --git a/runtime/modules.h b/runtime/modules.h index 16425beb..e42d19e1 100644 --- a/runtime/modules.h +++ b/runtime/modules.h @@ -131,6 +131,7 @@ struct modInfo_s { /* TODO: remove? */rsRetVal (*willRun)(void); /* check if the current config will be able to run*/ rsRetVal (*runInput)(thrdInfo_t*); /* function to gather input and submit to queue */ rsRetVal (*afterRun)(thrdInfo_t*); /* function to gather input and submit to queue */ + rsRetVal (*newInpInst)(struct nvlst *lst); int bCanRun; /* cached value of whether willRun() succeeded */ } im; struct {/* data for output modules */ @@ -194,6 +195,6 @@ PROTOTYPEObj(module); */ rsRetVal modulesProcessCnf(struct cnfobj *o); uchar *modGetName(modInfo_t *pThis); - -rsRetVal addModToCnfList(modInfo_t *pThis); +rsRetVal addModToCnfList(cfgmodules_etry_t *pNew, cfgmodules_etry_t *pLast); +rsRetVal readyModForCnf(modInfo_t *pThis, cfgmodules_etry_t **ppNew, cfgmodules_etry_t **ppLast); #endif /* #ifndef MODULES_H_INCLUDED */ diff --git a/runtime/rsconf.c b/runtime/rsconf.c index 2cffd14c..b45746c4 100644 --- a/runtime/rsconf.c +++ b/runtime/rsconf.c @@ -97,6 +97,17 @@ static uchar template_SysklogdFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogta static uchar template_StdJSONFmt[] = "\"{\\\"message\\\":\\\"%msg:::json%\\\",\\\"fromhost\\\":\\\"%HOSTNAME:::json%\\\",\\\"facility\\\":\\\"%syslogfacility-text%\\\",\\\"priority\\\":\\\"%syslogpriority-text%\\\",\\\"timereported\\\":\\\"%timereported:::date-rfc3339%\\\",\\\"timegenerated\\\":\\\"%timegenerated:::date-rfc3339%\\\"}\""; /* end templates */ +/* tables for interfacing with the v6 config system (as far as we need to) */ +static struct cnfparamdescr inppdescr[] = { + { "type", eCmdHdlrString, CNFPARAM_REQUIRED } +}; +static struct cnfparamblk inppblk = + { CNFPARAMBLK_VERSION, + sizeof(inppdescr)/sizeof(struct cnfparamdescr), + inppdescr + }; + +/* forward-definitions */ void cnfDoCfsysline(char *ln); /* Standard-Constructor @@ -323,6 +334,45 @@ finalize_it: return estr; } + +/* Process input() objects */ +rsRetVal +inputProcessCnf(struct cnfobj *o) +{ + struct cnfparamvals *pvals; + modInfo_t *pMod; + uchar *cnfModName = NULL; + int typeIdx; + DEFiRet; + + pvals = nvlstGetParams(o->nvlst, &inppblk, NULL); + if(pvals == NULL) { + ABORT_FINALIZE(RS_RET_ERR); + } + DBGPRINTF("input param blk after inputProcessCnf:\n"); + cnfparamsPrint(&inppblk, pvals); + typeIdx = cnfparamGetIdx(&inppblk, "type"); + if(pvals[typeIdx].bUsed == 0) { + errmsg.LogError(0, RS_RET_CONF_RQRD_PARAM_MISSING, "input type missing"); + ABORT_FINALIZE(RS_RET_CONF_RQRD_PARAM_MISSING); // TODO: move this into rainerscript handlers + } + cnfModName = (uchar*)es_str2cstr(pvals[typeIdx].val.d.estr, NULL); + if((pMod = module.FindWithCnfName(loadConf, cnfModName, eMOD_IN)) == NULL) { + errmsg.LogError(0, RS_RET_MOD_UNKNOWN, "input module name '%s' is unknown", cnfModName); + ABORT_FINALIZE(RS_RET_MOD_UNKNOWN); + } + if(pMod->mod.im.newInpInst == NULL) { + errmsg.LogError(0, RS_RET_MOD_NO_INPUT_STMT, + "input module '%s' does not support input() statement", cnfModName); + ABORT_FINALIZE(RS_RET_MOD_NO_INPUT_STMT); + } + CHKiRet(pMod->mod.im.newInpInst(o->nvlst)); +finalize_it: + free(cnfModName); + cnfparamvalsDestruct(pvals, &inppblk); + RETiRet; +} + /*------------------------------ interface to flex/bison parser ------------------------------*/ extern int yylineno; @@ -360,6 +410,9 @@ void cnfDoObj(struct cnfobj *o) case CNFOBJ_MODULE: modulesProcessCnf(o); break; + case CNFOBJ_INPUT: + inputProcessCnf(o); + break; case CNFOBJ_TPL: tplProcessCnf(o); break; @@ -941,10 +994,13 @@ setModDir(void __attribute__((unused)) *pVal, uchar* pszNewVal) static rsRetVal regBuildInModule(rsRetVal (*modInit)(), uchar *name, void *pModHdlr) { + cfgmodules_etry_t *pNew; + cfgmodules_etry_t *pLast; modInfo_t *pMod; DEFiRet; CHKiRet(module.doModInit(modInit, name, pModHdlr, &pMod)); - addModToCnfList(pMod); + readyModForCnf(pMod, &pNew, &pLast); + addModToCnfList(pNew, pLast); finalize_it: RETiRet; } diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index fe9f856a..336ab5bf 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -381,6 +381,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_MODULE_ALREADY_IN_CONF = -2221, /**< module already in current configuration */ RS_RET_PARAM_NOT_PERMITTED = -2222, /**< legacy parameter no longer permitted (usally already set by v2) */ RS_RET_NO_JSON_PASSING = -2223, /**< rsyslog core does not support JSON-passing plugin API */ + RS_RET_MOD_NO_INPUT_STMT = -2224, /**< (input) module does not support input() statement */ /**** up to 2300 is reserved for v6 use ****/ RS_RET_JNAME_NO_ROOT = -2301, /**< root element is missing in JSON path */ diff --git a/runtime/typedefs.h b/runtime/typedefs.h index b53c36f5..b99daed7 100644 --- a/runtime/typedefs.h +++ b/runtime/typedefs.h @@ -156,6 +156,8 @@ typedef enum cslCmdHdlrType { eCmdHdlrBinary, eCmdHdlrFileCreateMode, eCmdHdlrInt, + eCmdHdlrNonNegInt, + eCmdHdlrPositiveInt, eCmdHdlrSize, eCmdHdlrGetChar, eCmdHdlrFacility, |