1 /* $Id$ */
2 /*
3 * sp_dynamic.c
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License Version 2 as
7 * published by the Free Software Foundation. You may not use, modify or
8 * distribute this program under any other version of the GNU General
9 * Public License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
21 * Copyright (C) 2005-2013 Sourcefire, Inc.
22 *
23 * Author: Steven Sturges
24 *
25 * Purpose:
26 * Supports dynamically loaded detection plugin to check the packet.
27 *
28 * does not update the doe_ptr
29 *
30 * Arguments:
31 * Required:
32 * None
33 * Optional:
34 * None
35 *
36 * sample rules:
37 * alert tcp any any -> any any (msg: "DynamicRuleCheck"; );
38 *
39 * Effect:
40 *
41 * Returns 1 if the dynamic detection plugin matches, 0 if it doesn't.
42 *
43 * Comments:
44 *
45 *
46 */
47 #ifdef HAVE_CONFIG_H
48 #include "config.h"
49 #endif
50
51 #include <sys/types.h>
52 #include <stdlib.h>
53 #include <ctype.h>
54 #ifdef HAVE_STRINGS_H
55 #include <strings.h>
56 #endif
57 #include <errno.h>
58
59 #include "sf_types.h"
60 #include "rules.h"
61 #include "treenodes.h"
62 #include "decode.h"
63 #include "bitop_funcs.h"
64 #include "plugbase.h"
65 #include "parser.h"
66 #include "snort_debug.h"
67 #include "util.h"
68 #include "plugin_enum.h"
69 #include "sp_dynamic.h"
70 #include "sf_dynamic_engine.h"
71 #include "detection-plugins/sp_flowbits.h"
72 #include "detection-plugins/sp_asn1_detect.h"
73 #include "dynamic-plugins/sf_engine/sf_snort_plugin_api.h"
74 #include "sf_convert_dynamic.h"
75 #include "sfhashfcn.h"
76 #include "sp_preprocopt.h"
77 #include "sfutil/sf_base64decode.h"
78 #include "detection_util.h"
79 #include "stream_api.h"
80
81 #include "snort.h"
82 #include "profiler.h"
83 #include "reload.h"
84
85 #ifdef PERF_PROFILING
86 PreprocStats dynamicRuleEvalPerfStats;
87 extern PreprocStats ruleOTNEvalPerfStats;
88 #endif
89
90 extern SFGHASH *flowbits_hash;
91 extern SF_QUEUE *flowbits_bit_queue;
92 extern uint32_t flowbits_count;
93
94 void DynamicInit(struct _SnortConfig *, char *, OptTreeNode *, int);
95 void DynamicParse(char *, OptTreeNode *);
96 int DynamicCheck(void *option_data, Packet *p);
97
DynamicRuleHash(void * d)98 uint32_t DynamicRuleHash(void *d)
99 {
100 uint32_t a,b,c;
101 DynamicData *dynData = (DynamicData *)d;
102 #if (defined(__ia64) || defined(__amd64) || defined(_LP64))
103 {
104 /* Cleanup warning because of cast from 64bit ptr to 32bit int
105 * warning on 64bit OSs */
106 uint64_t ptr; /* Addresses are 64bits */
107 ptr = (uint64_t)dynData->contextData;
108 a = (ptr >> 32);
109 b = (ptr & 0xFFFFFFFF);
110
111 ptr = (uint64_t)dynData->checkFunction;
112 c = (ptr >> 32);
113
114 mix (a,b,c);
115
116 a += (ptr & 0xFFFFFFFF);
117
118 ptr = (uint64_t)dynData->hasOptionFunction;
119 b += (ptr >> 32);
120 c += (ptr & 0xFFFFFFFF);
121
122 ptr = (uint64_t)dynData->getDynamicContents;
123 a += (ptr >> 32);
124 b += (ptr & 0xFFFFFFFF);
125 c += dynData->contentFlags;
126
127 mix (a,b,c);
128
129 a += RULE_OPTION_TYPE_DYNAMIC;
130 }
131 #else
132 {
133 a = (uint32_t)dynData->contextData;
134 b = (uint32_t)dynData->checkFunction;
135 c = (uint32_t)dynData->hasOptionFunction;
136 mix(a,b,c);
137
138 a += (uint32_t)dynData->getDynamicContents;
139 b += dynData->contentFlags;
140 c += RULE_OPTION_TYPE_DYNAMIC;
141 }
142 #endif
143
144 final(a,b,c);
145
146 return c;
147 }
148
DynamicRuleCompare(void * l,void * r)149 int DynamicRuleCompare(void *l, void *r)
150 {
151 DynamicData *left = (DynamicData *)l;
152 DynamicData *right = (DynamicData *)r;
153
154 if (!left || !right)
155 return DETECTION_OPTION_NOT_EQUAL;
156
157 if ((left->contextData == right->contextData) &&
158 (left->checkFunction == right->checkFunction) &&
159 (left->hasOptionFunction == right->hasOptionFunction) &&
160 (left->getDynamicContents == right->getDynamicContents) &&
161 (left->contentFlags == right->contentFlags))
162 {
163 return DETECTION_OPTION_EQUAL;
164 }
165
166 return DETECTION_OPTION_NOT_EQUAL;
167 }
168
169 /****************************************************************************
170 *
171 * Function: SetupDynamic()
172 *
173 * Purpose: Load it up
174 *
175 * Arguments: None.
176 *
177 * Returns: void function
178 *
179 ****************************************************************************/
SetupDynamic(void)180 void SetupDynamic(void)
181 {
182 /* map the keyword to an initialization/processing function */
183 RegisterRuleOption("dynamic", DynamicInit, NULL, OPT_TYPE_DETECTION, NULL);
184
185 #ifdef PERF_PROFILING
186 RegisterPreprocessorProfile("dynamic_rule", &dynamicRuleEvalPerfStats, 3, &ruleOTNEvalPerfStats, NULL);
187 #endif
188 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN,"Plugin: Dynamic Setup\n"););
189 }
190
191
192 /****************************************************************************
193 *
194 * Function: DynamicInit(struct _SnortConfig *, char *, OptTreeNode *)
195 *
196 * Purpose: Configuration function. Handles parsing the rule
197 * information and attaching the associated detection function to
198 * the OTN.
199 *
200 * Arguments: data => rule arguments/data
201 * otn => pointer to the current rule option list node
202 * protocol => protocol the rule is on (we don't care in this case)
203 *
204 * Returns: void function
205 *
206 ****************************************************************************/
DynamicInit(struct _SnortConfig * sc,char * data,OptTreeNode * otn,int protocol)207 void DynamicInit(struct _SnortConfig *sc, char *data, OptTreeNode *otn, int protocol)
208 {
209 OptFpList *fpl;
210 DynamicData *dynData;
211 void *option_dup;
212
213 dynData = (DynamicData *)otn->ds_list[PLUGIN_DYNAMIC];
214
215 fpl = AddOptFuncToList(DynamicCheck, otn);
216
217 /* attach it to the context node so that we can call each instance
218 * individually
219 */
220 fpl->context = (void *) dynData;
221
222 if (add_detection_option(sc, RULE_OPTION_TYPE_DYNAMIC, (void *)dynData, &option_dup) == DETECTION_OPTION_EQUAL)
223 {
224 free(dynData);
225 fpl->context = dynData = option_dup;
226 }
227 fpl->type = RULE_OPTION_TYPE_DYNAMIC;
228 }
229
230 /****************************************************************************
231 *
232 * Function: DynamicCheck(char *, OptTreeNode *, OptFpList *)
233 *
234 * Purpose: Use this function to perform the particular detection routine
235 * that this rule keyword is supposed to encompass.
236 *
237 * Arguments: p => pointer to the decoded packet
238 * otn => pointer to the current rule's OTN
239 * fp_list => pointer to the function pointer list
240 *
241 * Returns: If the detection test fails, this function *must* return a zero!
242 * On success, it calls the next function in the detection list
243 *
244 ****************************************************************************/
DynamicCheck(void * option_data,Packet * p)245 int DynamicCheck(void *option_data, Packet *p)
246 {
247 DynamicData *dynData = (DynamicData *)option_data;
248 int result = 0;
249 PROFILE_VARS;
250
251 PREPROC_PROFILE_START(dynamicRuleEvalPerfStats);
252
253 if (!dynData)
254 {
255 LogMessage("Dynamic Rule with no context data available");
256 PREPROC_PROFILE_END(dynamicRuleEvalPerfStats);
257 return DETECTION_OPTION_NO_MATCH;
258 }
259
260 result = dynData->checkFunction((void *)p, dynData->contextData);
261 if (result)
262 {
263 PREPROC_PROFILE_END(dynamicRuleEvalPerfStats);
264 return result;
265 }
266
267 /* Detection failed */
268 PREPROC_PROFILE_END(dynamicRuleEvalPerfStats);
269 return DETECTION_OPTION_NO_MATCH;
270 }
271
DynamicRuleListFree(DynamicRuleNode * head)272 void DynamicRuleListFree(DynamicRuleNode *head)
273 {
274 while (head != NULL)
275 {
276 DynamicRuleNode *tmp = head->next;
277
278 /*
279 * Clean up will be executed only when snort exits or
280 * dynamic libs have changed
281 */
282 if (head->freeFunc)
283 {
284 head->freeFunc((void *)head->rule);
285 }
286
287 free(head);
288 head = tmp;
289 }
290 }
291
292 /****************************************************************************
293 *
294 * Function: RegisterDynamicRule(Snortconfig *, uint32_t, uint32_t, char *,
295 * void *,
296 * OTNCheckFunction, int, GetFPContentFunction)
297 *
298 * Purpose: A dynamically loaded detection engine library can use this
299 * function to register a dynamically loaded rule/preprocessor. It
300 * provides a pointer to context specific data for the
301 * rule/preprocessor and a reference to the function used to
302 * check the rule.
303 *
304 * Arguments: sid => Signature ID
305 * gid => Generator ID
306 * info => context specific data
307 * chkFunc => Function to call to check if the rule matches
308 * has*Funcs => Functions used to categorize this rule
309 * contentFlags => Flags indicating which contents are available
310 * contentsFunc => Function to call to get list of rule contents
311 *
312 * Returns: 0 on success
313 *
314 ****************************************************************************/
RegisterDynamicRule(SnortConfig * sc,uint32_t sid,uint32_t gid,void * info,OTNCheckFunction chkFunc,OTNHasFunction hasFunc,int contentFlags,GetDynamicContentsFunction contentsFunc,RuleFreeFunc freeFunc,GetDynamicPreprocOptFpContentsFunc preprocFpFunc)315 int RegisterDynamicRule(
316 SnortConfig *sc,
317 uint32_t sid,
318 uint32_t gid,
319 void *info,
320 OTNCheckFunction chkFunc,
321 OTNHasFunction hasFunc,
322 int contentFlags,
323 GetDynamicContentsFunction contentsFunc,
324 RuleFreeFunc freeFunc,
325 GetDynamicPreprocOptFpContentsFunc preprocFpFunc
326 )
327 {
328 DynamicData *dynData;
329 struct _OptTreeNode *otn = NULL;
330 OptFpList *idx; /* index pointer */
331 OptFpList *fpl;
332 char done_once = 0;
333 void *option_dup;
334 DynamicRuleNode *node = NULL;
335
336 if (sc == NULL)
337 {
338 FatalError("%s(%d) Snort config is NULL.\n",
339 __FILE__, __LINE__);
340 }
341
342 if ( SnortDynamicLibsChanged() || SnortIsInitializing() )
343 {
344 node = (DynamicRuleNode *)SnortAlloc(sizeof(DynamicRuleNode));
345
346 if (sc->dynamic_rules == NULL)
347 {
348 sc->dynamic_rules = node;
349 }
350 else
351 {
352 DynamicRuleNode *tmp = sc->dynamic_rules;
353
354 while (tmp->next != NULL)
355 tmp = tmp->next;
356
357 tmp->next = node;
358 }
359
360 node->rule = (Rule *)info;
361 node->chkFunc = chkFunc;
362 node->hasFunc = hasFunc;
363 node->contentFlags = contentFlags;
364 node->contentsFunc = contentsFunc;
365 node->freeFunc = freeFunc;
366 node->preprocFpContentsFunc = preprocFpFunc;
367 }
368
369 /* Get OTN/RTN from SID */
370 otn = SoRuleOtnLookup(sc->so_rule_otn_map, gid, sid);
371 if (!otn)
372 {
373 if (ScConfErrorOut())
374 {
375 FatalError("DynamicPlugin: Rule [%u:%u] not enabled in configuration.\n", gid, sid);
376 }
377 else
378 {
379 #ifndef SOURCEFIRE
380 LogMessage("DynamicPlugin: Rule [%u:%u] not enabled in "
381 "configuration, rule will not be used.\n", gid, sid);
382 #endif
383 }
384
385 return -1;
386 }
387
388 /* If this dynamic rule can be expressed as a regular rule, break it down
389 * and convert it to use the rule option tree. */
390 if (ConvertDynamicRule(sc, (Rule *)info, otn) > 0)
391 {
392 if (node != NULL)
393 node->converted = 1;
394
395 return 0;
396 }
397
398 /* allocate the data structure and attach it to the
399 * rule's data struct list */
400 dynData = (DynamicData *)SnortAlloc(sizeof(DynamicData));
401 dynData->contextData = info;
402 dynData->checkFunction = chkFunc;
403 dynData->hasOptionFunction = hasFunc;
404 dynData->getDynamicContents = contentsFunc;
405 dynData->contentFlags = contentFlags;
406 dynData->getPreprocFpContents = preprocFpFunc;
407
408 while (otn)
409 {
410 OptFpList *prev = NULL;
411
412 otn->ds_list[PLUGIN_DYNAMIC] = (void *)dynData;
413
414 /* And add this function into the tail of the list */
415 fpl = AddOptFuncToList(DynamicCheck, otn);
416 fpl->context = dynData;
417 fpl->type = RULE_OPTION_TYPE_DYNAMIC;
418
419 if (done_once == 0)
420 {
421 if (add_detection_option(sc, RULE_OPTION_TYPE_DYNAMIC,
422 (void *)dynData, &option_dup) == DETECTION_OPTION_EQUAL)
423 {
424 free(dynData);
425 fpl->context = dynData = option_dup;
426 }
427
428 done_once = 1;
429 }
430
431 /* Arrgh. Because we read this rule in earlier, there is
432 * already an OptListEnd node there. Need to move this new
433 * one to just before it.
434 */
435 DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Adding new rule to list\n"););
436
437 /* set the index pointer to the start of this OTN's function list */
438 idx = otn->opt_func;
439
440 /* if there are no nodes on the function list... */
441 while(idx != NULL)
442 {
443 if (idx->next == fpl) /* The last one in the list before us */
444 {
445 if (prev)
446 {
447 prev->next = fpl;
448 fpl->next = idx;
449 idx->next = NULL;
450 }
451 else /* idx is the head of the list */
452 {
453 otn->opt_func = fpl;
454 fpl->next = idx;
455 idx->next = NULL;
456 }
457 }
458 prev = idx;
459 idx = idx->next;
460 }
461
462 otn = SoRuleOtnLookupNext(gid, sid);
463 }
464
465 return 0;
466 }
467
468 #ifdef SNORT_RELOAD
ReloadDynamicRules(SnortConfig * sc)469 int ReloadDynamicRules(SnortConfig *sc)
470 {
471 /*
472 * We are registering the dynamic rules from old
473 * snort config to new one. Hence this should be
474 * snort_conf. This code will not be execute if
475 * dynamic detection has changed.
476 */
477 DynamicRuleNode *node = snort_conf->dynamic_rules;
478
479 sc->dynamic_rules = snort_conf->dynamic_rules;
480 sc->loadedDetectionPlugins = snort_conf->loadedDetectionPlugins;
481 snort_conf->loadedDetectionPlugins = NULL;
482 snort_conf->dynamic_rules = NULL;
483
484 for (; node != NULL; node = node->next)
485 {
486 int i;
487
488 if (node->rule == NULL || (!node->rule->initialized) || node->rule->options == NULL)
489 continue;
490
491 for (i = 0; node->rule->options[i] != NULL; i++)
492 {
493 RuleOption *option = node->rule->options[i];
494
495 switch (option->optionType)
496 {
497 case OPTION_TYPE_FLOWBIT:
498 {
499 FlowBitsInfo *flowbits = option->option_u.flowBit;
500 flowbits = DynamicFlowbitRegister(flowbits);
501 }
502
503 break;
504
505 default:
506 break;
507 }
508 }
509
510 if (RegisterDynamicRule(sc, node->rule->info.sigID, node->rule->info.genID,
511 (void *)node->rule, node->chkFunc, node->hasFunc,
512 node->contentFlags, node->contentsFunc,
513 node->freeFunc, node->preprocFpContentsFunc) == -1)
514 {
515 for (i = 0; node->rule->options[i] != NULL; i++)
516 {
517 RuleOption *option = node->rule->options[i];
518 switch (option->optionType)
519 {
520 case OPTION_TYPE_FLOWBIT:
521 {
522 FlowBitsInfo *flowbits = option->option_u.flowBit;
523 DynamicFlowbitUnregister(flowbits);
524 }
525 break;
526
527 default:
528 break;
529 }
530 }
531
532 }
533 }
534
535 return 0;
536 }
537 #endif
538
DynamicPreprocRuleOptInit(struct _SnortConfig * sc,void * opt)539 int DynamicPreprocRuleOptInit(struct _SnortConfig *sc, void *opt)
540 {
541 PreprocessorOption *preprocOpt = (PreprocessorOption *)opt;
542 PreprocOptionInit optionInit;
543 PreprocOptionOtnHandler otnHandler;
544 char *option_name = NULL;
545 char *option_params = NULL;
546 char *tmp;
547 int result;
548
549 if (preprocOpt == NULL)
550 return -1;
551
552 if (preprocOpt->optionName == NULL)
553 return -1;
554
555 result = GetPreprocessorRuleOptionFuncs(sc, (char *)preprocOpt->optionName,
556 &preprocOpt->optionInit,
557 &preprocOpt->optionEval,
558 &otnHandler,
559 &preprocOpt->optionFpFunc,
560 &preprocOpt->optionCleanup);
561 if (!result)
562 return -1;
563
564 optionInit = (PreprocOptionInit)preprocOpt->optionInit;
565
566 option_name = SnortStrdup(preprocOpt->optionName);
567
568 /* XXX Hack right now for override options where the rule
569 * option is stored as <option> <override>, e.g.
570 * "byte_test dce"
571 * Since name is passed in to init function, the function
572 * is expecting the first word in the option name and not
573 * the whole string */
574 tmp = option_name;
575 while ((*tmp != '\0') && !isspace((int)*tmp)) tmp++;
576 *tmp = '\0';
577
578 if (preprocOpt->optionParameters != NULL)
579 option_params = SnortStrdup(preprocOpt->optionParameters);
580
581 result = optionInit(sc, option_name, option_params, &preprocOpt->dataPtr);
582
583 free(option_name);
584 if (option_params != NULL) free(option_params);
585
586 if (!result)
587 return -1;
588
589 return 0;
590 }
591
DynamicFlowbitRegister(void * info)592 void *DynamicFlowbitRegister(void *info)
593 {
594 FlowBitsInfo *flowbitsInfo = (FlowBitsInfo *)info;
595 FLOWBITS_OP *flowbits;
596
597 if (!info)
598 return NULL;
599
600 flowbits = (FLOWBITS_OP *) SnortAlloc(sizeof(FLOWBITS_OP));
601 flowbits->type = flowbitsInfo->operation;
602 processFlowBitsWithGroup(flowbitsInfo->flowBitsName, flowbitsInfo->groupName, flowbits);
603
604 // SO rules sometimes reuse the same option structure for multiple rule
605 // definitions. Also on snort reload we can't muck with the structure
606 // since it'll possibly be in use. So if flowbitsInfo->ids is already set,
607 // the flowbits structure has already been parsed and flowbits->ids will
608 // remain unchanged, so just return.
609 // processFlowBitsWithGroup() is called again, mainly for reload in
610 // case flowbits have been removed or added and/or the actual id values
611 // have changed.
612 if (flowbitsInfo->ids != NULL)
613 {
614 if (flowbits->ids != NULL)
615 free(flowbits->ids);
616 free(flowbits);
617 return flowbitsInfo;
618 }
619
620 flowbitsInfo->eval = flowbits->eval;
621 flowbitsInfo->ids = flowbits->ids;
622 flowbitsInfo->num_ids = flowbits->num_ids;
623 free(flowbits);
624 return flowbitsInfo;
625 }
626
unregisterFlowbit(char * name,int op)627 static void unregisterFlowbit(char *name, int op)
628 {
629 FLOWBITS_OBJECT *flowbits_item;
630
631 if (flowbits_hash == NULL)
632 return;
633
634 flowbits_item = sfghash_find(flowbits_hash, name);
635 if (flowbits_item == NULL)
636 return;
637
638 switch (op)
639 {
640 case FLOWBITS_SET:
641 case FLOWBITS_SETX:
642 case FLOWBITS_UNSET:
643 case FLOWBITS_TOGGLE:
644 case FLOWBITS_RESET:
645 if (flowbits_item->set == 0)
646 return;
647 flowbits_item->set--;
648 break;
649
650 case FLOWBITS_ISSET:
651 case FLOWBITS_ISNOTSET:
652 if (flowbits_item->isset == 0)
653 return;
654 flowbits_item->isset--;
655 break;
656
657 default:
658 break;
659 }
660 }
661
DynamicFlowbitUnregister(void * info)662 void DynamicFlowbitUnregister(void *info)
663 {
664 FlowBitsInfo *flowbitsInfo = (FlowBitsInfo *)info;
665 char *names;
666 char *flowbitName;
667 char *nextName;
668 int op;
669
670 if ((!flowbitsInfo)||(!flowbitsInfo->flowBitsName))
671 return;
672
673 op = flowbitsInfo->operation;
674 names = SnortStrdup(flowbitsInfo->flowBitsName);
675 flowbitName = strtok_r(names, "|&", &nextName);
676 while ( flowbitName )
677 {
678 unregisterFlowbit(flowbitName, op);
679 flowbitName = strtok_r(nextName, "|&", &nextName);
680 }
681
682 // Don't free flowbits->ids here for SO rules as it may cause a segfault
683 // with rules that share the same flowbits structure when not all of the
684 // stub rules are enabled. The ids array will be free'd at shutdown in
685 // FreeOneRule().
686
687 free(names);
688 }
689
DynamicFlowbitCheck(void * pkt,void * info)690 int DynamicFlowbitCheck(void *pkt, void *info)
691 {
692 Packet *p = (Packet *)pkt;
693 FlowBitsInfo *flowbitsInfo = (FlowBitsInfo *)info;
694 int result = 0;
695 result = checkFlowBits(flowbitsInfo->operation, flowbitsInfo->eval, flowbitsInfo->ids,
696 flowbitsInfo->num_ids,flowbitsInfo->groupName, p);
697 return result;
698 }
699
700
DynamicAsn1Detect(void * pkt,void * ctxt,const uint8_t * cursor)701 int DynamicAsn1Detect(void *pkt, void *ctxt, const uint8_t *cursor)
702 {
703 Packet *p = (Packet *) pkt;
704 ASN1_CTXT *c = (ASN1_CTXT *) ctxt;
705
706 /* Call same detection function that snort calls */
707 return Asn1DoDetect(p->data, p->dsize, c, cursor);
708 }
709
DynamicsfUnfold(const uint8_t * inbuf,uint32_t insize,uint8_t * outbuf,uint32_t outsize,uint32_t * read)710 int DynamicsfUnfold(const uint8_t *inbuf, uint32_t insize, uint8_t *outbuf, uint32_t outsize, uint32_t *read)
711 {
712 return sf_unfold_header(inbuf, insize, outbuf, outsize, read, 0, 0);
713 }
714
Dynamicsfbase64decode(uint8_t * inbuf,uint32_t insize,uint8_t * outbuf,uint32_t outsize,uint32_t * read)715 int Dynamicsfbase64decode(uint8_t *inbuf, uint32_t insize, uint8_t *outbuf, uint32_t outsize, uint32_t *read)
716 {
717 return sf_base64decode(inbuf, insize, outbuf, outsize, read);
718 }
719
DynamicGetAltDetect(uint8_t ** bufPtr,uint16_t * altLenPtr)720 int DynamicGetAltDetect(uint8_t **bufPtr, uint16_t *altLenPtr)
721 {
722 return GetAltDetect(bufPtr, altLenPtr);
723 }
724
DynamicSetAltDetect(uint8_t * buf,uint16_t altLen)725 void DynamicSetAltDetect(uint8_t *buf, uint16_t altLen)
726 {
727 SetAltDetect(buf, altLen);
728 }
729
DynamicIsDetectFlag(SFDetectFlagType df)730 int DynamicIsDetectFlag(SFDetectFlagType df)
731 {
732 return Is_DetectFlag((DetectFlagType)df);
733 }
734
DynamicDetectFlagDisable(SFDetectFlagType df)735 void DynamicDetectFlagDisable(SFDetectFlagType df)
736 {
737 DetectFlag_Disable((DetectFlagType)df);
738 }
739
740
DynamicHasOption(OptTreeNode * otn,DynamicOptionType optionType,int flowFlag)741 static inline int DynamicHasOption(
742 OptTreeNode *otn, DynamicOptionType optionType, int flowFlag
743 ) {
744 DynamicData *dynData;
745
746 dynData = (DynamicData *)otn->ds_list[PLUGIN_DYNAMIC];
747 if (!dynData)
748 {
749 return 0;
750 }
751
752 return dynData->hasOptionFunction(dynData->contextData, optionType, flowFlag);
753 }
754
DynamicHasFlow(OptTreeNode * otn)755 int DynamicHasFlow(OptTreeNode *otn)
756 {
757 return DynamicHasOption(otn, OPTION_TYPE_FLOWFLAGS, 0);
758 }
759
DynamicHasFlowbit(OptTreeNode * otn)760 int DynamicHasFlowbit(OptTreeNode *otn)
761 {
762 return DynamicHasOption(otn, OPTION_TYPE_FLOWBIT, 0);
763 }
764
DynamicHasContent(OptTreeNode * otn)765 int DynamicHasContent(OptTreeNode *otn)
766 {
767 return DynamicHasOption(otn, OPTION_TYPE_CONTENT, 0);
768 }
769
DynamicHasByteTest(OptTreeNode * otn)770 int DynamicHasByteTest(OptTreeNode *otn)
771 {
772 return DynamicHasOption(otn, OPTION_TYPE_BYTE_TEST, 0);
773 }
774
DynamicHasByteMath(OptTreeNode * otn)775 int DynamicHasByteMath(OptTreeNode *otn)
776 {
777 return DynamicHasOption(otn, OPTION_TYPE_BYTE_MATH, 0);
778 }
779
DynamicHasPCRE(OptTreeNode * otn)780 int DynamicHasPCRE(OptTreeNode *otn)
781 {
782 return DynamicHasOption(otn, OPTION_TYPE_PCRE, 0);
783 }
784