1 /* rsyslog rainerscript definitions
2  *
3  * Copyright 2011-2018 Rainer Gerhards
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *       -or-
11  *       see COPYING.ASL20 in the source distribution
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 #ifndef INC_UTILS_H
20 #define INC_UTILS_H
21 #include <stdio.h>
22 #include <libestr.h>
23 #include <typedefs.h>
24 #include <sys/types.h>
25 #include <json.h>
26 #include <regex.h>
27 #include "typedefs.h"
28 
29 #define LOG_NFACILITIES 24+1 /* we copy&paste this as including rsyslog.h gets us in off64_t trouble... :-( */
30 #define CNFFUNC_MAX_ARGS 32
31 	/**< maximum number of arguments that any function can have (among
32 	 *   others, this is used to size data structures).
33 	 */
34 
35 enum cnfobjType {
36 	CNFOBJ_ACTION,
37 	CNFOBJ_RULESET,
38 	CNFOBJ_GLOBAL,
39 	CNFOBJ_INPUT,
40 	CNFOBJ_MODULE,
41 	CNFOBJ_TPL,
42 	CNFOBJ_PROPERTY,
43 	CNFOBJ_CONSTANT,
44 	CNFOBJ_MAINQ,
45 	CNFOBJ_LOOKUP_TABLE,
46 	CNFOBJ_PARSER,
47 	CNFOBJ_TIMEZONE,
48 	CNFOBJ_DYN_STATS,
49 	CNFOBJ_PERCTILE_STATS,
50 	CNFOBJ_INVALID = 0
51 };
52 
53 const char* cnfobjType2str(enum cnfobjType ot);
54 
55 /* a variant type, for example used for expression evaluation
56  * 2011-07-15/rger: note that there exists a "legacy" object var,
57  * which implements the same idea, but in a suboptimal manner. I have
58  * stipped this down as much as possible, but will keep it for a while
59  * to avoid unnecessary complexity during development. TODO: in the long
60  * term, var shall be replaced by struct svar.
61  */
62 struct svar{
63 	union {
64 		es_str_t *estr;
65 		struct cnfarray *ar;
66 		long long n;
67 		struct json_object *json;
68 	} d;
69 	char datatype; /* 'N' number, 'S' string, 'J' JSON, 'A' array
70 			* Note: 'A' is only supported during config phase
71 			*/
72 };
73 
74 struct cnfobj {
75 	enum cnfobjType objType;
76 	struct nvlst *nvlst;
77 	struct objlst *subobjs;
78 	struct cnfstmt *script;
79 };
80 
81 struct objlst {
82 	struct objlst *next;
83 	struct cnfobj *obj;
84 };
85 
86 struct nvlst {
87 	struct nvlst *next;
88 	es_str_t *name;
89 	struct svar val;
90 	unsigned char bUsed;
91 	/**< was this node used during config processing? If not, this
92 	 *   indicates an error. After all, the user specified a setting
93 	 *   that the software does not know.
94 	 */
95 };
96 
97 /* the following structures support expressions, and may (very much later
98  * be the sole foundation for the AST.
99  *
100  * nodetypes (list not yet complete)
101  * A - (string) array
102  * F - function
103  * N - number
104  * P - fparamlst
105  * R - rule
106  * S - string
107  * V - var
108  * ... plus the S_* #define's below:
109  */
110 #define S_STOP 4000
111 #define S_PRIFILT 4001
112 #define S_PROPFILT 4002
113 #define S_IF 4003
114 #define S_ACT 4004
115 #define S_NOP 4005	/* usually used to disable some statement */
116 #define S_SET 4006
117 #define S_UNSET 4007
118 #define S_CALL 4008
119 #define S_FOREACH 4009
120 #define S_RELOAD_LOOKUP_TABLE 4010
121 #define S_CALL_INDIRECT 4011
122 #define S_FUNC_EXISTS 4012 /* special case function which must get varname only */
123 
124 enum cnfFiltType { CNFFILT_NONE, CNFFILT_PRI, CNFFILT_PROP, CNFFILT_SCRIPT };
125 const char* cnfFiltType2str(const enum cnfFiltType filttype);
126 
127 
128 struct cnfstmt {
129 	unsigned nodetype;
130 	struct cnfstmt *next;
131 	uchar *printable; /* printable text for debugging */
132 	union {
133 		struct {
134 			struct cnfexpr *expr;
135 			struct cnfstmt *t_then;
136 			struct cnfstmt *t_else;
137 		} s_if;
138 		struct {
139 			uchar *varname;
140 			struct cnfexpr *expr;
141 			int force_reset;
142 		} s_set;
143 		struct {
144 			uchar *varname;
145 		} s_unset;
146 		struct {
147 			es_str_t *name;
148 			struct cnfstmt *stmt;
149 			ruleset_t *ruleset;	/* non-NULL if the ruleset has a queue assigned */
150 		} s_call;
151 		struct {
152 			struct cnfexpr *expr;
153 		} s_call_ind;
154 		struct {
155 			uchar pmask[LOG_NFACILITIES+1];	/* priority mask */
156 			struct cnfstmt *t_then;
157 			struct cnfstmt *t_else;
158 		} s_prifilt;
159 		struct {
160 			fiop_t operation;
161 			regex_t *regex_cache;/* cache for compiled REs, if used */
162 			struct cstr_s *pCSCompValue;/* value to "compare" against */
163 			sbool isNegated;
164 			msgPropDescr_t prop; /* requested property */
165 			struct cnfstmt *t_then;
166 			struct cnfstmt *t_else;
167 		} s_propfilt;
168 		struct action_s *act;
169 	struct {
170 			struct cnfitr *iter;
171 			struct cnfstmt *body;
172 		} s_foreach;
173 	struct {
174 			lookup_ref_t *table;
175 			uchar *table_name;
176 			uchar *stub_value;
177 		} s_reload_lookup_table;
178 	} d;
179 };
180 
181 struct cnfexpr {
182 	unsigned nodetype;
183 	struct cnfexpr *l;
184 	struct cnfexpr *r;
185 } __attribute__((aligned (8)));
186 
187 struct cnfitr {
188 	char* var;
189 	struct cnfexpr* collection;
190 } __attribute__((aligned (8)));
191 
192 struct cnfnumval {
193 	unsigned nodetype;
194 	long long val;
195 } __attribute__((aligned (8)));
196 
197 struct cnfstringval {
198 	unsigned nodetype;
199 	es_str_t *estr;
200 } __attribute__((aligned (8)));
201 
202 struct cnfvar {
203 	unsigned nodetype;
204 	char *name;
205 	msgPropDescr_t prop;
206 } __attribute__((aligned (8)));
207 
208 struct cnfarray {
209 	unsigned nodetype;
210 	int nmemb;
211 	es_str_t **arr;
212 } __attribute__((aligned (8)));
213 
214 struct cnffparamlst {
215 	unsigned nodetype; /* P */
216 	struct cnffparamlst *next;
217 	struct cnfexpr *expr;
218 } __attribute__((aligned (8)));
219 
220 enum cnffuncid {
221 	CNFFUNC_INVALID = 0, /**< defunct entry, do not use (should normally not be present) */
222 	CNFFUNC_NAME = 1,   /**< use name to call function (for future use) */
223 	CNFFUNC_STRLEN,
224 	CNFFUNC_SUBSTRING,
225 	CNFFUNC_GETENV,
226 	CNFFUNC_TOLOWER,
227 	CNFFUNC_CSTR,
228 	CNFFUNC_CNUM,
229 	CNFFUNC_RE_MATCH,
230 	CNFFUNC_RE_EXTRACT,
231 	CNFFUNC_FIELD,
232 	CNFFUNC_PRIFILT,
233 	CNFFUNC_LOOKUP,
234 	CNFFUNC_EXEC_TEMPLATE,
235 	CNFFUNC_REPLACE,
236 	CNFFUNC_WRAP,
237 	CNFFUNC_RANDOM,
238 	CNFFUNC_DYN_INC,
239 	CNFFUNC_IPV42NUM,
240 	CNFFUNC_NUM2IPV4,
241 	CNFFUNC_INT2HEX,
242 	CNFFUNC_LTRIM,
243 	CNFFUNC_RTRIM,
244 	CNFFUNC_FORMAT_TIME,
245 	CNFFUNC_PARSE_TIME,
246 	CNFFUNC_PARSE_JSON,
247 	CNFFUNC_GET_PROPERTY,
248 	CNFFUNC_PREVIOUS_ACTION_SUSPENDED,
249 	CNFFUNC_SCRIPT_ERROR,
250 	CNFFUNC_HTTP_REQUEST,
251 	CNFFUNC_IS_TIME
252 };
253 
254 typedef struct cnffunc cnffunc_t;
255 typedef void (*rscriptFuncPtr) (cnffunc_t *, struct svar *, void *, wti_t *);
256 
257 struct cnffunc {
258 	unsigned nodetype;
259 	es_str_t *fname;
260 	unsigned short nParams;
261 	rscriptFuncPtr fPtr;
262 	void *funcdata;	/* global data for function-specific use (e.g. compiled regex) */
263 	uint8_t destructable_funcdata;
264 	struct cnfexpr *expr[];
265 } __attribute__((aligned (8)));
266 
267 
268 struct cnffuncexists {
269 	unsigned nodetype;
270 	const char *varname;
271 	msgPropDescr_t prop;
272 } __attribute__((aligned (8)));
273 
274 struct scriptFunct {
275 	const char *fname;
276 	unsigned short minParams;
277 	unsigned short maxParams;
278 	rscriptFuncPtr fPtr;
279 	rsRetVal (*initFunc) (struct cnffunc *);
280 	void (*destruct) (struct cnffunc *);
281 	/* currently no optimizer entrypoint, may be added later.
282 	 * Since the optimizer needs metadata about functions, it does
283 	 * not seem practical to add such a function at the current state
284 	 */
285 };
286 
287 
288 /* future extensions
289 <code>
290 struct x {
291 	int nodetype;
292 };
293 </code>
294 */
295 
296 
297 /* the following defines describe the parameter block for puling
298  * config parameters. Note that the focus is on ease and saveness of
299  * use, not performance. For example, we address parameters by name
300  * instead of index, because the former is less error-prone. The (severe)
301  * performance hit does not matter, as it is a one-time hit during config
302  * load but never during actual processing. So there is really no reason
303  * to care.
304  */
305 struct cnfparamdescr { /* first the param description */
306 	const char *name;/**< not a es_str_t to ease definition in code */
307 	ecslCmdHdrlType type;
308 	unsigned flags;
309 };
310 /* flags for cnfparamdescr: */
311 #define CNFPARAM_REQUIRED	0x0001
312 #define CNFPARAM_DEPRECATED	0x0002
313 
314 struct cnfparamblk { /* now the actual param block use in API calls */
315 	unsigned short version;
316 	unsigned short nParams;
317 	struct cnfparamdescr *descr;
318 };
319 #define CNFPARAMBLK_VERSION 1
320 	/**< caller must have same version as engine -- else things may
321 	 * be messed up. But note that we may support multiple versions
322 	 * inside the engine, if at some later stage we want to do
323 	 * that. -- rgerhards, 2011-07-15
324 	 */
325 struct cnfparamvals { /* the values we obtained for param descr. */
326 	struct svar val;
327 	unsigned char bUsed;
328 };
329 
330 struct funcData_prifilt {
331 	uchar pmask[LOG_NFACILITIES+1];	/* priority mask */
332 };
333 
334 /* script errno-like interface error codes: */
335 #define RS_SCRIPT_EOK		0
336 #define RS_SCRIPT_EINVAL	1
337 
338 void varFreeMembers(const struct svar *r);
339 rsRetVal addMod2List(const int version, struct scriptFunct *functArray);
340 void readConfFile(FILE *fp, es_str_t **str);
341 struct objlst* objlstNew(struct cnfobj *obj);
342 void objlstDestruct(struct objlst *lst);
343 void objlstPrint(struct objlst *lst);
344 struct nvlst* nvlstNewArray(struct cnfarray *ar);
345 struct nvlst* nvlstNewStr(es_str_t *value);
346 struct nvlst* nvlstNewStrBackticks(es_str_t *const value);
347 struct nvlst* nvlstSetName(struct nvlst *lst, es_str_t *name);
348 void nvlstDestruct(struct nvlst *lst);
349 void nvlstPrint(struct nvlst *lst);
350 void nvlstChkUnused(struct nvlst *lst);
351 struct nvlst* nvlstFindName(struct nvlst *lst, es_str_t *name);
352 int nvlstChkDisabled(struct nvlst *lst);
353 struct cnfobj* cnfobjNew(enum cnfobjType objType, struct nvlst *lst);
354 void cnfobjDestruct(struct cnfobj *o);
355 void cnfobjPrint(struct cnfobj *o);
356 struct cnfexpr* cnfexprNew(unsigned nodetype, struct cnfexpr *l, struct cnfexpr *r);
357 void cnfexprPrint(struct cnfexpr *expr, int indent);
358 void cnfexprEval(const struct cnfexpr *const expr, struct svar *ret, void *pusr, wti_t *pWti);
359 int cnfexprEvalBool(struct cnfexpr *expr, void *usrptr, wti_t *pWti);
360 struct json_object* cnfexprEvalCollection(struct cnfexpr * const expr, void * const usrptr, wti_t *pWti);
361 void cnfexprDestruct(struct cnfexpr *expr);
362 struct cnfnumval* cnfnumvalNew(long long val);
363 struct cnfstringval* cnfstringvalNew(es_str_t *estr);
364 struct cnfvar* cnfvarNew(char *name);
365 struct cnffunc * cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst);
366 struct cnffuncexists * cnffuncexistsNew(const char *varname);
367 struct cnffparamlst * cnffparamlstNew(struct cnfexpr *expr, struct cnffparamlst *next);
368 int cnfDoInclude(const char *name, const int optional);
369 int cnfparamGetIdx(struct cnfparamblk *params, const char *name);
370 struct cnfparamvals* nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params,
371 	       struct cnfparamvals *vals);
372 void cnfparamsPrint(const struct cnfparamblk *params, const struct cnfparamvals *vals);
373 int cnfparamvalsIsSet(struct cnfparamblk *params, struct cnfparamvals *vals);
374 void varDelete(const struct svar *v);
375 void cnfparamvalsDestruct(const struct cnfparamvals *paramvals, const struct cnfparamblk *blk);
376 struct cnfstmt * cnfstmtNew(unsigned s_type);
377 struct cnfitr * cnfNewIterator(char *var, struct cnfexpr *collection);
378 void cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree);
379 void cnfstmtPrint(struct cnfstmt *stmt, int indent);
380 struct cnfstmt* scriptAddStmt(struct cnfstmt *root, struct cnfstmt *s);
381 struct objlst* objlstAdd(struct objlst *root, struct cnfobj *o);
382 char *rmLeadingSpace(char *s);
383 struct cnfstmt * cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then);
384 struct cnfstmt * cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then);
385 struct cnfstmt * cnfstmtNewAct(struct nvlst *lst);
386 struct cnfstmt * cnfstmtNewLegaAct(char *actline);
387 struct cnfstmt * cnfstmtNewSet(char *var, struct cnfexpr *expr, int force_reset);
388 struct cnfstmt * cnfstmtNewUnset(char *var);
389 struct cnfstmt * cnfstmtNewCall(es_str_t *name);
390 struct cnfstmt * cnfstmtNewContinue(void);
391 struct cnfstmt * cnfstmtNewReloadLookupTable(struct cnffparamlst *fparams);
392 void cnfstmtDestructLst(struct cnfstmt *root);
393 struct cnfstmt *cnfstmtOptimize(struct cnfstmt *root);
394 struct cnfarray* cnfarrayNew(es_str_t *val);
395 struct cnfarray* cnfarrayDup(struct cnfarray *old);
396 struct cnfarray* cnfarrayAdd(struct cnfarray *ar, es_str_t *val);
397 void cnfarrayContentDestruct(struct cnfarray *ar);
398 const char* getFIOPName(unsigned iFIOP);
399 rsRetVal initRainerscript(void);
400 void unescapeStr(uchar *s, int len);
401 const char * tokenval2str(int tok);
402 uchar* var2CString(struct svar *__restrict__ const r, int *__restrict__ const bMustFree);
403 long long var2Number(struct svar *r, int *bSuccess);
404 void includeProcessCnf(struct nvlst *const lst);
405 
406 /* debug helper */
407 void cstrPrint(const char *text, es_str_t *estr);
408 
409 #endif
410