diff options
Diffstat (limited to 'plugins/pmnormalize/pmnormalize.c')
-rw-r--r-- | plugins/pmnormalize/pmnormalize.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/plugins/pmnormalize/pmnormalize.c b/plugins/pmnormalize/pmnormalize.c new file mode 100644 index 0000000..4d3ad76 --- /dev/null +++ b/plugins/pmnormalize/pmnormalize.c @@ -0,0 +1,270 @@ +/* pmnormalize.c + * This is a parser module for parsing incoming messages using liblognorm. + * + * File begun on 2017-03-03 by Pascal Withopf. + * + * Copyright 2014-2019 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 <stdlib.h> +#include <string.h> +#include <assert.h> +#include <errno.h> +#include <ctype.h> +#include <liblognorm.h> +#include <json.h> +#include "conf.h" +#include "syslogd-types.h" +#include "template.h" +#include "msg.h" +#include "module-template.h" +#include "glbl.h" +#include "errmsg.h" +#include "parser.h" +#include "datetime.h" +#include "unicode-helper.h" + +MODULE_TYPE_PARSER +MODULE_TYPE_NOKEEP +PARSER_NAME("rsyslog.pmnormalize") +MODULE_CNFNAME("pmnormalize") + +/* internal structures */ +DEF_PMOD_STATIC_DATA +DEFobjCurrIf(glbl) +DEFobjCurrIf(parser) +DEFobjCurrIf(datetime) + + +/* parser instance parameters */ +static struct cnfparamdescr parserpdescr[] = { + { "rulebase", eCmdHdlrGetWord, 0 }, + { "rule", eCmdHdlrArray, 0 }, + { "undefinedpropertyerror", eCmdHdlrBinary, 0 } +}; +static struct cnfparamblk parserpblk = + { CNFPARAMBLK_VERSION, + sizeof(parserpdescr)/sizeof(struct cnfparamdescr), + parserpdescr + }; + +struct instanceConf_s { + sbool undefPropErr; + char *rulebase; + char *rule; + ln_ctx ctxln; /*context to be used for liblognorm*/ + char *pszPath; /*path of normalized data*/ +}; + +BEGINisCompatibleWithFeature +CODESTARTisCompatibleWithFeature + if(eFeat == sFEATUREAutomaticSanitazion) + iRet = RS_RET_OK; + if(eFeat == sFEATUREAutomaticPRIParsing) + iRet = RS_RET_OK; +ENDisCompatibleWithFeature + +/* create input instance, set default parameters, 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->undefPropErr = 0; + inst->rulebase = NULL; + inst->rule = NULL; + inst->ctxln = NULL; + *pinst = inst; +finalize_it: + RETiRet; +} + +/* callback for liblognorm error messages */ +static void +errCallBack(void __attribute__((unused)) *cookie, const char *msg, + size_t __attribute__((unused)) lenMsg) +{ + LogError(0, RS_RET_ERR_LIBLOGNORM, "liblognorm error: %s", msg); +} + +/* to be called to build the liblognorm part of the instance ONCE ALL PARAMETERS ARE CORRECT + * (and set within inst!). + */ +static rsRetVal +buildInstance(instanceConf_t *inst) +{ + DEFiRet; + if((inst->ctxln = ln_initCtx()) == NULL) { + LogError(0, RS_RET_ERR_LIBLOGNORM_INIT, "error: could not initialize " + "liblognorm ctx, cannot activate action"); + ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_INIT); + } + ln_setErrMsgCB(inst->ctxln, errCallBack, NULL); + + if(inst->rule != NULL && inst->rulebase == NULL) { + if(ln_loadSamplesFromString(inst->ctxln, inst->rule) !=0) { + LogError(0, RS_RET_NO_RULEBASE, "error: normalization rules '%s' " + "could not be loaded, cannot activate action", inst->rule); + ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD); + } + } else if(inst->rulebase != NULL && inst->rule == NULL) { + if(ln_loadSamples(inst->ctxln, (char*) inst->rulebase) != 0) { + LogError(0, RS_RET_NO_RULEBASE, "error: normalization rulebase '%s' " + "could not be loaded, cannot activate action", inst->rulebase); + ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD); + } + } +finalize_it: + RETiRet; +} + + +BEGINfreeParserInst +CODESTARTfreeParserInst + dbgprintf("pmnormalize: free parser instance %p\n", pInst); + free(pInst->rulebase); + free(pInst->rule); + if(pInst->ctxln != NULL) { + ln_exitCtx(pInst->ctxln); + } +ENDfreeParserInst + + +BEGINnewParserInst + struct cnfparamvals *pvals = NULL; + int i; +CODESTARTnewParserInst + DBGPRINTF("newParserInst (pmnormalize)\n"); + + inst = NULL; + CHKiRet(createInstance(&inst)); + + if(lst == NULL) + FINALIZE; /* just set defaults, no param block! */ + + if((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) { + ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); + } + + if(Debug) { + dbgprintf("parser param blk in pmnormalize:\n"); + cnfparamsPrint(&parserpblk, pvals); + } + + for(i = 0 ; i < parserpblk.nParams ; ++i) { + if(!pvals[i].bUsed) + continue; + if(!strcmp(parserpblk.descr[i].name, "undefinedpropertyerror")) { + inst->undefPropErr = (int) pvals[i].val.d.n; + } else if(!strcmp(parserpblk.descr[i].name, "rulebase")) { + inst->rulebase = (char *) es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(parserpblk.descr[i].name, "rule")) { + es_str_t *rules; + CHKmalloc(rules = es_newStr(128)); + for(int j=0; j < pvals[i].val.d.ar->nmemb; ++j) { + CHKiRet(es_addStr(&rules, pvals[i].val.d.ar->arr[j])); + CHKiRet(es_addChar(&rules, '\n')); + } + inst->rule = (char*)es_str2cstr(rules, NULL); + if(rules != NULL) + es_deleteStr(rules); + } else { + LogError(0, RS_RET_INTERNAL_ERROR , + "pmnormalize: program error, non-handled param '%s'", + parserpblk.descr[i].name); + } + } + if(!inst->rulebase && !inst->rule) { + LogError(0, RS_RET_CONFIG_ERROR, "pmnormalize: you need to specify " + "either parameter 'rule' or 'rulebase'."); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } + if(inst->rulebase && inst->rule) { + LogError(0, RS_RET_CONFIG_ERROR, "pmnormalize: you need to specify " + "one of the parameters 'rule' and 'rulebase', but not both"); + ABORT_FINALIZE(RS_RET_CONFIG_ERROR); + } + + iRet = buildInstance(inst); +finalize_it: +CODE_STD_FINALIZERnewParserInst + if(lst != NULL) + cnfparamvalsDestruct(pvals, &parserpblk); + if(iRet != RS_RET_OK && inst != NULL) + freeParserInst(inst); +ENDnewParserInst + + +BEGINparse2 + uchar *buf; + rs_size_t len; + int r; + struct json_object *json = NULL; +CODESTARTparse2 + DBGPRINTF("Message will now be parsed by pmnormalize\n"); + /*Msg OffSet needs to be set*/ + MsgSetMSGoffs(pMsg, 0); + + getRawMsg(pMsg, &buf, &len); + r = ln_normalize(pInst->ctxln, (char*)buf, len, &json); + if(r != 0) { + DBGPRINTF("error %d during ln_normalize\n", r); + if(pInst->undefPropErr) { + LogError(0, RS_RET_ERR, "error %d during ln_normalize; " + "json: %s\n", r, fjson_object_to_json_string(json)); + } + fjson_object_put(json); + ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); + } else { + iRet = MsgSetPropsViaJSON_Object(pMsg, json); + } +finalize_it: +ENDparse2 + + +BEGINmodExit +CODESTARTmodExit + /* release what we no longer need */ + objRelease(glbl, CORE_COMPONENT); + objRelease(parser, CORE_COMPONENT); + objRelease(datetime, CORE_COMPONENT); +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_PMOD2_QUERIES +CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES +ENDqueryEtryPt + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ +CODEmodInit_QueryRegCFSLineHdlr + CHKiRet(objUse(glbl, CORE_COMPONENT)); + CHKiRet(objUse(parser, CORE_COMPONENT)); + CHKiRet(objUse(datetime, CORE_COMPONENT)); + + DBGPRINTF("pmnormalize parser init called\n"); +ENDmodInit |