suricata
detect-detection-filter.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 Gerardo Iglesias <iglesiasg@gmail.com>
22  *
23  * Implements the detection_filter keyword
24  */
25 
26 #include "suricata-common.h"
27 #include "suricata.h"
28 #include "decode.h"
29 #include "detect.h"
30 
31 #include "host.h"
32 
34 #include "detect-threshold.h"
35 #include "detect-parse.h"
36 
37 #include "util-byte.h"
38 #include "util-unittest-helper.h"
39 #include "util-debug.h"
40 #include "detect-engine-build.h"
41 #include "detect-engine-proto.h"
42 
43 #define TRACK_DST 1
44 #define TRACK_SRC 2
45 
46 /**
47  *\brief Regex for parsing our detection_filter options
48  */
49 #define PARSE_REGEX \
50  "^\\s*(track|count|seconds)\\s+(by_src|by_dst|by_flow|\\d+)\\s*,\\s*(track|count|seconds)\\s+" \
51  "(by_src|" \
52  "by_dst|by_flow|\\d+)\\s*,\\s*(track|count|seconds)\\s+(by_src|by_dst|by_flow|\\d+)" \
53  "(?:\\s*,\\s*unique_on\\s+(src_port|dst_port))?\\s*$"
54 
55 /* minimum number of PCRE submatches expected for detection_filter parse */
56 #define DF_PARSE_MIN_SUBMATCHES 5
57 
58 static DetectParseRegex parse_regex;
59 
60 static int DetectDetectionFilterMatch(
61  DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *);
62 static int DetectDetectionFilterSetup(DetectEngineCtx *, Signature *, const char *);
63 #ifdef UNITTESTS
64 static void DetectDetectionFilterRegisterTests(void);
65 #endif
66 static void DetectDetectionFilterFree(DetectEngineCtx *, void *);
67 
68 /**
69  * \brief Registration function for detection_filter: keyword
70  */
72 {
73  sigmatch_table[DETECT_DETECTION_FILTER].name = "detection_filter";
75  "alert on every match after a threshold has been reached";
76  sigmatch_table[DETECT_DETECTION_FILTER].url = "/rules/thresholding.html#detection-filter";
77  sigmatch_table[DETECT_DETECTION_FILTER].Match = DetectDetectionFilterMatch;
78  sigmatch_table[DETECT_DETECTION_FILTER].Setup = DetectDetectionFilterSetup;
79  sigmatch_table[DETECT_DETECTION_FILTER].Free = DetectDetectionFilterFree;
80 #ifdef UNITTESTS
81  sigmatch_table[DETECT_DETECTION_FILTER].RegisterTests = DetectDetectionFilterRegisterTests;
82 #endif
83  /* this is compatible to ip-only signatures */
85 
86  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
87 }
88 
89 static int DetectDetectionFilterMatch(
90  DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx)
91 {
92  return 1;
93 }
94 
95 /**
96  * \internal
97  * \brief This function is used to parse detection_filter options passed via detection_filter:
98  * keyword
99  *
100  * \param rawstr Pointer to the user provided detection_filter options
101  *
102  * \retval df pointer to DetectThresholdData on success
103  * \retval NULL on failure
104  */
105 static DetectThresholdData *DetectDetectionFilterParse(const char *rawstr)
106 {
107  DetectThresholdData *df = NULL;
108  int res = 0;
109  size_t pcre2_len;
110  const char *str_ptr = NULL;
111  char *args[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
112  char *copy_str = NULL, *df_opt = NULL;
113  int seconds_found = 0, count_found = 0, track_found = 0;
114  int seconds_pos = 0, count_pos = 0;
115  size_t pos = 0;
116  int i = 0;
117  int parsed_count = 0;
118  int ret = 0;
119  char *saveptr = NULL;
120  pcre2_match_data *match = NULL;
121 
122  copy_str = SCStrdup(rawstr);
123  if (unlikely(copy_str == NULL)) {
124  goto error;
125  }
126 
127  for (pos = 0, df_opt = strtok_r(copy_str, ",", &saveptr);
128  pos < strlen(copy_str) && df_opt != NULL;
129  pos++, df_opt = strtok_r(NULL, ",", &saveptr)) {
130  if (strstr(df_opt, "count"))
131  count_found++;
132  if (strstr(df_opt, "second"))
133  seconds_found++;
134  if (strstr(df_opt, "track"))
135  track_found++;
136  }
137  SCFree(copy_str);
138  copy_str = NULL;
139 
140  if (count_found != 1 || seconds_found != 1 || track_found != 1)
141  goto error;
142 
143  ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
144  if (ret < DF_PARSE_MIN_SUBMATCHES) {
145  SCLogError("pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr);
146  goto error;
147  }
148 
149  df = SCCalloc(1, sizeof(DetectThresholdData));
150  if (unlikely(df == NULL))
151  goto error;
152 
153  df->type = TYPE_DETECTION;
154 
155  for (i = 0; i < (ret - 1); i++) {
156  res = pcre2_substring_get_bynumber(match, i + 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
157  if (res < 0) {
158  SCLogError("pcre2_substring_get_bynumber failed");
159  goto error;
160  }
161 
162  args[i] = (char *)str_ptr;
163  parsed_count++;
164 
165  if (strncasecmp(args[i], "by_dst", strlen("by_dst")) == 0)
166  df->track = TRACK_DST;
167  if (strncasecmp(args[i], "by_src", strlen("by_src")) == 0)
168  df->track = TRACK_SRC;
169  if (strncasecmp(args[i], "by_flow", strlen("by_flow")) == 0)
170  df->track = TRACK_FLOW;
171  if (strncasecmp(args[i], "count", strlen("count")) == 0)
172  count_pos = i + 1;
173  if (strncasecmp(args[i], "seconds", strlen("seconds")) == 0)
174  seconds_pos = i + 1;
175  if (strcasecmp(args[i], "src_port") == 0)
177  if (strcasecmp(args[i], "dst_port") == 0)
179  }
180 
181  if (args[count_pos] == NULL || args[seconds_pos] == NULL) {
182  goto error;
183  }
184 
185  if (StringParseUint32(&df->count, 10, strlen(args[count_pos]), args[count_pos]) <= 0) {
186  goto error;
187  }
188 
189  if (StringParseUint32(&df->seconds, 10, strlen(args[seconds_pos]), args[seconds_pos]) <= 0) {
190  goto error;
191  }
192 
193  if (df->count == 0 || df->seconds == 0) {
194  SCLogError("found an invalid value");
195  goto error;
196  }
197 
198  for (i = 0; i < parsed_count; i++) {
199  if (args[i] != NULL)
200  pcre2_substring_free((PCRE2_UCHAR *)args[i]);
201  }
202 
203  pcre2_match_data_free(match);
204  return df;
205 
206 error:
207  for (i = 0; i < parsed_count; i++) {
208  if (args[i] != NULL)
209  pcre2_substring_free((PCRE2_UCHAR *)args[i]);
210  }
211  if (df != NULL)
212  SCFree(df);
213  if (match) {
214  pcre2_match_data_free(match);
215  }
216  return NULL;
217 }
218 
219 /**
220  * \internal
221  * \brief this function is used to add the parsed detection_filter into the current signature
222  *
223  * \param de_ctx pointer to the Detection Engine Context
224  * \param s pointer to the Current Signature
225  * \param m pointer to the Current SigMatch
226  * \param rawstr pointer to the user provided detection_filter options
227  *
228  * \retval 0 on Success
229  * \retval -1 on Failure
230  */
231 static int DetectDetectionFilterSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
232 {
233  SCEnter();
234  DetectThresholdData *df = NULL;
235  SigMatch *tmpm = NULL;
236 
237  /* checks if there's a previous instance of threshold */
239  if (tmpm != NULL) {
240  SCLogError("\"detection_filter\" and \"threshold\" are not allowed in the same rule");
241  SCReturnInt(-1);
242  }
243  /* checks there's no previous instance of detection_filter */
245  if (tmpm != NULL) {
246  SCLogError("At most one \"detection_filter\" is allowed per rule");
247  SCReturnInt(-1);
248  }
249 
250  df = DetectDetectionFilterParse(rawstr);
251  if (df == NULL)
252  goto error;
253 
254  /* unique_on requires a ported L4 protocol: tcp/udp/sctp */
255  if (df->unique_on != DF_UNIQUE_NONE) {
256  const bool has_tcp = DetectProtoHasExplicitProto(&s->init_data->proto, IPPROTO_TCP);
257  const bool has_udp = DetectProtoHasExplicitProto(&s->init_data->proto, IPPROTO_UDP);
258  const bool has_sctp = DetectProtoHasExplicitProto(&s->init_data->proto, IPPROTO_SCTP);
259  if (!(has_tcp || has_udp || has_sctp)) {
260  SCLogError("detection_filter unique_on requires protocol tcp/udp/sctp");
261  goto error;
262  }
263  }
264 
266  DETECT_SM_LIST_THRESHOLD) == NULL) {
267  goto error;
268  }
269 
270  return 0;
271 
272 error:
273  if (df)
274  SCFree(df);
275  return -1;
276 }
277 
278 /**
279  * \internal
280  * \brief this function will free memory associated with DetectThresholdData
281  *
282  * \param df_ptr pointer to DetectDetectionFilterData
283  */
284 static void DetectDetectionFilterFree(DetectEngineCtx *de_ctx, void *df_ptr)
285 {
287  if (df)
288  SCFree(df);
289 }
290 
291 /*
292  * ONLY TESTS BELOW THIS COMMENT
293  */
294 #ifdef UNITTESTS
295 #include "detect-engine.h"
296 #include "detect-engine-mpm.h"
297 #include "detect-engine-threshold.h"
298 #include "detect-engine-alert.h"
299 #include "util-hashlist.h"
300 #include "action-globals.h"
301 #include "packet.h"
302 
303 /* test seams from detect-engine-threshold.c */
304 void ThresholdForceAllocFail(int);
305 uint64_t ThresholdGetBitmapMemuse(void);
306 uint64_t ThresholdGetBitmapAllocFail(void);
307 
308 /**
309  * \test DetectDetectionFilterTestParse01 is a test for a valid detection_filter options
310  *
311  */
312 static int DetectDetectionFilterTestParse01(void)
313 {
314  DetectThresholdData *df = DetectDetectionFilterParse("track by_dst,count 10,seconds 60");
315  FAIL_IF_NULL(df);
316  FAIL_IF_NOT(df->track == TRACK_DST);
317  FAIL_IF_NOT(df->count == 10);
318  FAIL_IF_NOT(df->seconds == 60);
319  DetectDetectionFilterFree(NULL, df);
320 
321  PASS;
322 }
323 
324 /**
325  * \test DetectDetectionFilterTestParse02 is a test for a invalid detection_filter options
326  *
327  */
328 static int DetectDetectionFilterTestParse02(void)
329 {
330  DetectThresholdData *df = DetectDetectionFilterParse("track both,count 10,seconds 60");
331  FAIL_IF_NOT_NULL(df);
332 
333  PASS;
334 }
335 
336 /**
337  * \test DetectDetectionfilterTestParse03 is a test for a valid detection_filter options in any
338  * order
339  *
340  */
341 static int DetectDetectionFilterTestParse03(void)
342 {
343  DetectThresholdData *df = DetectDetectionFilterParse("track by_dst, seconds 60, count 10");
344  FAIL_IF_NULL(df);
345  FAIL_IF_NOT(df->track == TRACK_DST);
346  FAIL_IF_NOT(df->count == 10);
347  FAIL_IF_NOT(df->seconds == 60);
348  DetectDetectionFilterFree(NULL, df);
349 
350  PASS;
351 }
352 
353 /**
354  * \test DetectDetectionFilterTestParse04 is a test for an invalid detection_filter options in any
355  * order
356  *
357  */
358 static int DetectDetectionFilterTestParse04(void)
359 {
360  DetectThresholdData *df =
361  DetectDetectionFilterParse("count 10, track by_dst, seconds 60, count 10");
362  FAIL_IF_NOT_NULL(df);
363 
364  PASS;
365 }
366 
367 /**
368  * \test DetectDetectionFilterTestParse05 is a test for a valid detection_filter options in any
369  * order
370  *
371  */
372 static int DetectDetectionFilterTestParse05(void)
373 {
374  DetectThresholdData *df = DetectDetectionFilterParse("count 10, track by_dst, seconds 60");
375  FAIL_IF_NULL(df);
376  FAIL_IF_NOT(df->track == TRACK_DST);
377  FAIL_IF_NOT(df->count == 10);
378  FAIL_IF_NOT(df->seconds == 60);
379  DetectDetectionFilterFree(NULL, df);
380 
381  PASS;
382 }
383 
384 /**
385  * \test DetectDetectionFilterTestParse06 is a test for an invalid value in detection_filter
386  *
387  */
388 static int DetectDetectionFilterTestParse06(void)
389 {
390  DetectThresholdData *df = DetectDetectionFilterParse("count 10, track by_dst, seconds 0");
391  FAIL_IF_NOT_NULL(df);
392 
393  PASS;
394 }
395 /**
396  * \test unique_on requires tcp/udp/sctp protocol; alert ip should fail
397  */
398 static int DetectDetectionFilterUniqueOnProtoValidationFail(void)
399 {
400  ThresholdInit();
401 
404  de_ctx->flags |= DE_QUIET;
405 
407  "alert ip any any -> any any (msg:\"DF proto validation\"; "
408  "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:29;)");
409  /* setup should fail, append returns NULL */
410  FAIL_IF_NOT_NULL(s);
411 
414  PASS;
415 }
416 
417 /**
418  * \test DetectDetectionFilterTestParseUnique01 tests parsing unique_on dst_port
419  */
420 static int DetectDetectionFilterTestParseUnique01(void)
421 {
422  DetectThresholdData *df =
423  DetectDetectionFilterParse("track by_dst, count 10, seconds 60, unique_on dst_port");
424  FAIL_IF_NULL(df);
425  FAIL_IF_NOT(df->track == TRACK_DST);
426  FAIL_IF_NOT(df->count == 10);
427  FAIL_IF_NOT(df->seconds == 60);
429  DetectDetectionFilterFree(NULL, df);
430  PASS;
431 }
432 
433 /**
434  * \test Distinct boundary: exactly 'count' distinct should not alert
435  */
436 static int DetectDetectionFilterDistinctBoundaryNoAlert(void)
437 {
439  DetectEngineThreadCtx *det_ctx;
440 
441  ThresholdInit();
442  memset(&th_v, 0, sizeof(th_v));
444 
445  Packet *p1 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
446  Packet *p2 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 81);
447 
450  de_ctx->flags |= DE_QUIET;
451 
453  "alert tcp any any -> any any (msg:\"DF distinct boundary no alert\"; "
454  "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:24;)");
455  FAIL_IF_NULL(s);
456 
458  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
459 
460  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
461  FAIL_IF(PacketAlertCheck(p1, 24));
462  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
463  FAIL_IF(PacketAlertCheck(p2, 24));
464 
465  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
467  UTHFreePackets(&p1, 1);
468  UTHFreePackets(&p2, 1);
471  PASS;
472 }
473 
474 /**
475  * \test Distinct window reset: expire and re-trigger after seconds
476  */
477 static int DetectDetectionFilterDistinctWindowReset(void)
478 {
480  DetectEngineThreadCtx *det_ctx;
481 
482  ThresholdInit();
483  memset(&th_v, 0, sizeof(th_v));
485 
488  de_ctx->flags |= DE_QUIET;
489 
491  "alert tcp any any -> any any (msg:\"DF distinct window reset\"; "
492  "detection_filter: track by_dst, count 2, seconds 2, unique_on dst_port; sid:25;)");
493  FAIL_IF_NULL(s);
494 
496  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
497 
498  Packet *p1 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
499  p1->ts = TimeGet();
500  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
501  FAIL_IF(PacketAlertCheck(p1, 25));
502 
503  Packet *p2 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 81);
504  p2->ts = TimeGet();
505  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
506  FAIL_IF(PacketAlertCheck(p2, 25));
507 
508  Packet *p3 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 82);
509  p3->ts = TimeGet();
510  SigMatchSignatures(&th_v, de_ctx, det_ctx, p3);
511  FAIL_IF_NOT(PacketAlertCheck(p3, 25));
512 
513  /* advance time beyond window to force expiration */
515 
516  Packet *p4 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
517  p4->ts = TimeGet();
518  SigMatchSignatures(&th_v, de_ctx, det_ctx, p4);
519  FAIL_IF(PacketAlertCheck(p4, 25));
520 
521  Packet *p5 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 81);
522  p5->ts = TimeGet();
523  SigMatchSignatures(&th_v, de_ctx, det_ctx, p5);
524  FAIL_IF(PacketAlertCheck(p5, 25));
525 
526  Packet *p6 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 82);
527  p6->ts = TimeGet();
528  SigMatchSignatures(&th_v, de_ctx, det_ctx, p6);
529  FAIL_IF_NOT(PacketAlertCheck(p6, 25));
530 
531  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
533  UTHFreePackets(&p1, 1);
534  UTHFreePackets(&p2, 1);
535  UTHFreePackets(&p3, 1);
536  UTHFreePackets(&p4, 1);
537  UTHFreePackets(&p5, 1);
538  UTHFreePackets(&p6, 1);
541  PASS;
542 }
543 
544 /**
545  * \test When bitmap alloc fails, unique_on falls back to classic counting (> count)
546  */
547 static int DetectDetectionFilterDistinctAllocFailFallback(void)
548 {
550  DetectEngineThreadCtx *det_ctx;
551 
552  ThresholdInit();
553  memset(&th_v, 0, sizeof(th_v));
555 
558  de_ctx->flags |= DE_QUIET;
559 
560  /* Force allocation failure for distinct bitmap */
562 
564  "alert tcp any any -> any any (msg:\"DF alloc fail fallback\"; "
565  "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:27;)");
566  FAIL_IF_NULL(s);
567 
569  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
570 
571  Packet *p1 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
572  Packet *p2 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
573  Packet *p3 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
574 
575  int result = 0;
576 
577  /* Classic detection_filter alerts when current_count > count (i.e., 3rd packet) */
578  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
579  if (PacketAlertCheck(p1, 27))
580  goto end;
581  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
582  if (PacketAlertCheck(p2, 27))
583  goto end;
584  SigMatchSignatures(&th_v, de_ctx, det_ctx, p3);
585  if (!PacketAlertCheck(p3, 27))
586  goto end;
587 
588  result = 1;
589 
590 end:
591  /* cleanup and restore hook */
593  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
595  UTHFreePackets(&p1, 1);
596  UTHFreePackets(&p2, 1);
597  UTHFreePackets(&p3, 1);
600  return result;
601 }
602 
603 /**
604  * \test DetectDetectionFilterTestSig1 is a test for checking the working of detection_filter
605  * keyword by setting up the signature and later testing its working by matching the received packet
606  * against the sig.
607  *
608  */
609 static int DetectDetectionFilterTestSig1(void)
610 {
612  DetectEngineThreadCtx *det_ctx;
613 
614  ThresholdInit();
615 
616  memset(&th_v, 0, sizeof(th_v));
618 
619  Packet *p = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
620 
623 
624  de_ctx->flags |= DE_QUIET;
625 
627  "alert tcp any any -> any 80 (msg:\"detection_filter Test\"; detection_filter: "
628  "track by_dst, count 4, seconds 60; sid:1;)");
629  FAIL_IF_NULL(s);
630 
632  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
633 
634  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
636  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
638  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
640  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
642  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
644  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
646  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
648  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
650 
651  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
653 
654  UTHFreePackets(&p, 1);
657  PASS;
658 }
659 
660 /**
661  * \test DetectDetectionFilterTestSig2 is a test for checking the working of detection_filter
662  * keyword by setting up the signature and later testing its working by matching the received packet
663  * against the sig.
664  *
665  */
666 
667 static int DetectDetectionFilterTestSig2(void)
668 {
670  DetectEngineThreadCtx *det_ctx;
671 
672  ThresholdInit();
673 
674  memset(&th_v, 0, sizeof(th_v));
676 
677  Packet *p = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
678 
680 
682 
683  de_ctx->flags |= DE_QUIET;
684 
686  "alert tcp any any -> any 80 (msg:\"detection_filter Test 2\"; "
687  "detection_filter: track by_dst, count 4, seconds 60; sid:10;)");
688  FAIL_IF_NULL(s);
689 
691  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
692 
693  p->ts = TimeGet();
694 
695  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
696  FAIL_IF(PacketAlertCheck(p, 10));
697  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
698  FAIL_IF(PacketAlertCheck(p, 10));
699  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
700  FAIL_IF(PacketAlertCheck(p, 10));
701 
703  p->ts = TimeGet();
704 
705  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
706  FAIL_IF(PacketAlertCheck(p, 10));
707  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
708  FAIL_IF(PacketAlertCheck(p, 10));
709  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
710  FAIL_IF(PacketAlertCheck(p, 10));
711  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
712  FAIL_IF(PacketAlertCheck(p, 10));
713 
714  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
716 
717  UTHFreePackets(&p, 1);
720  PASS;
721 }
722 
723 /**
724  * \test drops
725  */
726 static int DetectDetectionFilterTestSig3(void)
727 {
729  DetectEngineThreadCtx *det_ctx;
730 
731  ThresholdInit();
732 
733  memset(&th_v, 0, sizeof(th_v));
735 
736  Packet *p = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
737 
740 
741  de_ctx->flags |= DE_QUIET;
742 
744  "drop tcp any any -> any 80 (msg:\"detection_filter Test 2\"; "
745  "detection_filter: track by_dst, count 2, seconds 60; sid:10;)");
746  FAIL_IF_NULL(s);
747 
749  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
750 
751  p->ts = TimeGet();
752 
753  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
754  FAIL_IF(PacketAlertCheck(p, 10));
755  FAIL_IF(PacketTestAction(p, ACTION_DROP));
756  p->action = 0;
757 
758  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
759  FAIL_IF(PacketAlertCheck(p, 10));
760  FAIL_IF(PacketTestAction(p, ACTION_DROP));
761  p->action = 0;
762 
763  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
765  FAIL_IF_NOT(PacketTestAction(p, ACTION_DROP));
766  p->action = 0;
767 
769  p->ts = TimeGet();
770 
771  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
772  FAIL_IF(PacketAlertCheck(p, 10));
773  FAIL_IF(PacketTestAction(p, ACTION_DROP));
774  p->action = 0;
775 
776  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
777  FAIL_IF(PacketAlertCheck(p, 10));
778  FAIL_IF(PacketTestAction(p, ACTION_DROP));
779  p->action = 0;
780 
781  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
783  FAIL_IF_NOT(PacketTestAction(p, ACTION_DROP));
784  p->action = 0;
785 
786  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
788 
789  UTHFreePackets(&p, 1);
792  PASS;
793 }
794 
795 /**
796  * \test Verify bitmap memory is tracked in bitmap_memuse counter
797  */
798 static int DetectDetectionFilterDistinctBitmapMemuseTracking(void)
799 {
801  DetectEngineThreadCtx *det_ctx;
802 
803  ThresholdInit();
804  memset(&th_v, 0, sizeof(th_v));
806 
807  /* Record baseline memuse */
808  uint64_t baseline_memuse = ThresholdGetBitmapMemuse();
809 
812  de_ctx->flags |= DE_QUIET;
813 
815  "alert tcp any any -> any any (msg:\"DF memuse tracking\"; "
816  "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:30;)");
817  FAIL_IF_NULL(s);
818 
820  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
821 
822  /* Send a packet to trigger threshold entry creation with bitmap */
823  Packet *p1 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
824  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
825 
826  /* Verify bitmap_memuse increased by 8192 bytes (65536/8) */
827  uint64_t after_memuse = ThresholdGetBitmapMemuse();
828  FAIL_IF_NOT(after_memuse == baseline_memuse + 8192);
829 
830  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
832  UTHFreePackets(&p1, 1);
834 
835  /* After destroy, bitmap_memuse should return to baseline */
836  uint64_t final_memuse = ThresholdGetBitmapMemuse();
837  FAIL_IF_NOT(final_memuse == baseline_memuse);
838 
840  PASS;
841 }
842 
843 /**
844  * \test Verify bitmap_alloc_fail counter increments on forced failure
845  */
846 static int DetectDetectionFilterDistinctAllocFailCounter(void)
847 {
849  DetectEngineThreadCtx *det_ctx;
850 
851  ThresholdInit();
852  memset(&th_v, 0, sizeof(th_v));
854 
855  /* Record baseline alloc fail count */
856  uint64_t baseline_fail = ThresholdGetBitmapAllocFail();
857 
860  de_ctx->flags |= DE_QUIET;
861 
862  /* Force allocation failure */
864 
866  "alert tcp any any -> any any (msg:\"DF alloc fail counter\"; "
867  "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:31;)");
868  FAIL_IF_NULL(s);
869 
871  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
872 
873  /* Send packet to trigger threshold entry creation (bitmap alloc will fail) */
874  Packet *p1 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
875  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
876 
877  /* Verify alloc_fail counter increased */
878  uint64_t after_fail = ThresholdGetBitmapAllocFail();
879  FAIL_IF_NOT(after_fail == baseline_fail + 1);
880 
881  /* bitmap_memuse should NOT have increased since alloc failed */
882  uint64_t memuse = ThresholdGetBitmapMemuse();
883  FAIL_IF_NOT(memuse == 0);
884 
885  /* cleanup */
887  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
889  UTHFreePackets(&p1, 1);
892  PASS;
893 }
894 
895 /**
896  * \test Multiple distinct trackers should accumulate bitmap memory
897  */
898 static int DetectDetectionFilterDistinctMultipleTrackers(void)
899 {
901  DetectEngineThreadCtx *det_ctx;
902 
903  ThresholdInit();
904  memset(&th_v, 0, sizeof(th_v));
906 
907  uint64_t baseline_memuse = ThresholdGetBitmapMemuse();
908 
911  de_ctx->flags |= DE_QUIET;
912 
914  "alert tcp any any -> any any (msg:\"DF multi tracker\"; "
915  "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:32;)");
916  FAIL_IF_NULL(s);
917 
919  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
920 
921  /* Create packets to different destinations - each will create a new threshold entry */
922  Packet *p1 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
923  Packet *p2 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "3.3.3.3", 1024, 80);
924  Packet *p3 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "4.4.4.4", 1024, 80);
925 
926  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
927  SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
928  SigMatchSignatures(&th_v, de_ctx, det_ctx, p3);
929 
930  /* Verify 3 bitmaps allocated = 3 * 8192 = 24576 bytes */
931  uint64_t after_memuse = ThresholdGetBitmapMemuse();
932  FAIL_IF_NOT(after_memuse == baseline_memuse + (3 * 8192));
933 
934  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
936  UTHFreePackets(&p1, 1);
937  UTHFreePackets(&p2, 1);
938  UTHFreePackets(&p3, 1);
940 
941  /* After destroy, should return to baseline */
942  uint64_t final_memuse = ThresholdGetBitmapMemuse();
943  FAIL_IF_NOT(final_memuse == baseline_memuse);
944 
946  PASS;
947 }
948 
949 /**
950  * \test Bitmap memory is freed when threshold entry expires
951  */
952 static int DetectDetectionFilterDistinctBitmapExpiry(void)
953 {
955  DetectEngineThreadCtx *det_ctx;
956 
957  ThresholdInit();
958  memset(&th_v, 0, sizeof(th_v));
960 
961  uint64_t baseline_memuse = ThresholdGetBitmapMemuse();
962 
965  de_ctx->flags |= DE_QUIET;
966 
967  /* Use short timeout (2 seconds) */
969  "alert tcp any any -> any any (msg:\"DF bitmap expiry\"; "
970  "detection_filter: track by_dst, count 2, seconds 2, unique_on dst_port; sid:33;)");
971  FAIL_IF_NULL(s);
972 
974  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
975 
976  Packet *p1 = UTHBuildPacketReal(NULL, 0, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
977  p1->ts = TimeGet();
978  SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
979 
980  /* Verify bitmap allocated */
981  uint64_t after_alloc = ThresholdGetBitmapMemuse();
982  FAIL_IF_NOT(after_alloc == baseline_memuse + 8192);
983 
984  /* Advance time beyond the timeout to expire the entry */
986 
987  /* Trigger expiration by calling ThresholdsExpire */
988  SCTime_t now = TimeGet();
989  ThresholdsExpire(now);
990 
991  /* After expiry, bitmap memory should be freed */
992  uint64_t after_expiry = ThresholdGetBitmapMemuse();
993  FAIL_IF_NOT(after_expiry == baseline_memuse);
994 
995  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
997  UTHFreePackets(&p1, 1);
1000  PASS;
1001 }
1002 
1003 static void DetectDetectionFilterRegisterTests(void)
1004 {
1005  UtRegisterTest("DetectDetectionFilterTestParse01", DetectDetectionFilterTestParse01);
1006  UtRegisterTest("DetectDetectionFilterTestParse02", DetectDetectionFilterTestParse02);
1007  UtRegisterTest("DetectDetectionFilterTestParse03", DetectDetectionFilterTestParse03);
1008  UtRegisterTest("DetectDetectionFilterTestParse04", DetectDetectionFilterTestParse04);
1009  UtRegisterTest("DetectDetectionFilterTestParse05", DetectDetectionFilterTestParse05);
1010  UtRegisterTest("DetectDetectionFilterTestParse06", DetectDetectionFilterTestParse06);
1012  "DetectDetectionFilterTestParseUnique01", DetectDetectionFilterTestParseUnique01);
1013  UtRegisterTest("DetectDetectionFilterTestSig1", DetectDetectionFilterTestSig1);
1014  UtRegisterTest("DetectDetectionFilterTestSig2", DetectDetectionFilterTestSig2);
1015  UtRegisterTest("DetectDetectionFilterTestSig3", DetectDetectionFilterTestSig3);
1016  UtRegisterTest("DetectDetectionFilterDistinctBoundaryNoAlert",
1017  DetectDetectionFilterDistinctBoundaryNoAlert);
1019  "DetectDetectionFilterDistinctWindowReset", DetectDetectionFilterDistinctWindowReset);
1020  UtRegisterTest("DetectDetectionFilterDistinctAllocFailFallback",
1021  DetectDetectionFilterDistinctAllocFailFallback);
1022  UtRegisterTest("DetectDetectionFilterUniqueOnProtoValidationFail",
1023  DetectDetectionFilterUniqueOnProtoValidationFail);
1024  UtRegisterTest("DetectDetectionFilterDistinctBitmapMemuseTracking",
1025  DetectDetectionFilterDistinctBitmapMemuseTracking);
1026  UtRegisterTest("DetectDetectionFilterDistinctAllocFailCounter",
1027  DetectDetectionFilterDistinctAllocFailCounter);
1028  UtRegisterTest("DetectDetectionFilterDistinctMultipleTrackers",
1029  DetectDetectionFilterDistinctMultipleTrackers);
1031  "DetectDetectionFilterDistinctBitmapExpiry", DetectDetectionFilterDistinctBitmapExpiry);
1032 }
1033 #endif /* UNITTESTS */
util-byte.h
host.h
SigTableElmt_::url
const char * url
Definition: detect.h:1545
detect-engine.h
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
detect-engine-proto.h
SigTableElmt_::desc
const char * desc
Definition: detect.h:1544
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:78
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1529
util-hashlist.h
PARSE_REGEX
#define PARSE_REGEX
Regex for parsing our detection_filter options.
Definition: detect-detection-filter.c:49
DetectParseRegex
Definition: detect-parse.h:94
SigTableElmt_::name
const char * name
Definition: detect.h:1542
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:101
SigTableElmt_::flags
uint32_t flags
Definition: detect.h:1533
PacketAlertCheck
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
Definition: detect-engine-alert.c:144
DetectThresholdData_::count
uint32_t count
Definition: detect-threshold.h:63
action-globals.h
Packet_::action
uint8_t action
Definition: decode.h:624
SCDetectGetLastSMFromLists
SigMatch * SCDetectGetLastSMFromLists(const Signature *s,...)
Returns the sm with the largest index (added latest) from the lists passed to us.
Definition: detect-parse.c:600
DETECT_SM_LIST_THRESHOLD
@ DETECT_SM_LIST_THRESHOLD
Definition: detect.h:134
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:995
DF_UNIQUE_DST_PORT
@ DF_UNIQUE_DST_PORT
Definition: detect-threshold.h:54
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2912
TRACK_DST
#define TRACK_DST
Definition: detect-detection-filter.c:43
DE_QUIET
#define DE_QUIET
Definition: detect.h:334
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:3305
p
Packet * p
Definition: fuzz_dataset.c:30
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, pcre2_match_data **match, const char *str, int start_offset, int options)
Definition: detect-parse.c:4019
DetectEngineAppendSig
Signature * DetectEngineAppendSig(DetectEngineCtx *, const char *)
Parse and append a Signature into the Detection Engine Context signature list.
Definition: detect-parse.c:3965
UTHBuildPacketReal
Packet * UTHBuildPacketReal(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, const char *src, const char *dst, uint16_t sport, uint16_t dport)
UTHBuildPacketReal is a function that create tcp/udp packets for unittests specifying ip and port sou...
Definition: util-unittest-helper.c:136
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1524
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
DetectThresholdData_::unique_on
enum DetectThresholdUniqueOn unique_on
Definition: detect-threshold.h:71
DetectThresholdData_::type
uint8_t type
Definition: detect-threshold.h:65
ThresholdForceAllocFail
void ThresholdForceAllocFail(int)
Definition: detect-engine-threshold.c:76
ThresholdGetBitmapAllocFail
uint64_t ThresholdGetBitmapAllocFail(void)
Definition: detect-engine-threshold.c:86
decode.h
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
TRACK_FLOW
#define TRACK_FLOW
Definition: detect-threshold.h:40
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
detect-detection-filter.h
DetectEngineThreadCtx_
Definition: detect.h:1316
Packet_::ts
SCTime_t ts
Definition: decode.h:570
DETECT_THRESHOLD
@ DETECT_THRESHOLD
Definition: detect-engine-register.h:67
DetectSetupParseRegexes
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
Definition: detect-parse.c:4145
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
detect-engine-mpm.h
SCSigMatchAppendSMToList
SigMatch * SCSigMatchAppendSMToList(DetectEngineCtx *de_ctx, Signature *s, uint16_t type, SigMatchCtx *ctx, const int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:424
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data)
initialize thread specific detection engine context
Definition: detect-engine.c:3660
SignatureInitData_::proto
DetectProto proto
Definition: detect.h:655
StringParseUint32
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition: util-byte.c:268
ThresholdDestroy
void ThresholdDestroy(void)
Definition: detect-engine-threshold.c:155
TimeSetIncrementTime
void TimeSetIncrementTime(uint32_t tv_sec)
increment the time in the engine
Definition: util-time.c:180
Packet_
Definition: decode.h:516
SIGMATCH_IPONLY_COMPAT
#define SIGMATCH_IPONLY_COMPAT
Definition: detect-engine-register.h:310
detect-engine-build.h
TimeGet
SCTime_t TimeGet(void)
Definition: util-time.c:152
detect-engine-alert.h
SCTime_t
Definition: util-time.h:40
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:775
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1504
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2300
DetectThresholdData_::track
uint8_t track
Definition: detect-threshold.h:66
StatsThreadInit
void StatsThreadInit(StatsThreadContext *stats)
Definition: counters.c:1332
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:355
th_v
ThreadVars * th_v
Definition: fuzz_dataset.c:29
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
suricata-common.h
DetectThresholdData_
Definition: detect-threshold.h:62
packet.h
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *tv, void *data)
Definition: detect-engine.c:3905
DF_PARSE_MIN_SUBMATCHES
#define DF_PARSE_MIN_SUBMATCHES
Definition: detect-detection-filter.c:56
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
ThresholdGetBitmapMemuse
uint64_t ThresholdGetBitmapMemuse(void)
Definition: detect-engine-threshold.c:81
DETECT_DETECTION_FILTER
@ DETECT_DETECTION_FILTER
Definition: detect-engine-register.h:130
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SCFree
#define SCFree(p)
Definition: util-mem.h:61
detect-parse.h
DetectDetectionFilterRegister
void DetectDetectionFilterRegister(void)
Registration function for detection_filter: keyword.
Definition: detect-detection-filter.c:71
Signature_
Signature container.
Definition: detect.h:692
SigMatch_
a single match condition for a signature
Definition: detect.h:360
DF_UNIQUE_NONE
@ DF_UNIQUE_NONE
Definition: detect-threshold.h:52
detect-threshold.h
DetectProtoHasExplicitProto
bool DetectProtoHasExplicitProto(const DetectProto *dp, const uint8_t proto)
see if a DetectProto explicitly a certain proto Explicit means the protocol was explicitly set,...
Definition: detect-engine-proto.c:132
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2873
suricata.h
TRACK_SRC
#define TRACK_SRC
Definition: detect-detection-filter.c:44
DF_UNIQUE_SRC_PORT
@ DF_UNIQUE_SRC_PORT
Definition: detect-threshold.h:53
IPPROTO_SCTP
#define IPPROTO_SCTP
Definition: decode.h:1273
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:997
DetectThresholdData_::seconds
uint32_t seconds
Definition: detect-threshold.h:64
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:120
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
StatsThreadCleanup
void StatsThreadCleanup(StatsThreadContext *stats)
Definition: counters.c:1428
ThresholdInit
void ThresholdInit(void)
Definition: detect-engine-threshold.c:133
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1531
detect-engine-threshold.h
ThresholdsExpire
uint32_t ThresholdsExpire(const SCTime_t ts)
Definition: detect-engine-threshold.c:390
TYPE_DETECTION
#define TYPE_DETECTION
Definition: detect-threshold.h:30
UTHFreePackets
void UTHFreePackets(Packet **p, int numpkts)
UTHFreePackets: function to release the allocated data from UTHBuildPacket and the packet itself.
Definition: util-unittest-helper.c:453