diff options
Diffstat (limited to 'grammar')
-rw-r--r-- | grammar/grammar.y | 19 | ||||
-rw-r--r-- | grammar/lexer.l | 11 | ||||
-rw-r--r-- | grammar/rainerscript.c | 221 | ||||
-rw-r--r-- | grammar/rainerscript.h | 27 |
4 files changed, 271 insertions, 7 deletions
diff --git a/grammar/grammar.y b/grammar/grammar.y index 402b1a57..29ff02fe 100644 --- a/grammar/grammar.y +++ b/grammar/grammar.y @@ -49,6 +49,7 @@ extern int yyerror(char*); enum cnfobjType objType; struct cnfobj *obj; struct nvlst *nvlst; + struct objlst *objlst; struct cnfactlst *actlst; struct cnfexpr *expr; struct cnfrule *rule; @@ -63,8 +64,12 @@ extern int yyerror(char*); %token ENDOBJ %token <s> CFSYSLINE %token BEGIN_ACTION +%token BEGIN_PROPERTY +%token BEGIN_CONSTANT +%token BEGIN_TPL %token STOP %token <s> LEGACY_ACTION +%token <s> LEGACY_RULESET %token <s> PRIFILT %token <s> PROPFILT %token <s> BSD_TAG_SELECTOR @@ -89,7 +94,8 @@ extern int yyerror(char*); %token CMP_STARTSWITHI %type <nvlst> nv nvlst -%type <obj> obj +%type <obj> obj property constant +%type <objlst> propconst %type <actlst> actlst %type <actlst> act %type <s> cfsysline @@ -124,10 +130,21 @@ conf: /* empty (to end recursion) */ | conf obj { cnfDoObj($2); } | conf rule { cnfDoRule($2); } | conf cfsysline { cnfDoCfsysline($2); } + | conf LEGACY_RULESET { cnfDoCfsysline($2); } | conf BSD_TAG_SELECTOR { cnfDoBSDTag($2); } | conf BSD_HOST_SELECTOR { cnfDoBSDHost($2); } obj: BEGINOBJ nvlst ENDOBJ { $$ = cnfobjNew($1, $2); } | BEGIN_ACTION nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_ACTION, $2); } + | BEGIN_TPL nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_TPL, $2); } + | BEGIN_TPL nvlst ENDOBJ '{' propconst '}' + { $$ = cnfobjNew(CNFOBJ_TPL, $2); + $$->subobjs = $5; + } +propconst: { $$ = NULL; } + | propconst property { $$ = objlstAdd($1, $2); } + | propconst constant { $$ = objlstAdd($1, $2); } +property: BEGIN_PROPERTY nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_PROPERTY, $2); } +constant: BEGIN_CONSTANT nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_CONSTANT, $2); } cfsysline: CFSYSLINE { $$ = $1; } nvlst: { $$ = NULL; } | nvlst nv { $2->next = $1; $$ = $2; } diff --git a/grammar/lexer.l b/grammar/lexer.l index 6ac7fd9a..b006b75f 100644 --- a/grammar/lexer.l +++ b/grammar/lexer.l @@ -9,7 +9,7 @@ * cases. So while we hope that cfsysline support can be dropped some time in * the future, we will probably keep these useful constructs. * - * Copyright 2011 Rainer Gerhards and Adiscon GmbH. + * Copyright 2011-2012 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * @@ -157,6 +157,12 @@ int fileno(FILE *stream); BEGIN INITIAL; } "global"[ \n\t]*"(" { yylval.objType = CNFOBJ_GLOBAL; BEGIN INOBJ; return BEGINOBJ; } +"template"[ \n\t]*"(" { yylval.objType = CNFOBJ_TPL; + BEGIN INOBJ; return BEGIN_TPL; } +"property"[ \n\t]*"(" { yylval.objType = CNFOBJ_PROPERTY; + BEGIN INOBJ; return BEGIN_PROPERTY; } +"constant"[ \n\t]*"(" { yylval.objType = CNFOBJ_CONSTANT; + BEGIN INOBJ; return BEGIN_CONSTANT; } "input"[ \n\t]*"(" { yylval.objType = CNFOBJ_INPUT; BEGIN INOBJ; return BEGINOBJ; } "module"[ \n\t]*"(" { yylval.objType = CNFOBJ_MODULE; @@ -192,6 +198,9 @@ int fileno(FILE *stream); if(!strncasecmp(yytext, "$includeconfig ", 14)) { yyless(14); BEGIN INCL; + } else if(!strncasecmp(yytext, "$ruleset ", 9)) { + yylval.s = strdup(yytext); + return LEGACY_RULESET; } else { yylval.s = strdup(yytext); return CFSYSLINE; diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index e458187c..5e6e492d 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -41,6 +41,11 @@ #include "grammar.h" #include "queue.h" #include "srUtils.h" +#include "regexp.h" +#include "obj.h" + +DEFobjCurrIf(obj) +DEFobjCurrIf(regexp) void readConfFile(FILE *fp, es_str_t **str) @@ -93,6 +98,62 @@ readConfFile(FILE *fp, es_str_t **str) es_addChar(str, '\0'); } +struct objlst* +objlstNew(struct cnfobj *o) +{ + struct objlst *lst; + + if((lst = malloc(sizeof(struct objlst))) != NULL) { + lst->next = NULL; + lst->obj = o; + } +dbgprintf("AAAA: creating new objlst\n"); +cnfobjPrint(o); + + return lst; +} + +/* add object to end of object list, always returns pointer to root object */ +struct objlst* +objlstAdd(struct objlst *root, struct cnfobj *o) +{ + struct objlst *l; + struct objlst *newl; + + newl = objlstNew(o); + if(root == 0) { + root = newl; + } else { /* find last, linear search ok, as only during config phase */ + for(l = root ; l->next != NULL ; l = l->next) + ; + l->next = newl; + } + return root; +} + +void +objlstDestruct(struct objlst *lst) +{ + struct objlst *toDel; + + while(lst != NULL) { + toDel = lst; + lst = lst->next; + cnfobjDestruct(toDel->obj); + free(toDel); + } +} + +void +objlstPrint(struct objlst *lst) +{ + dbgprintf("objlst %p:\n", lst); + while(lst != NULL) { + cnfobjPrint(lst->obj); + lst = lst->next; + } +} + struct nvlst* nvlstNew(es_str_t *name, es_str_t *value) { @@ -576,6 +637,7 @@ cnfobjNew(enum cnfobjType objType, struct nvlst *lst) nvlstChkDupes(lst); o->objType = objType; o->nvlst = lst; + o->subobjs = NULL; } return o; @@ -586,6 +648,7 @@ cnfobjDestruct(struct cnfobj *o) { if(o != NULL) { nvlstDestruct(o->nvlst); + objlstDestruct(o->subobjs); free(o); } } @@ -677,7 +740,6 @@ cnfactlstReverse(struct cnfactlst *actlst) prev = NULL; while(actlst != NULL) { - //dbgprintf("reversing: %s\n", actlst->data.legActLine); curr = actlst; actlst = actlst->next; curr->syslines = cnfcfsyslinelstReverse(curr->syslines); @@ -749,8 +811,7 @@ var2Number(struct var *r, int *bSuccess) return n; } -/* ensure that retval is a string; if string is no number, - * emit error message and set number to 0. +/* ensure that retval is a string */ static inline es_str_t * var2String(struct var *r, int *bMustFree) @@ -774,6 +835,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr) int bMustFree; es_str_t *estr; char *str; + int retval; struct var r[CNFFUNC_MAX_ARGS]; dbgprintf("rainerscript: executing function id %d\n", func->fID); @@ -816,6 +878,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr) es_tolower(estr); ret->datatype = 'S'; ret->d.estr = estr; + if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr); break; case CNFFUNC_CSTR: cnfexprEval(func->expr[0], &r[0], usrptr); @@ -824,6 +887,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr) estr = es_strdup(estr); ret->datatype = 'S'; ret->d.estr = estr; + if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr); break; case CNFFUNC_CNUM: if(func->expr[0]->nodetype == 'N') { @@ -838,6 +902,24 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr) } ret->datatype = 'N'; break; + case CNFFUNC_RE_MATCH: + cnfexprEval(func->expr[0], &r[0], usrptr); + estr = var2String(&r[0], &bMustFree); + str = es_str2cstr(estr, NULL); + retval = regexp.regexec(func->funcdata, str, 0, NULL, 0); + if(retval == 0) + ret->d.n = 1; + else { + ret->d.n = 0; + if(retval != REG_NOMATCH) { + DBGPRINTF("re_match: regexec returned error %d\n", retval); + } + } + ret->datatype = 'N'; + if(bMustFree) es_deleteStr(estr); + free(str); + if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr); + break; default: if(Debug) { fname = es_str2cstr(func->fname, NULL); @@ -891,7 +973,7 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr) int bMustFree, bMustFree2; long long n_r, n_l; - //dbgprintf("eval expr %p, type '%c'(%u)\n", expr, expr->nodetype, expr->nodetype); + dbgprintf("eval expr %p, type '%c'(%u)\n", expr, expr->nodetype, expr->nodetype); switch(expr->nodetype) { /* note: comparison operations are extremely similar. The code can be copyied, only * places flagged with "CMP" need to be changed. @@ -1199,6 +1281,78 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr) } } +//--------------------------------------------------------- + +static inline void +cnffuncDestruct(struct cnffunc *func) +{ + unsigned short i; + + for(i = 0 ; i < func->nParams ; ++i) { + cnfexprDestruct(func->expr[i]); + } + /* some functions require special destruction */ + switch(func->fID) { + case CNFFUNC_RE_MATCH: + regexp.regfree(func->funcdata); + free(func->funcdata); + free(func->fname); + break; + default:break; + } +} + +/* Destruct an expression and all sub-expressions contained in it. + */ +void +cnfexprDestruct(struct cnfexpr *expr) +{ + + dbgprintf("cnfexprDestruct expr %p, type '%c'(%u)\n", expr, expr->nodetype, expr->nodetype); + switch(expr->nodetype) { + case CMP_NE: + case CMP_EQ: + case CMP_LE: + case CMP_GE: + case CMP_LT: + case CMP_GT: + case CMP_STARTSWITH: + case CMP_STARTSWITHI: + case CMP_CONTAINS: + case CMP_CONTAINSI: + case OR: + case AND: + case '+': + case '-': + case '*': + case '/': + case '%': /* binary */ + cnfexprDestruct(expr->l); + cnfexprDestruct(expr->r); + break; + case NOT: + case 'M': /* unary */ + cnfexprDestruct(expr->r); + break; + case 'N': + break; + case 'S': + es_deleteStr(((struct cnfstringval*)expr)->estr); + break; + case 'V': + free(((struct cnfvar*)expr)->name); + break; + case 'F': + cnffuncDestruct((struct cnffunc*)expr); + break; + default:break; + } + free(expr); +} + +//---- END + + /* Evaluate an expression as a bool. This is added because expressions are * mostly used inside filters, and so this function is quite common and * important. @@ -1488,11 +1642,53 @@ funcName2ID(es_str_t *fname, unsigned short nParams) return CNFFUNC_INVALID; } return CNFFUNC_CNUM; + } else if(!es_strbufcmp(fname, (unsigned char*)"re_match", sizeof("re_match") - 1)) { + if(nParams != 2) { + parser_errmsg("number of parameters for re_match() must be two " + "but is %d.", nParams); + return CNFFUNC_INVALID; + } + return CNFFUNC_RE_MATCH; } else { return CNFFUNC_INVALID; } } + +static inline rsRetVal +initFunc_re_match(struct cnffunc *func) +{ + rsRetVal localRet; + char *regex = NULL; + regex_t *re; + DEFiRet; + + func->funcdata = NULL; + if(func->expr[1]->nodetype != 'S') { + parser_errmsg("param 2 of re_match() must be a constant string"); + FINALIZE; + } + + CHKmalloc(re = malloc(sizeof(regex_t))); + func->funcdata = re; + + regex = es_str2cstr(((struct cnfstringval*) func->expr[1])->estr, NULL); + + if((localRet = objUse(regexp, LM_REGEXP_FILENAME)) == RS_RET_OK) { + if(regexp.regcomp(re, (char*) regex, REG_EXTENDED) != 0) { + parser_errmsg("cannot compile regex '%s'", regex); + ABORT_FINALIZE(RS_RET_ERR); + } + } else { /* regexp object could not be loaded */ + parser_errmsg("could not load regex support - regex ignored"); + ABORT_FINALIZE(RS_RET_ERR); + } + +finalize_it: + free(regex); + RETiRet; +} + struct cnffunc * cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst) { @@ -1519,6 +1715,14 @@ cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst) param = param->next; free(toDel); } + /* some functions require special initialization */ + switch(func->fID) { + case CNFFUNC_RE_MATCH: + /* need to compile the regexp in param 2, so this MUST be a constant */ + initFunc_re_match(func); + break; + default:break; + } } return func; } @@ -1617,6 +1821,15 @@ cstrPrint(char *text, es_str_t *estr) free(str); } +/* init must be called once before any parsing of the script files start */ +rsRetVal +initRainerscript(void) +{ + DEFiRet; + CHKiRet(objGetObjInterface(&obj)); +finalize_it: + RETiRet; +} /* we need a function to check for octal digits */ static inline int diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index a52b3fa8..f5627597 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -16,6 +16,9 @@ enum cnfobjType { CNFOBJ_GLOBAL, CNFOBJ_INPUT, CNFOBJ_MODULE, + CNFOBJ_TPL, + CNFOBJ_PROPERTY, + CNFOBJ_CONSTANT, CNFOBJ_INVALID = 0 }; @@ -35,6 +38,15 @@ cnfobjType2str(enum cnfobjType ot) case CNFOBJ_MODULE: return "module"; break; + case CNFOBJ_TPL: + return "template"; + break; + case CNFOBJ_PROPERTY: + return "property"; + break; + case CNFOBJ_CONSTANT: + return "constant"; + break; default:return "error: invalid cnfobjType"; } } @@ -60,6 +72,12 @@ struct var { struct cnfobj { enum cnfobjType objType; struct nvlst *nvlst; + struct objlst *subobjs; +}; + +struct objlst { + struct objlst *next; + struct cnfobj *obj; }; struct nvlst { @@ -163,7 +181,8 @@ enum cnffuncid { CNFFUNC_GETENV, CNFFUNC_TOLOWER, CNFFUNC_CSTR, - CNFFUNC_CNUM + CNFFUNC_CNUM, + CNFFUNC_RE_MATCH }; struct cnffunc { @@ -171,6 +190,7 @@ struct cnffunc { es_str_t *fname; unsigned short nParams; enum cnffuncid fID; /* function ID for built-ins, 0 means use name */ + void *funcdata; /* global data for function-specific use (e.g. compiled regex) */ struct cnfexpr *expr[]; }; @@ -216,6 +236,9 @@ struct cnfparamvals { /* the values we obtained for param descr. */ int cnfParseBuffer(char *buf, unsigned lenBuf); void readConfFile(FILE *fp, es_str_t **str); +struct objlst* objlstNew(struct cnfobj *obj); +void objlstDestruct(struct objlst *lst); +void objlstPrint(struct objlst *lst); struct nvlst* nvlstNew(es_str_t *name, es_str_t *value); void nvlstDestruct(struct nvlst *lst); void nvlstPrint(struct nvlst *lst); @@ -233,6 +256,7 @@ struct cnfexpr* cnfexprNew(unsigned nodetype, struct cnfexpr *l, struct cnfexpr void cnfexprPrint(struct cnfexpr *expr, int indent); void cnfexprEval(struct cnfexpr *expr, struct var *ret, void *pusr); int cnfexprEvalBool(struct cnfexpr *expr, void *usrptr); +void cnfexprDestruct(struct cnfexpr *expr); struct cnfnumval* cnfnumvalNew(long long val); struct cnfstringval* cnfstringvalNew(es_str_t *estr); struct cnfrule * cnfruleNew(enum cnfFiltType filttype, struct cnfactlst *actlst); @@ -249,6 +273,7 @@ void cnfparamsPrint(struct cnfparamblk *params, struct cnfparamvals *vals); void varDelete(struct var *v); void cnfparamvalsDestruct(struct cnfparamvals *paramvals, struct cnfparamblk *blk); void cnfcfsyslinelstDestruct(struct cnfcfsyslinelst *cfslst); +rsRetVal initRainerscript(void); void unescapeStr(uchar *s, int len); /* debug helper */ |