suricata
detect-flowint.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2020 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
22 *
23 * Flowvar management for integer types, part of the detection engine
24 * Keyword: flowint
25 */
26
27#include "suricata-common.h"
28#include "decode.h"
29#include "detect.h"
30#include "threads.h"
31#include "flow.h"
32#include "flow-var.h"
33#include "detect-flowint.h"
34#include "util-spm.h"
35#include "util-var-name.h"
36#include "util-debug.h"
37#include "util-unittest.h"
39
40#include "detect-parse.h"
41#include "detect-engine.h"
42#include "detect-engine-mpm.h"
44#include "detect-engine-build.h"
45
46#include "pkt-var.h"
47#include "host.h"
48#include "util-profiling.h"
49
50/* name modifiers value */
51#define PARSE_REGEX \
52 "^\\s*([a-zA-Z][\\w\\d_./" \
53 "]+)\\s*,\\s*([+=-]{1}|==|!=|<|<=|>|>=|isset|notset|isnotset)\\s*,?\\s*([a-zA-Z][\\w\\d]+|[" \
54 "\\d]{1,10})?\\s*$"
55/* Varnames must begin with a letter */
56
57static DetectParseRegex parse_regex;
58
60 const Signature *, const SigMatchCtx *);
61static int DetectFlowintSetup(DetectEngineCtx *, Signature *, const char *);
63#ifdef UNITTESTS
64static void DetectFlowintRegisterTests(void);
65#endif
66
68{
70 sigmatch_table[DETECT_FLOWINT].desc = "operate on a per-flow integer";
71 sigmatch_table[DETECT_FLOWINT].url = "/rules/flow-keywords.html#flowint";
73 sigmatch_table[DETECT_FLOWINT].Setup = DetectFlowintSetup;
75#ifdef UNITTESTS
76 sigmatch_table[DETECT_FLOWINT].RegisterTests = DetectFlowintRegisterTests;
77#endif
79}
80
81/**
82 * \brief This function is used to create a flowint, add/substract values,
83 * compare it with other flowints, etc
84 *
85 * \param t pointer to thread vars
86 * \param det_ctx pointer to the pattern matcher thread
87 * \param p pointer to the current packet
88 * \param s pointer to the current Signature
89 * \param m pointer to the sigmatch that we will cast into DetectFlowintData
90 *
91 * \retval 0 no match, when a var doesn't exist
92 * \retval 1 match, when a var is initialized well, add/subtracted, or a true
93 * condition
94 */
96 Packet *p, const Signature *s, const SigMatchCtx *ctx)
97{
98 const DetectFlowintData *sfd = (const DetectFlowintData *)ctx;
99 FlowVar *fv;
100 FlowVar *fvt;
101 uint32_t targetval;
102 int ret = 0;
103
104 if (p->flow == NULL)
105 return 0;
106
107 /** ATM If we are going to compare the current var with another
108 * that doesn't exist, the default value will be zero;
109 * if you don't want this behaviour, you can use the keyword
110 * "isset" to make it match or not before using the default
111 * value of zero;
112 * But it is mandatory that the current var exist, otherwise, it will
113 * return zero(not match).
114 */
115 if (sfd->targettype == FLOWINT_TARGET_VAR) {
116 uint32_t tvar_idx = VarNameStoreLookupByName(sfd->target.tvar.name, VAR_TYPE_FLOW_INT);
117
118 fvt = FlowVarGet(p->flow, tvar_idx);
119 /* We don't have that variable initialized yet */
120 if (fvt == NULL)
121 targetval = 0;
122 else
123 targetval = fvt->data.fv_int.value;
124 } else {
125 targetval = sfd->target.value;
126 }
127
128 SCLogDebug("Our var %s is at idx: %"PRIu32"", sfd->name, sfd->idx);
129
130 if (sfd->modifier == FLOWINT_MODIFIER_SET) {
131 FlowVarAddIntNoLock(p->flow, sfd->idx, targetval);
132 SCLogDebug("Setting %s = %u", sfd->name, targetval);
133 ret = 1;
134 goto end;
135 }
136
137 fv = FlowVarGet(p->flow, sfd->idx);
138
139 if (sfd->modifier == FLOWINT_MODIFIER_ISSET) {
140 SCLogDebug(" Isset %s? = %u", sfd->name,(fv) ? 1 : 0);
141 if (fv != NULL)
142 ret = 1;
143 goto end;
144 }
145
147 SCLogDebug(" Not set %s? = %u", sfd->name,(fv) ? 0 : 1);
148 if (fv == NULL)
149 ret = 1;
150 goto end;
151 }
152
153 if (fv != NULL && fv->datatype == FLOWVAR_TYPE_INT) {
154 if (sfd->modifier == FLOWINT_MODIFIER_ADD) {
155 SCLogDebug("Adding %u to %s", targetval, sfd->name);
157 targetval);
158 ret = 1;
159 goto end;
160 }
161
162 if (sfd->modifier == FLOWINT_MODIFIER_SUB) {
163 SCLogDebug("Subtracting %u to %s", targetval, sfd->name);
165 targetval);
166 ret = 1;
167 goto end;
168 }
169
170 switch(sfd->modifier) {
172 SCLogDebug("( %u EQ %u )", fv->data.fv_int.value, targetval);
173 ret = (fv->data.fv_int.value == targetval);
174 break;
176 SCLogDebug("( %u NE %u )", fv->data.fv_int.value, targetval);
177 ret = (fv->data.fv_int.value != targetval);
178 break;
180 SCLogDebug("( %u LT %u )", fv->data.fv_int.value, targetval);
181 ret = (fv->data.fv_int.value < targetval);
182 break;
184 SCLogDebug("( %u LE %u )", fv->data.fv_int.value, targetval);
185 ret = (fv->data.fv_int.value <= targetval);
186 break;
188 SCLogDebug("( %u GT %u )", fv->data.fv_int.value, targetval);
189 ret = (fv->data.fv_int.value > targetval);
190 break;
192 SCLogDebug("( %u GE %u )", fv->data.fv_int.value, targetval);
193 ret = (fv->data.fv_int.value >= targetval);
194 break;
195 default:
196 SCLogDebug("Unknown Modifier!");
197#ifdef DEBUG
198 BUG_ON(1);
199#endif
200 }
201 } else {
202 /* allow a add on a non-existing var, it will init to the "add" value,
203 * so implying a 0 set. */
204 if (sfd->modifier == FLOWINT_MODIFIER_ADD) {
205 SCLogDebug("Adding %u to %s (new var)", targetval, sfd->name);
206 FlowVarAddIntNoLock(p->flow, sfd->idx, targetval);
207 ret = 1;
208 } else {
209 SCLogDebug("Var not found!");
210 /* It doesn't exist because it wasn't set
211 * or it is a string var, that we don't compare here
212 */
213 ret = 0;
214 }
215 }
216
217end:
218 return ret;
219}
220
221/**
222 * \brief This function is used to parse a flowint option
223 *
224 * \param de_ctx pointer to the engine context
225 * \param rawstr pointer to the string holding the options
226 *
227 * \retval NULL if invalid option
228 * \retval DetectFlowintData pointer with the flowint parsed
229 */
230static DetectFlowintData *DetectFlowintParse(DetectEngineCtx *de_ctx, const char *rawstr)
231{
232 DetectFlowintData *sfd = NULL;
233 char *varname = NULL;
234 char *varval = NULL;
235 char *modstr = NULL;
236 int res = 0;
237 size_t pcre2_len;
238 uint8_t modifier = FLOWINT_MODIFIER_UNKNOWN;
239 unsigned long long value_long = 0;
240 const char *str_ptr;
241 pcre2_match_data *match = NULL;
242
243 int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
244 if (ret < 3 || ret > 4) {
245 SCLogError("\"%s\" is not a valid setting for flowint(ret = %d).", rawstr, ret);
246 goto error;
247 }
248
249 /* Get our flowint varname */
250 res = pcre2_substring_get_bynumber(match, 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
251 if (res < 0 || str_ptr == NULL) {
252 SCLogError("pcre2_substring_get_bynumber failed");
253 goto error;
254 }
255 varname = (char *)str_ptr;
256
257 res = pcre2_substring_get_bynumber(match, 2, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
258 if (res < 0 || str_ptr == NULL) {
259 SCLogError("pcre2_substring_get_bynumber failed");
260 goto error;
261 }
262 modstr = (char *)str_ptr;
263
264 /* Get the modifier */
265 if (strcmp("=", modstr) == 0)
266 modifier = FLOWINT_MODIFIER_SET;
267 if (strcmp("+", modstr) == 0)
268 modifier = FLOWINT_MODIFIER_ADD;
269 if (strcmp("-", modstr) == 0)
270 modifier = FLOWINT_MODIFIER_SUB;
271
272 if (strcmp("<", modstr) == 0)
273 modifier = FLOWINT_MODIFIER_LT;
274 if (strcmp("<=", modstr) == 0)
275 modifier = FLOWINT_MODIFIER_LE;
276 if (strcmp("!=", modstr) == 0)
277 modifier = FLOWINT_MODIFIER_NE;
278 if (strcmp("==", modstr) == 0)
279 modifier = FLOWINT_MODIFIER_EQ;
280 if (strcmp(">=", modstr) == 0)
281 modifier = FLOWINT_MODIFIER_GE;
282 if (strcmp(">", modstr) == 0)
283 modifier = FLOWINT_MODIFIER_GT;
284 if (strcmp("isset", modstr) == 0)
285 modifier = FLOWINT_MODIFIER_ISSET;
286 if (strcmp("notset", modstr) == 0 || strcmp("isnotset", modstr) == 0)
287 modifier = FLOWINT_MODIFIER_ISNOTSET;
288
289 if (modifier == FLOWINT_MODIFIER_UNKNOWN) {
290 SCLogError("Unknown modifier");
291 goto error;
292 }
293
294 sfd = SCMalloc(sizeof(DetectFlowintData));
295 if (unlikely(sfd == NULL))
296 goto error;
297
298 /* If we need another arg, check it out(isset doesn't need another arg) */
299 if (modifier != FLOWINT_MODIFIER_ISSET && modifier != FLOWINT_MODIFIER_ISNOTSET) {
300 if (ret < 4)
301 goto error;
302
303 res = pcre2_substring_get_bynumber(match, 3, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
304 varval = (char *)str_ptr;
305 if (res < 0 || varval == NULL || strcmp(varval, "") == 0) {
306 SCLogError("pcre2_substring_get_bynumber failed");
307 goto error;
308 }
309
310 if (varval[0] >= '0' && varval[0] <= '9') { /* is digit, look at the regexp */
312 value_long = atoll(varval);
313 if (value_long > UINT32_MAX) {
314 SCLogDebug("DetectFlowintParse: Cannot load this value."
315 " Values should be between 0 and %"PRIu32, UINT32_MAX);
316 goto error;
317 }
318 sfd->target.value = (uint32_t) value_long;
319 } else {
321 sfd->target.tvar.name = SCStrdup(varval);
322 if (unlikely(sfd->target.tvar.name == NULL)) {
323 SCLogError("malloc from strdup failed");
324 goto error;
325 }
326 }
327 } else {
329 }
330
331 /* Set the name of the origin var to modify/compared with the target */
332 sfd->name = SCStrdup(varname);
333 if (unlikely(sfd->name == NULL)) {
334 SCLogError("malloc from strdup failed");
335 goto error;
336 }
338 SCLogDebug("sfd->name %s id %u", sfd->name, sfd->idx);
339 sfd->modifier = modifier;
340
341 pcre2_substring_free((PCRE2_UCHAR *)varname);
342 pcre2_substring_free((PCRE2_UCHAR *)modstr);
343 if (varval)
344 pcre2_substring_free((PCRE2_UCHAR *)varval);
345 pcre2_match_data_free(match);
346 return sfd;
347error:
348 if (match) {
349 pcre2_match_data_free(match);
350 }
351 if (varname)
352 pcre2_substring_free((PCRE2_UCHAR *)varname);
353 if (varval)
354 pcre2_substring_free((PCRE2_UCHAR *)varval);
355 if (modstr)
356 pcre2_substring_free((PCRE2_UCHAR *)modstr);
357 if (sfd != NULL)
358 SCFree(sfd);
359 return NULL;
360}
361
362/**
363 * \brief This function is used to set up the SigMatch holding the flowint opt
364 *
365 * \param de_ctx pointer to the engine context
366 * \param s pointer to the current Signature
367 * \param rawstr pointer to the string holding the options
368 *
369 * \retval 0 if all is ok
370 * \retval -1 if we find any problem
371 */
372static int DetectFlowintSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
373{
374 DetectFlowintData *sfd = NULL;
375
376 sfd = DetectFlowintParse(de_ctx, rawstr);
377 if (sfd == NULL)
378 goto error;
379
380 /* Okay so far so good, lets get this into a SigMatch
381 * and put it in the Signature. */
382
383 switch (sfd->modifier) {
388 DETECT_SM_LIST_POSTMATCH) == NULL) {
389 goto error;
390 }
391 break;
392
402 DETECT_SM_LIST_MATCH) == NULL) {
403 goto error;
404 }
405 break;
406 default:
407 goto error;
408 }
409
410 return 0;
411
412error:
413 if (sfd)
415 return -1;
416}
417
418/**
419 * \brief This function is used to free the data of DetectFlowintData
420 */
422{
424 if (sfd != NULL) {
426 if (sfd->name != NULL)
427 SCFree(sfd->name);
428 if (sfd->targettype == FLOWINT_TARGET_VAR)
429 if (sfd->target.tvar.name != NULL)
430 SCFree(sfd->target.tvar.name);
431 SCFree(sfd);
432 }
433}
434
435#ifdef UNITTESTS
436#include "detect-engine-alert.h"
437/**
438 * \brief This is a helper function used for debugging purposes
439 */
440static void DetectFlowintPrintData(DetectFlowintData *sfd)
441{
442 if (sfd == NULL) {
443 SCLogDebug("DetectFlowintPrintData: Error, DetectFlowintData == NULL!");
444 return;
445 }
446
447 SCLogDebug("Varname: %s, modifier: %"PRIu8", idx: %"PRIu32" Target: ",
448 sfd->name, sfd->modifier, sfd->idx);
449 switch(sfd->targettype) {
451 SCLogDebug("target_var: %s",
452 sfd->target.tvar.name);
453 break;
455 SCLogDebug("Value: %"PRIu32"; ", sfd->target.value);
456 break;
457 default :
458 SCLogDebug("DetectFlowintPrintData: Error, Targettype not known!");
459 }
460}
461
462/**
463 * \test DetectFlowintTestParseVal01 is a test to make sure that we set the
464 * DetectFlowint correctly for setting a valid target value
465 */
466static int DetectFlowintTestParseVal01(void)
467{
468 int result = 0;
469 DetectFlowintData *sfd = NULL;
472 if (de_ctx == NULL)
473 return 0;
475
476 sfd = DetectFlowintParse(de_ctx, "myvar,=,35");
477 DetectFlowintPrintData(sfd);
478 if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
479 && sfd->modifier == FLOWINT_MODIFIER_SET) {
480 result = 1;
481 }
482 if (sfd) DetectFlowintFree(NULL, sfd);
483
485
486 return result;
487}
488
489/**
490 * \test DetectFlowintTestParseVar01 is a test to make sure that we set the
491 * DetectFlowint correctly for setting a valid target variable
492 */
493static int DetectFlowintTestParseVar01(void)
494{
495 int result = 0;
496 DetectFlowintData *sfd = NULL;
499 if (de_ctx == NULL)
500 return 0;
502
503 sfd = DetectFlowintParse(de_ctx, "myvar,=,targetvar");
504 DetectFlowintPrintData(sfd);
505 if (sfd != NULL && !strcmp(sfd->name, "myvar")
507 && sfd->target.tvar.name != NULL
508 && !strcmp(sfd->target.tvar.name, "targetvar")
509 && sfd->modifier == FLOWINT_MODIFIER_SET) {
510
511 result = 1;
512 }
513 if (sfd) DetectFlowintFree(NULL, sfd);
515
516 return result;
517}
518
519/**
520 * \test DetectFlowintTestParseVal02 is a test to make sure that we set the
521 * DetectFlowint correctly for adding a valid target value
522 */
523static int DetectFlowintTestParseVal02(void)
524{
525 int result = 0;
526 DetectFlowintData *sfd = NULL;
529 if (de_ctx == NULL)
530 return 0;
532
533 sfd = DetectFlowintParse(de_ctx, "myvar,+,35");
534 DetectFlowintPrintData(sfd);
535 if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
536 && sfd->modifier == FLOWINT_MODIFIER_ADD) {
537 result = 1;
538 }
539 if (sfd) DetectFlowintFree(NULL, sfd);
540
542
543 return result;
544}
545
546/**
547 * \test DetectFlowintTestParseVar02 is a test to make sure that we set the
548 * DetectFlowint correctly for adding a valid target variable
549 */
550static int DetectFlowintTestParseVar02(void)
551{
552 int result = 0;
553 DetectFlowintData *sfd = NULL;
556 if (de_ctx == NULL)
557 return 0;
559
560 sfd = DetectFlowintParse(de_ctx, "myvar,+,targetvar");
561 DetectFlowintPrintData(sfd);
562 if (sfd != NULL && !strcmp(sfd->name, "myvar")
564 && sfd->target.tvar.name != NULL
565 && !strcmp(sfd->target.tvar.name, "targetvar")
566 && sfd->modifier == FLOWINT_MODIFIER_ADD) {
567
568 result = 1;
569 }
570 if (sfd) DetectFlowintFree(NULL, sfd);
572
573 return result;
574}
575
576/**
577 * \test DetectFlowintTestParseVal03 is a test to make sure that we set the
578 * DetectFlowint correctly for substract a valid target value
579 */
580static int DetectFlowintTestParseVal03(void)
581{
582 int result = 0;
583 DetectFlowintData *sfd = NULL;
586 if (de_ctx == NULL)
587 return 0;
589
590 sfd = DetectFlowintParse(de_ctx, "myvar,-,35");
591 DetectFlowintPrintData(sfd);
592 if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
593 && sfd->modifier == FLOWINT_MODIFIER_SUB) {
594 result = 1;
595 }
596 if (sfd) DetectFlowintFree(NULL, sfd);
597
599
600 return result;
601}
602
603/**
604 * \test DetectFlowintTestParseVar03 is a test to make sure that we set the
605 * DetectFlowint correctly for substract a valid target variable
606 */
607static int DetectFlowintTestParseVar03(void)
608{
609 int result = 0;
610 DetectFlowintData *sfd = NULL;
613 if (de_ctx == NULL)
614 return 0;
616
617 sfd = DetectFlowintParse(de_ctx, "myvar,-,targetvar");
618 DetectFlowintPrintData(sfd);
619 if (sfd != NULL && !strcmp(sfd->name, "myvar")
621 && sfd->target.tvar.name != NULL
622 && !strcmp(sfd->target.tvar.name, "targetvar")
623 && sfd->modifier == FLOWINT_MODIFIER_SUB) {
624
625 result = 1;
626 }
627 if (sfd) DetectFlowintFree(NULL, sfd);
629
630 return result;
631}
632
633
634/**
635 * \test DetectFlowintTestParseVal04 is a test to make sure that we set the
636 * DetectFlowint correctly for checking if equal to a valid target value
637 */
638static int DetectFlowintTestParseVal04(void)
639{
640 int result = 0;
641 DetectFlowintData *sfd = NULL;
644 if (de_ctx == NULL)
645 return 0;
647
648 sfd = DetectFlowintParse(de_ctx, "myvar,==,35");
649 DetectFlowintPrintData(sfd);
650 if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
651 && sfd->modifier == FLOWINT_MODIFIER_EQ) {
652 result = 1;
653 }
654 if (sfd) DetectFlowintFree(NULL, sfd);
655
657
658 return result;
659}
660
661/**
662 * \test DetectFlowintTestParseVar04 is a test to make sure that we set the
663 * DetectFlowint correctly for checking if equal to a valid target variable
664 */
665static int DetectFlowintTestParseVar04(void)
666{
667 int result = 0;
668 DetectFlowintData *sfd = NULL;
671 if (de_ctx == NULL)
672 return 0;
674
675 sfd = DetectFlowintParse(de_ctx, "myvar,==,targetvar");
676 DetectFlowintPrintData(sfd);
677 if (sfd != NULL && !strcmp(sfd->name, "myvar")
679 && sfd->target.tvar.name != NULL
680 && !strcmp(sfd->target.tvar.name, "targetvar")
681 && sfd->modifier == FLOWINT_MODIFIER_EQ) {
682
683 result = 1;
684 }
685 if (sfd) DetectFlowintFree(NULL, sfd);
687
688 return result;
689}
690
691/**
692 * \test DetectFlowintTestParseVal05 is a test to make sure that we set the
693 * DetectFlowint correctly for checking if not equal to a valid target value
694 */
695static int DetectFlowintTestParseVal05(void)
696{
697 int result = 0;
698 DetectFlowintData *sfd = NULL;
701 if (de_ctx == NULL)
702 return 0;
704
705 sfd = DetectFlowintParse(de_ctx, "myvar,!=,35");
706 DetectFlowintPrintData(sfd);
707 if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
708 && sfd->modifier == FLOWINT_MODIFIER_NE) {
709 result = 1;
710 }
711 if (sfd) DetectFlowintFree(NULL, sfd);
712
714
715 return result;
716}
717
718/**
719 * \test DetectFlowintTestParseVar05 is a test to make sure that we set the
720 * DetectFlowint correctly for checking if not equal to a valid target variable
721 */
722static int DetectFlowintTestParseVar05(void)
723{
724 int result = 0;
725 DetectFlowintData *sfd = NULL;
728 if (de_ctx == NULL)
729 return 0;
731
732 sfd = DetectFlowintParse(de_ctx, "myvar,!=,targetvar");
733 DetectFlowintPrintData(sfd);
734 if (sfd != NULL && !strcmp(sfd->name, "myvar")
736 && sfd->target.tvar.name != NULL
737 && !strcmp(sfd->target.tvar.name, "targetvar")
738 && sfd->modifier == FLOWINT_MODIFIER_NE) {
739
740 result = 1;
741 }
742 if (sfd) DetectFlowintFree(NULL, sfd);
744
745 return result;
746}
747
748/**
749 * \test DetectFlowintTestParseVal06 is a test to make sure that we set the
750 * DetectFlowint correctly for checking if greater than a valid target value
751 */
752static int DetectFlowintTestParseVal06(void)
753{
754 int result = 0;
755 DetectFlowintData *sfd = NULL;
758 if (de_ctx == NULL)
759 return 0;
761
762 sfd = DetectFlowintParse(de_ctx, "myvar, >,35");
763 DetectFlowintPrintData(sfd);
764 if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
765 && sfd->modifier == FLOWINT_MODIFIER_GT) {
766 result = 1;
767 }
768 if (sfd) DetectFlowintFree(NULL, sfd);
769
771
772 return result;
773}
774
775/**
776 * \test DetectFlowintTestParseVar06 is a test to make sure that we set the
777 * DetectFlowint correctly for checking if greater than a valid target variable
778 */
779static int DetectFlowintTestParseVar06(void)
780{
781 int result = 0;
782 DetectFlowintData *sfd = NULL;
785 if (de_ctx == NULL)
786 return 0;
788
789 sfd = DetectFlowintParse(de_ctx, "myvar, >,targetvar");
790 DetectFlowintPrintData(sfd);
791 if (sfd != NULL && !strcmp(sfd->name, "myvar")
793 && sfd->target.tvar.name != NULL
794 && !strcmp(sfd->target.tvar.name, "targetvar")
795 && sfd->modifier == FLOWINT_MODIFIER_GT) {
796
797 result = 1;
798 }
799 if (sfd) DetectFlowintFree(NULL, sfd);
801
802 return result;
803}
804
805/**
806 * \test DetectFlowintTestParseVal07 is a test to make sure that we set the
807 * DetectFlowint correctly for checking if greater or equal than a valid target value
808 */
809static int DetectFlowintTestParseVal07(void)
810{
811 int result = 0;
812 DetectFlowintData *sfd = NULL;
815 if (de_ctx == NULL)
816 return 0;
818
819 sfd = DetectFlowintParse(de_ctx, "myvar, >= ,35");
820 DetectFlowintPrintData(sfd);
821 if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
822 && sfd->modifier == FLOWINT_MODIFIER_GE) {
823 result = 1;
824 }
825 if (sfd) DetectFlowintFree(NULL, sfd);
826
828
829 return result;
830}
831
832/**
833 * \test DetectFlowintTestParseVar07 is a test to make sure that we set the
834 * DetectFlowint correctly for checking if greater or equal than a valid target variable
835 */
836static int DetectFlowintTestParseVar07(void)
837{
838 int result = 0;
839 DetectFlowintData *sfd = NULL;
842 if (de_ctx == NULL)
843 return 0;
845
846 sfd = DetectFlowintParse(de_ctx, "myvar, >= ,targetvar");
847 DetectFlowintPrintData(sfd);
848 if (sfd != NULL && !strcmp(sfd->name, "myvar")
850 && sfd->target.tvar.name != NULL
851 && !strcmp(sfd->target.tvar.name, "targetvar")
852 && sfd->modifier == FLOWINT_MODIFIER_GE) {
853
854 result = 1;
855 }
856 if (sfd) DetectFlowintFree(NULL, sfd);
858
859 return result;
860}
861
862/**
863 * \test DetectFlowintTestParseVal08 is a test to make sure that we set the
864 * DetectFlowint correctly for checking if lower or equal than a valid target value
865 */
866static int DetectFlowintTestParseVal08(void)
867{
868 int result = 0;
869 DetectFlowintData *sfd = NULL;
872 if (de_ctx == NULL)
873 return 0;
875
876 sfd = DetectFlowintParse(de_ctx, "myvar, <= ,35");
877 DetectFlowintPrintData(sfd);
878 if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
879 && sfd->modifier == FLOWINT_MODIFIER_LE) {
880 result = 1;
881 }
882 if (sfd) DetectFlowintFree(NULL, sfd);
883
885
886 return result;
887}
888
889/**
890 * \test DetectFlowintTestParseVar08 is a test to make sure that we set the
891 * DetectFlowint correctly for checking if lower or equal than a valid target variable
892 */
893static int DetectFlowintTestParseVar08(void)
894{
895 int result = 0;
896 DetectFlowintData *sfd = NULL;
899 if (de_ctx == NULL)
900 return 0;
902
903 sfd = DetectFlowintParse(de_ctx, "myvar, <= ,targetvar");
904 DetectFlowintPrintData(sfd);
905 if (sfd != NULL && !strcmp(sfd->name, "myvar")
907 && sfd->target.tvar.name != NULL
908 && !strcmp(sfd->target.tvar.name, "targetvar")
909 && sfd->modifier == FLOWINT_MODIFIER_LE) {
910
911 result = 1;
912 }
913 if (sfd) DetectFlowintFree(NULL, sfd);
915
916 return result;
917}
918
919/**
920 * \test DetectFlowintTestParseVal09 is a test to make sure that we set the
921 * DetectFlowint correctly for checking if lower than a valid target value
922 */
923static int DetectFlowintTestParseVal09(void)
924{
925 int result = 0;
926 DetectFlowintData *sfd = NULL;
929 if (de_ctx == NULL)
930 return 0;
932
933 sfd = DetectFlowintParse(de_ctx, "myvar, < ,35");
934 DetectFlowintPrintData(sfd);
935 if (sfd != NULL && sfd->target.value == 35 && !strcmp(sfd->name, "myvar")
936 && sfd->modifier == FLOWINT_MODIFIER_LT) {
937 result = 1;
938 }
939 if (sfd) DetectFlowintFree(NULL, sfd);
940
942
943 return result;
944}
945
946/**
947 * \test DetectFlowintTestParseVar09 is a test to make sure that we set the
948 * DetectFlowint correctly for checking if lower than a valid target variable
949 */
950static int DetectFlowintTestParseVar09(void)
951{
952 int result = 0;
953 DetectFlowintData *sfd = NULL;
956 if (de_ctx == NULL)
957 return 0;
959
960 sfd = DetectFlowintParse(de_ctx, "myvar, < ,targetvar");
961 DetectFlowintPrintData(sfd);
962 if (sfd != NULL && !strcmp(sfd->name, "myvar")
964 && sfd->target.tvar.name != NULL
965 && !strcmp(sfd->target.tvar.name, "targetvar")
966 && sfd->modifier == FLOWINT_MODIFIER_LT) {
967
968 result = 1;
969 }
970 if (sfd) DetectFlowintFree(NULL, sfd);
972
973 return result;
974}
975
976/**
977 * \test DetectFlowintTestParseVar09 is a test to make sure that handle the
978 * isset keyword correctly
979 */
980static int DetectFlowintTestParseIsset10(void)
981{
982 int result = 1;
983 DetectFlowintData *sfd = NULL;
986 if (de_ctx == NULL)
987 return 0;
989
990 sfd = DetectFlowintParse(de_ctx, "myvar, isset");
991 DetectFlowintPrintData(sfd);
992 if (sfd != NULL && !strcmp(sfd->name, "myvar")
994 && sfd->modifier == FLOWINT_MODIFIER_ISSET) {
995
996 result &= 1;
997 } else {
998 result = 0;
999 }
1000
1001 if (sfd) DetectFlowintFree(NULL, sfd);
1002 sfd = DetectFlowintParse(de_ctx, "myvar, notset");
1003 DetectFlowintPrintData(sfd);
1004 if (sfd != NULL && !strcmp(sfd->name, "myvar") && sfd->targettype == FLOWINT_TARGET_SELF &&
1006
1007 result &= 1;
1008 } else {
1009 result = 0;
1010 }
1011
1012 if (sfd) DetectFlowintFree(NULL, sfd);
1014
1015 return result;
1016}
1017
1018/**
1019 * \test DetectFlowintTestParseInvalidSyntaxis01 is a test to make sure that we dont set the
1020 * DetectFlowint for a invalid input option
1021 */
1022static int DetectFlowintTestParseInvalidSyntaxis01(void)
1023{
1024 int result = 1;
1025 DetectFlowintData *sfd = NULL;
1028 if (de_ctx == NULL)
1029 goto error;
1030 de_ctx->flags |= DE_QUIET;
1031
1032 sfd = DetectFlowintParse(de_ctx, "myvar,=,9999999999");
1033 if (sfd != NULL) {
1034 SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,=,9532458716234857");
1035 result = 0;
1036 }
1037 if (sfd) DetectFlowintFree(NULL, sfd);
1038
1039 sfd = DetectFlowintParse(de_ctx, "myvar,=,45targetvar");
1040 if (sfd != NULL) {
1041 SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,=,45targetvar ");
1042 result = 0;
1043 }
1044 if (sfd) DetectFlowintFree(NULL, sfd);
1045
1046 sfd = DetectFlowintParse(de_ctx, "657myvar,=,targetvar");
1047 if (sfd != NULL) {
1048 SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at 657myvar,=,targetvar ");
1049 result = 0;
1050 }
1051 if (sfd) DetectFlowintFree(NULL, sfd);
1052
1053 sfd = DetectFlowintParse(de_ctx, "myvar,=<,targetvar");
1054 if (sfd != NULL) {
1055 SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,=<,targetvar ");
1056 result = 0;
1057 }
1058 if (sfd) DetectFlowintFree(NULL, sfd);
1059
1060 sfd = DetectFlowintParse(de_ctx, "myvar,===,targetvar");
1061 if (sfd != NULL) {
1062 SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,===,targetvar ");
1063 result = 0;
1064 }
1065 if (sfd) DetectFlowintFree(NULL, sfd);
1066
1067 sfd = DetectFlowintParse(de_ctx, "myvar,==");
1068 if (sfd != NULL) {
1069 SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,==");
1070 result = 0;
1071 }
1072 if (sfd) DetectFlowintFree(NULL, sfd);
1073
1074 sfd = DetectFlowintParse(de_ctx, "myvar,");
1075 if (sfd != NULL) {
1076 SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar,");
1077 result = 0;
1078 }
1079 if (sfd) DetectFlowintFree(NULL, sfd);
1080
1081 sfd = DetectFlowintParse(de_ctx, "myvar");
1082 if (sfd != NULL) {
1083 SCLogDebug("DetectFlowintTestParseInvalidSyntaxis01: ERROR: invalid option at myvar");
1084 result = 0;
1085 }
1086 if (sfd) DetectFlowintFree(NULL, sfd);
1087
1089
1090 return result;
1091error:
1092 if (de_ctx)
1094 return result;
1095}
1096
1097/** \test DetectFlowintTestPacket01Real
1098 * \brief Set a counter when we see a content:"GET"
1099 * and increment it by 2 if we match a "Unauthorized"
1100 * When it reach 3(with the last +2), another counter starts
1101 * and when that counter reach 6 packets.
1102 *
1103 * All the Signatures generate an alert(its for testing)
1104 * but the signature that increment the second counter +1, that has
1105 * a "noalert", so we can do all increments
1106 * silently until we reach 6 next packets counted
1107 */
1108static int DetectFlowintTestPacket01Real(void)
1109{
1110 Packet *p = NULL;
1111 ThreadVars th_v;
1112 DetectEngineThreadCtx *det_ctx = NULL;
1113 memset(&th_v, 0, sizeof(th_v));
1114
1116 FAIL_IF(de_ctx == NULL);
1117
1118 de_ctx->flags |= DE_QUIET;
1119
1120 const char *sigs[5];
1121 sigs[0] = "alert tcp any any -> any any (msg:\"Setting a flowint counter\"; content:\"GET\"; flowint:myvar,=,1; flowint:maxvar,=,6; sid:101;)";
1122 sigs[1] = "alert tcp any any -> any any (msg:\"Adding to flowint counter\"; content:\"Unauthorized\"; flowint: myvar,+,2; sid:102;)";
1123 sigs[2] = "alert tcp any any -> any any (msg:\"if the flowint counter is 3 create a new counter\"; content:\"Unauthorized\"; flowint: myvar,==,3; flowint: cntpackets, =, 0; sid:103;)";
1124 sigs[3] = "alert tcp any any -> any any (msg:\"and count the rest of the packets received without generating alerts!!!\"; flowint: myvar,==,3; flowint: cntpackets, +, 1; noalert;sid:104;)";
1125 sigs[4] = "alert tcp any any -> any any (msg:\" and fire this when it reach 6\"; flowint: cntpackets, ==, maxvar; sid:105;)";
1126 FAIL_IF(UTHAppendSigs(de_ctx, sigs, 5) == 0);
1127
1132 DetectEngineThreadCtxInit(&th_v,(void *) de_ctx,(void *) &det_ctx);
1133
1134 Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1",
1135 41424, 80);
1136 FAIL_IF(f == NULL);
1137 f->proto = IPPROTO_TCP;
1138
1139 p = UTHBuildPacket((uint8_t *)"GET", 3, IPPROTO_TCP);
1140 FAIL_IF(p == NULL);
1141 UTHAssignFlow(p, f);
1142 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1143 FAIL_IF(!PacketAlertCheck(p, 101));
1144 UTHFreePacket(p);
1145
1146 p = UTHBuildPacket((uint8_t *)"Unauthorized", 12, IPPROTO_TCP);
1147 FAIL_IF(p == NULL);
1148 UTHAssignFlow(p, f);
1149 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1150 FAIL_IF(!PacketAlertCheck(p, 102));
1151 FAIL_IF(!PacketAlertCheck(p, 103));
1152 UTHFreePacket(p);
1153
1154 p = UTHBuildPacket((uint8_t *)"1", 1, IPPROTO_TCP);
1155 FAIL_IF(p == NULL);
1156 UTHAssignFlow(p, f);
1157 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1158 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1159 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1160 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1161 UTHFreePacket(p);
1162
1163 p = UTHBuildPacket((uint8_t *)"X", 1, IPPROTO_TCP);
1164 FAIL_IF(p == NULL);
1165 UTHAssignFlow(p, f);
1166 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1167 FAIL_IF(!PacketAlertCheck(p, 105));
1168 UTHFreePacket(p);
1169
1170 UTHFreeFlow(f);
1171 DetectEngineThreadCtxDeinit(&th_v,(void *) det_ctx);
1173
1174 PASS;
1175}
1176
1177/**
1178 * \test DetectFlowintTestPacket02Real
1179 * \brief like DetectFlowintTestPacket01Real but using isset/notset keywords
1180 */
1181static int DetectFlowintTestPacket02Real(void)
1182{
1183 Packet *p = NULL;
1184 ThreadVars th_v;
1185 DetectEngineThreadCtx *det_ctx = NULL;
1186 memset(&th_v, 0, sizeof(th_v));
1187
1189 FAIL_IF(de_ctx == NULL);
1190
1191 de_ctx->flags |= DE_QUIET;
1192
1193 const char *sigs[5];
1194 sigs[0] = "alert tcp any any -> any any (msg:\"Setting a flowint counter\"; content:\"GET\"; "
1195 "flowint:myvar,notset; flowint:maxvar,isnotset; flowint: myvar,=,1; flowint: "
1196 "maxvar,=,6; sid:101;)";
1197 sigs[1] = "alert tcp any any -> any any (msg:\"Adding to flowint counter\"; content:\"Unauthorized\"; flowint:myvar,isset; flowint: myvar,+,2; sid:102;)";
1198 sigs[2] = "alert tcp any any -> any any (msg:\"if the flowint counter is 3 create a new counter\"; content:\"Unauthorized\"; flowint: myvar, isset; flowint: myvar,==,3; flowint:cntpackets,notset; flowint: cntpackets, =, 0; sid:103;)";
1199 sigs[3] = "alert tcp any any -> any any (msg:\"and count the rest of the packets received without generating alerts!!!\"; flowint: cntpackets,isset; flowint: cntpackets, +, 1; noalert;sid:104;)";
1200 sigs[4] = "alert tcp any any -> any any (msg:\" and fire this when it reach 6\"; flowint: cntpackets, isset; flowint: maxvar,isset; flowint: cntpackets, ==, maxvar; sid:105;)";
1201 FAIL_IF(UTHAppendSigs(de_ctx, sigs, 5) == 0);
1202
1207 DetectEngineThreadCtxInit(&th_v,(void *) de_ctx,(void *) &det_ctx);
1208
1209 Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1",
1210 41424, 80);
1211 FAIL_IF(f == NULL);
1212 f->proto = IPPROTO_TCP;
1213
1214 p = UTHBuildPacket((uint8_t *)"GET", 3, IPPROTO_TCP);
1215 FAIL_IF(p == NULL);
1216 UTHAssignFlow(p, f);
1217 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1218 FAIL_IF(!PacketAlertCheck(p, 101));
1219 UTHFreePacket(p);
1220
1221 p = UTHBuildPacket((uint8_t *)"Unauthorized", 12, IPPROTO_TCP);
1222 FAIL_IF(p == NULL);
1223 UTHAssignFlow(p, f);
1224 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1225 FAIL_IF(!PacketAlertCheck(p, 102));
1226 FAIL_IF(!PacketAlertCheck(p, 103));
1227 UTHFreePacket(p);
1228
1229 p = UTHBuildPacket((uint8_t *)"1", 1, IPPROTO_TCP);
1230 FAIL_IF(p == NULL);
1231 UTHAssignFlow(p, f);
1232 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1233 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1234 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1235 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1236 UTHFreePacket(p);
1237
1238 p = UTHBuildPacket((uint8_t *)"X", 1, IPPROTO_TCP);
1239 FAIL_IF(p == NULL);
1240 UTHAssignFlow(p, f);
1241 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1242 FAIL_IF(!PacketAlertCheck(p, 105));
1243 UTHFreePacket(p);
1244
1245 UTHFreeFlow(f);
1246 DetectEngineThreadCtxDeinit(&th_v,(void *) det_ctx);
1248
1249 PASS;
1250}
1251
1252/**
1253 * \test DetectFlowintTestPacket03Real
1254 * \brief Check the behaviour of isset/notset
1255 */
1256static int DetectFlowintTestPacket03Real(void)
1257{
1258 Packet *p = NULL;
1259 ThreadVars th_v;
1260 DetectEngineThreadCtx *det_ctx = NULL;
1261 memset(&th_v, 0, sizeof(th_v));
1262
1264 FAIL_IF(de_ctx == NULL);
1265
1266 de_ctx->flags |= DE_QUIET;
1267
1268 const char *sigs[3];
1269 sigs[0] = "alert tcp any any -> any any (msg:\"check notset\"; content:\"GET\"; flowint: myvar, notset; flowint: myvar,=,0; flowint: other,=,10; sid:101;)";
1270 sigs[1] = "alert tcp any any -> any any (msg:\"check isset\"; content:\"Unauthorized\"; flowint:myvar,isset; flowint: other,isset; sid:102;)";
1271 sigs[2] = "alert tcp any any -> any any (msg:\"check notset\"; content:\"Unauthorized\"; flowint:lala,isset; sid:103;)";
1272 FAIL_IF(UTHAppendSigs(de_ctx, sigs, 3) == 0);
1273
1278 DetectEngineThreadCtxInit(&th_v,(void *) de_ctx,(void *) &det_ctx);
1279
1280 Flow *f = UTHBuildFlow(AF_INET, "192.168.1.5", "192.168.1.1",
1281 41424, 80);
1282 FAIL_IF(f == NULL);
1283 f->proto = IPPROTO_TCP;
1284
1285 p = UTHBuildPacket((uint8_t *)"GET", 3, IPPROTO_TCP);
1286 FAIL_IF(p == NULL);
1287 UTHAssignFlow(p, f);
1288 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1289 FAIL_IF(!PacketAlertCheck(p, 101));
1290 UTHFreePacket(p);
1291
1292 p = UTHBuildPacket((uint8_t *)"Unauthorized", 12, IPPROTO_TCP);
1293 FAIL_IF(p == NULL);
1294 UTHAssignFlow(p, f);
1295 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1296 FAIL_IF(!PacketAlertCheck(p, 102));
1297 FAIL_IF(PacketAlertCheck(p, 103));
1298 UTHFreePacket(p);
1299
1300 p = UTHBuildPacket((uint8_t *)"1", 1, IPPROTO_TCP);
1301 FAIL_IF(p == NULL);
1302 UTHAssignFlow(p, f);
1303 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1304 FAIL_IF(PacketAlertCheck(p, 102));
1305 FAIL_IF(PacketAlertCheck(p, 103));
1306 UTHFreePacket(p);
1307
1308 UTHFreeFlow(f);
1309 DetectEngineThreadCtxDeinit(&th_v,(void *) det_ctx);
1311
1312 PASS;
1313}
1314
1315/**
1316 * \brief this function registers unit tests for DetectFlowint
1317 */
1318void DetectFlowintRegisterTests(void)
1319{
1320 UtRegisterTest("DetectFlowintTestParseVal01", DetectFlowintTestParseVal01);
1321 UtRegisterTest("DetectFlowintTestParseVar01", DetectFlowintTestParseVar01);
1322 UtRegisterTest("DetectFlowintTestParseVal02", DetectFlowintTestParseVal02);
1323 UtRegisterTest("DetectFlowintTestParseVar02", DetectFlowintTestParseVar02);
1324 UtRegisterTest("DetectFlowintTestParseVal03", DetectFlowintTestParseVal03);
1325 UtRegisterTest("DetectFlowintTestParseVar03", DetectFlowintTestParseVar03);
1326 UtRegisterTest("DetectFlowintTestParseVal04", DetectFlowintTestParseVal04);
1327 UtRegisterTest("DetectFlowintTestParseVar04", DetectFlowintTestParseVar04);
1328 UtRegisterTest("DetectFlowintTestParseVal05", DetectFlowintTestParseVal05);
1329 UtRegisterTest("DetectFlowintTestParseVar05", DetectFlowintTestParseVar05);
1330 UtRegisterTest("DetectFlowintTestParseVal06", DetectFlowintTestParseVal06);
1331 UtRegisterTest("DetectFlowintTestParseVar06", DetectFlowintTestParseVar06);
1332 UtRegisterTest("DetectFlowintTestParseVal07", DetectFlowintTestParseVal07);
1333 UtRegisterTest("DetectFlowintTestParseVar07", DetectFlowintTestParseVar07);
1334 UtRegisterTest("DetectFlowintTestParseVal08", DetectFlowintTestParseVal08);
1335 UtRegisterTest("DetectFlowintTestParseVar08", DetectFlowintTestParseVar08);
1336 UtRegisterTest("DetectFlowintTestParseVal09", DetectFlowintTestParseVal09);
1337 UtRegisterTest("DetectFlowintTestParseVar09", DetectFlowintTestParseVar09);
1338 UtRegisterTest("DetectFlowintTestParseIsset10",
1339 DetectFlowintTestParseIsset10);
1340 UtRegisterTest("DetectFlowintTestParseInvalidSyntaxis01",
1341 DetectFlowintTestParseInvalidSyntaxis01);
1342 UtRegisterTest("DetectFlowintTestPacket01Real",
1343 DetectFlowintTestPacket01Real);
1344 UtRegisterTest("DetectFlowintTestPacket02Real",
1345 DetectFlowintTestPacket02Real);
1346 UtRegisterTest("DetectFlowintTestPacket03Real",
1347 DetectFlowintTestPacket03Real);
1348}
1349#endif /* UNITTESTS */
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
void SCSigOrderSignatures(DetectEngineCtx *de_ctx)
Orders the signatures.
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
void SCSigSignatureOrderingModuleCleanup(DetectEngineCtx *de_ctx)
De-registers all the signature ordering functions registered.
void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *de_ctx)
Lets you register the Signature ordering functions. The order in which the functions are registered s...
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
void DetectFlowintFree(DetectEngineCtx *, void *)
This function is used to free the data of DetectFlowintData.
void DetectFlowintRegister(void)
int DetectFlowintMatch(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
This function is used to create a flowint, add/substract values, compare it with other flowints,...
#define PARSE_REGEX
@ FLOWINT_TARGET_SELF
@ FLOWINT_TARGET_VAR
@ FLOWINT_TARGET_VAL
@ FLOWINT_MODIFIER_GE
@ FLOWINT_MODIFIER_LT
@ FLOWINT_MODIFIER_UNKNOWN
@ FLOWINT_MODIFIER_SUB
@ FLOWINT_MODIFIER_GT
@ FLOWINT_MODIFIER_ADD
@ FLOWINT_MODIFIER_ISSET
@ FLOWINT_MODIFIER_ISNOTSET
@ FLOWINT_MODIFIER_NE
@ FLOWINT_MODIFIER_EQ
@ FLOWINT_MODIFIER_LE
@ FLOWINT_MODIFIER_SET
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
SigTableElmt * sigmatch_table
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition detect.c:2420
#define DE_QUIET
Definition detect.h:330
@ DETECT_SM_LIST_MATCH
Definition detect.h:117
@ DETECT_SM_LIST_POSTMATCH
Definition detect.h:127
FlowVar * FlowVarGet(Flow *f, uint32_t idx)
get the flowvar with index 'idx' from the flow
Definition flow-var.c:84
void FlowVarAddIntNoLock(Flow *f, uint32_t idx, uint32_t value)
Definition flow-var.c:162
#define FLOWVAR_TYPE_INT
Definition flow-var.h:34
DetectEngineCtx * de_ctx
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
struct Thresholds ctx
main detection engine ctx
Definition detect.h:932
uint8_t flags
Definition detect.h:934
union DetectFlowintData_::@76 target
uint32_t value
Definition flow-var.h:46
uint8_t datatype
Definition flow-var.h:57
FlowVarTypeInt fv_int
Definition flow-var.h:65
union FlowVar_::@124 data
Flow data structure.
Definition flow.h:356
uint8_t proto
Definition flow.h:378
struct Flow_ * flow
Definition decode.h:546
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition detect.h:351
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
void(* Free)(DetectEngineCtx *, void *)
Definition detect.h:1446
const char * desc
Definition detect.h:1461
void(* RegisterTests)(void)
Definition detect.h:1448
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition detect.h:1421
const char * name
Definition detect.h:1459
Signature container.
Definition detect.h:668
Per thread variable structure.
Definition threadvars.h:58
#define BUG_ON(x)
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61
#define SCStrdup(s)
Definition util-mem.h:56
#define unlikely(expr)
Packet * UTHBuildPacket(uint8_t *payload, uint16_t payload_len, uint8_t ipproto)
UTHBuildPacket is a wrapper that build packets with default ip and port fields.
int UTHAppendSigs(DetectEngineCtx *de_ctx, const char *sigs[], int numsigs)
UTHAppendSigs: Add sigs to the detection_engine checking for errors.
void UTHAssignFlow(Packet *p, Flow *f)
void UTHFreeFlow(Flow *flow)
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself.
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
void VarNameStoreUnregister(const uint32_t id, const enum VarTypes type)
uint32_t VarNameStoreRegister(const char *name, const enum VarTypes type)
uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
find name for id+type at packet time. As the active store won't be modified, we don't need locks.
@ VAR_TYPE_FLOW_INT
Definition util-var.h:37