suricata
detect-flow.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 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 Victor Julien <victor@inliniac.net>
22  *
23  * FLOW part of the detection engine.
24  */
25 
26 #include "suricata-common.h"
27 #include "debug.h"
28 #include "decode.h"
29 
30 #include "detect.h"
31 #include "detect-parse.h"
32 #include "detect-engine.h"
34 
35 #include "flow.h"
36 #include "flow-var.h"
37 
38 #include "detect-flow.h"
39 
40 #include "util-unittest.h"
41 #include "util-unittest-helper.h"
42 #include "util-debug.h"
43 
44 /**
45  * \brief Regex for parsing our flow options
46  */
47 #define PARSE_REGEX "^\\s*([A-z_]+)\\s*(?:,\\s*([A-z_]+))?\\s*(?:,\\s*([A-z_]+))?\\s*$"
48 
49 static pcre *parse_regex;
50 static pcre_extra *parse_regex_study;
51 
53  const Signature *, const SigMatchCtx *);
54 static int DetectFlowSetup (DetectEngineCtx *, Signature *, const char *);
55 void DetectFlowRegisterTests(void);
56 void DetectFlowFree(void *);
57 
58 static int PrefilterSetupFlow(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
59 static _Bool PrefilterFlowIsPrefilterable(const Signature *s);
60 
61 /**
62  * \brief Registration function for flow: keyword
63  */
64 void DetectFlowRegister (void)
65 {
67  sigmatch_table[DETECT_FLOW].desc = "match on direction and state of the flow";
68  sigmatch_table[DETECT_FLOW].url = DOC_URL DOC_VERSION "/rules/flow-keywords.html#flow";
70  sigmatch_table[DETECT_FLOW].Setup = DetectFlowSetup;
73 
74  sigmatch_table[DETECT_FLOW].SupportsPrefilter = PrefilterFlowIsPrefilterable;
75  sigmatch_table[DETECT_FLOW].SetupPrefilter = PrefilterSetupFlow;
76 
77  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex, &parse_regex_study);
78 }
79 
80 /**
81  * \param pflags packet flags (p->flags)
82  * \param pflowflags packet flow flags (p->flowflags)
83  * \param tflags detection flags (det_ctx->flags)
84  * \param dflags detect flow flags
85  * \param match_cnt number of matches to trigger
86  */
87 static inline int FlowMatch(const uint32_t pflags, const uint8_t pflowflags,
88  const uint16_t tflags, const uint16_t dflags, const uint8_t match_cnt)
89 {
90  uint8_t cnt = 0;
91 
92  if ((dflags & DETECT_FLOW_FLAG_NO_FRAG) &&
93  (!(pflags & PKT_REBUILT_FRAGMENT))) {
94  cnt++;
95  } else if ((dflags & DETECT_FLOW_FLAG_ONLY_FRAG) &&
96  (pflags & PKT_REBUILT_FRAGMENT)) {
97  cnt++;
98  }
99 
100  if ((dflags & DETECT_FLOW_FLAG_TOSERVER) && (pflowflags & FLOW_PKT_TOSERVER)) {
101  cnt++;
102  } else if ((dflags & DETECT_FLOW_FLAG_TOCLIENT) && (pflowflags & FLOW_PKT_TOCLIENT)) {
103  cnt++;
104  }
105 
106  if ((dflags & DETECT_FLOW_FLAG_ESTABLISHED) && (pflowflags & FLOW_PKT_ESTABLISHED)) {
107  cnt++;
108  } else if (dflags & DETECT_FLOW_FLAG_NOT_ESTABLISHED && (!(pflowflags & FLOW_PKT_ESTABLISHED))) {
109  cnt++;
110  } else if (dflags & DETECT_FLOW_FLAG_STATELESS) {
111  cnt++;
112  }
113 
115  if (dflags & DETECT_FLOW_FLAG_ONLYSTREAM)
116  cnt++;
117  } else {
118  if (dflags & DETECT_FLOW_FLAG_NOSTREAM)
119  cnt++;
120  }
121 
122  return (match_cnt == cnt) ? 1 : 0;
123 }
124 
125 /**
126  * \brief This function is used to match flow flags set on a packet with those passed via flow:
127  *
128  * \param t pointer to thread vars
129  * \param det_ctx pointer to the pattern matcher thread
130  * \param p pointer to the current packet
131  * \param m pointer to the sigmatch that we will cast into DetectFlowData
132  *
133  * \retval 0 no match
134  * \retval 1 match
135  */
137  const Signature *s, const SigMatchCtx *ctx)
138 {
139  SCEnter();
140 
141  SCLogDebug("pkt %p", p);
142 
143  if (p->flowflags & FLOW_PKT_TOSERVER) {
144  SCLogDebug("FLOW_PKT_TOSERVER");
145  } else if (p->flowflags & FLOW_PKT_TOCLIENT) {
146  SCLogDebug("FLOW_PKT_TOCLIENT");
147  }
148 
149  if (p->flowflags & FLOW_PKT_ESTABLISHED) {
150  SCLogDebug("FLOW_PKT_ESTABLISHED");
151  }
152 
153  const DetectFlowData *fd = (const DetectFlowData *)ctx;
154 
155  const int ret = FlowMatch(p->flags, p->flowflags, det_ctx->flags, fd->flags, fd->match_cnt);
156  SCLogDebug("returning %" PRId32 " fd->match_cnt %" PRId32 " fd->flags 0x%02X p->flowflags 0x%02X",
157  ret, fd->match_cnt, fd->flags, p->flowflags);
158  SCReturnInt(ret);
159 }
160 
161 /**
162  * \brief This function is used to parse flow options passed via flow: keyword
163  *
164  * \param flowstr Pointer to the user provided flow options
165  *
166  * \retval fd pointer to DetectFlowData on success
167  * \retval NULL on failure
168  */
169 static DetectFlowData *DetectFlowParse (const char *flowstr)
170 {
171  DetectFlowData *fd = NULL;
172  char *args[3] = {NULL,NULL,NULL};
173 #define MAX_SUBSTRINGS 30
174  int ret = 0, res = 0;
175  int ov[MAX_SUBSTRINGS];
176  char str1[16] = "", str2[16] = "", str3[16] = "";
177 
178  ret = pcre_exec(parse_regex, parse_regex_study, flowstr, strlen(flowstr), 0, 0, ov, MAX_SUBSTRINGS);
179  if (ret < 1 || ret > 4) {
180  SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 ", string %s", ret, flowstr);
181  goto error;
182  }
183 
184  if (ret > 1) {
185  res = pcre_copy_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 1, str1, sizeof(str1));
186  if (res < 0) {
187  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
188  goto error;
189  }
190  args[0] = (char *)str1;
191 
192  if (ret > 2) {
193  res = pcre_copy_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 2, str2, sizeof(str2));
194  if (res < 0) {
195  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
196  goto error;
197  }
198  args[1] = (char *)str2;
199  }
200  if (ret > 3) {
201  res = pcre_copy_substring((char *)flowstr, ov, MAX_SUBSTRINGS, 3, str3, sizeof(str3));
202  if (res < 0) {
203  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_copy_substring failed");
204  goto error;
205  }
206  args[2] = (char *)str3;
207  }
208  }
209 
210  fd = SCMalloc(sizeof(DetectFlowData));
211  if (unlikely(fd == NULL))
212  goto error;
213  fd->flags = 0;
214  fd->match_cnt = 0;
215 
216  int i;
217  for (i = 0; i < (ret - 1); i++) {
218  if (args[i]) {
219  /* inspect our options and set the flags */
220  if (strcasecmp(args[i], "established") == 0) {
222  SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_ESTABLISHED flag is already set");
223  goto error;
224  } else if (fd->flags & DETECT_FLOW_FLAG_STATELESS) {
225  SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_STATELESS already set");
226  goto error;
227  }
229  } else if (strcasecmp(args[i], "not_established") == 0) {
231  SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_NOT_ESTABLISHED flag is already set");
232  goto error;
233  } else if (fd->flags & DETECT_FLOW_FLAG_NOT_ESTABLISHED) {
234  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_NOT_ESTABLISHED, DETECT_FLOW_FLAG_ESTABLISHED already set");
235  goto error;
236  }
238  } else if (strcasecmp(args[i], "stateless") == 0) {
239  if (fd->flags & DETECT_FLOW_FLAG_STATELESS) {
240  SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_STATELESS flag is already set");
241  goto error;
242  } else if (fd->flags & DETECT_FLOW_FLAG_ESTABLISHED) {
243  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_STATELESS, DETECT_FLOW_FLAG_ESTABLISHED already set");
244  goto error;
245  }
247  } else if (strcasecmp(args[i], "to_client") == 0 || strcasecmp(args[i], "from_server") == 0) {
248  if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
249  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_TOCLIENT flag is already set");
250  goto error;
251  } else if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
252  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set to_client, DETECT_FLOW_FLAG_TOSERVER already set");
253  goto error;
254  }
256  } else if (strcasecmp(args[i], "to_server") == 0 || strcasecmp(args[i], "from_client") == 0){
257  if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
258  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_TOSERVER flag is already set");
259  goto error;
260  } else if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
261  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set to_server, DETECT_FLOW_FLAG_TO_CLIENT flag already set");
262  goto error;
263  }
265  } else if (strcasecmp(args[i], "only_stream") == 0) {
267  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_stream flag is already set");
268  goto error;
269  } else if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) {
270  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_stream flag, DETECT_FLOW_FLAG_NOSTREAM already set");
271  goto error;
272  }
274  } else if (strcasecmp(args[i], "no_stream") == 0) {
275  if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) {
276  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_stream flag is already set");
277  goto error;
278  } else if (fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM) {
279  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_stream flag, DETECT_FLOW_FLAG_ONLYSTREAM already set");
280  goto error;
281  }
283  } else if (strcasecmp(args[i], "no_frag") == 0) {
284  if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) {
285  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_frag flag is already set");
286  goto error;
287  } else if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) {
288  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_frag flag, only_frag already set");
289  goto error;
290  }
292  } else if (strcasecmp(args[i], "only_frag") == 0) {
293  if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) {
294  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_frag flag is already set");
295  goto error;
296  } else if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) {
297  SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_frag flag, no_frag already set");
298  goto error;
299  }
301  } else {
302  SCLogError(SC_ERR_INVALID_VALUE, "invalid flow option \"%s\"", args[i]);
303  goto error;
304  }
305 
306  fd->match_cnt++;
307  //printf("args[%" PRId32 "]: %s match_cnt: %" PRId32 " flags: 0x%02X\n", i, args[i], fd->match_cnt, fd->flags);
308  }
309  }
310  return fd;
311 
312 error:
313  if (fd != NULL)
314  DetectFlowFree(fd);
315  return NULL;
316 
317 }
318 
320 {
321 #define SIG_FLAG_BOTH (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)
322  BUG_ON(flags == 0);
323  BUG_ON(flags & ~SIG_FLAG_BOTH);
324  BUG_ON((flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH);
325 
326  SCLogDebug("want %08lx", flags & SIG_FLAG_BOTH);
327  SCLogDebug("have %08lx", s->flags & SIG_FLAG_BOTH);
328 
329  if (flags & SIG_FLAG_TOSERVER) {
330  if ((s->flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH) {
331  /* both is set if we just have 'flow:established' */
332  s->flags &= ~SIG_FLAG_TOCLIENT;
333  } else if (s->flags & SIG_FLAG_TOCLIENT) {
334  return -1;
335  }
336  s->flags |= SIG_FLAG_TOSERVER;
337  } else {
338  if ((s->flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH) {
339  /* both is set if we just have 'flow:established' */
340  s->flags &= ~SIG_FLAG_TOSERVER;
341  } else if (s->flags & SIG_FLAG_TOSERVER) {
342  return -1;
343  }
344  s->flags |= SIG_FLAG_TOCLIENT;
345  }
346  return 0;
347 #undef SIG_FLAG_BOTH
348 }
349 
350 /**
351  * \brief this function is used to add the parsed flowdata into the current signature
352  *
353  * \param de_ctx pointer to the Detection Engine Context
354  * \param s pointer to the Current Signature
355  * \param flowstr pointer to the user provided flow options
356  *
357  * \retval 0 on Success
358  * \retval -1 on Failure
359  */
360 int DetectFlowSetup (DetectEngineCtx *de_ctx, Signature *s, const char *flowstr)
361 {
362  /* ensure only one flow option */
364  SCLogError (SC_ERR_INVALID_SIGNATURE, "A signature may have only one flow option.");
365  return -1;
366  }
367 
368  DetectFlowData *fd = DetectFlowParse(flowstr);
369  if (fd == NULL)
370  return -1;
371 
372  SigMatch *sm = SigMatchAlloc();
373  if (sm == NULL)
374  goto error;
375 
376  sm->type = DETECT_FLOW;
377  sm->ctx = (SigMatchCtx *)fd;
378 
379  /* set the signature direction flags */
380  if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
381  s->flags |= SIG_FLAG_TOSERVER;
382  } else if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
383  s->flags |= SIG_FLAG_TOCLIENT;
384  } else {
385  s->flags |= SIG_FLAG_TOSERVER;
386  s->flags |= SIG_FLAG_TOCLIENT;
387  }
390  }
391  if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) {
393  } else if (fd->flags == DETECT_FLOW_FLAG_TOSERVER ||
395  {
396  /* no direct flow is needed for just direction,
397  * no sigmatch is needed either. */
398  SigMatchFree(sm);
399  sm = NULL;
400  } else {
402  }
403 
404  if (sm != NULL) {
406  }
407  return 0;
408 
409 error:
410  if (fd != NULL)
411  DetectFlowFree(fd);
412  return -1;
413 
414 }
415 
416 /**
417  * \brief this function will free memory associated with DetectFlowData
418  *
419  * \param fd pointer to DetectFlowData
420  */
421 void DetectFlowFree(void *ptr)
422 {
423  DetectFlowData *fd = (DetectFlowData *)ptr;
424  SCFree(fd);
425 }
426 
427 static void
428 PrefilterPacketFlowMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
429 {
430  const PrefilterPacketHeaderCtx *ctx = pectx;
431 
432  if (PrefilterPacketHeaderExtraMatch(ctx, p) == FALSE)
433  return;
434 
435  if (FlowMatch(p->flags, p->flowflags, det_ctx->flags, ctx->v1.u8[0], ctx->v1.u8[1]))
436  {
437  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
438  }
439 }
440 
441 static void
442 PrefilterPacketFlowSet(PrefilterPacketHeaderValue *v, void *smctx)
443 {
444  const DetectFlowData *fb = smctx;
445  v->u8[0] = fb->flags;
446  v->u8[1] = fb->match_cnt;
447 }
448 
449 static _Bool
450 PrefilterPacketFlowCompare(PrefilterPacketHeaderValue v, void *smctx)
451 {
452  const DetectFlowData *fb = smctx;
453  if (v.u8[0] == fb->flags &&
454  v.u8[1] == fb->match_cnt)
455  {
456  return TRUE;
457  }
458  return FALSE;
459 }
460 
461 static int PrefilterSetupFlow(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
462 {
463  return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_FLOW,
464  PrefilterPacketFlowSet,
465  PrefilterPacketFlowCompare,
466  PrefilterPacketFlowMatch);
467 }
468 
469 static _Bool PrefilterFlowIsPrefilterable(const Signature *s)
470 {
471  const SigMatch *sm;
472  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
473  switch (sm->type) {
474  case DETECT_FLOW:
475  return TRUE;
476  }
477  }
478  return FALSE;
479 }
480 
481 #ifdef UNITTESTS
482 
483 /**
484  * \test DetectFlowTestParse01 is a test to make sure that we return "something"
485  * when given valid flow opt
486  */
487 static int DetectFlowTestParse01 (void)
488 {
489  DetectFlowData *fd = NULL;
490  fd = DetectFlowParse("established");
491  FAIL_IF_NULL(fd);
492  DetectFlowFree(fd);
493  PASS;
494 }
495 
496 /**
497  * \test DetectFlowTestParse02 is a test for setting the established flow opt
498  */
499 static int DetectFlowTestParse02 (void)
500 {
501  DetectFlowData *fd = NULL;
502  fd = DetectFlowParse("established");
503  FAIL_IF_NULL(fd);
505  fd->match_cnt == 1);
506  PASS;
507 }
508 
509 /**
510  * \test DetectFlowTestParse03 is a test for setting the stateless flow opt
511  */
512 static int DetectFlowTestParse03 (void)
513 {
514  DetectFlowData *fd = NULL;
515  fd = DetectFlowParse("stateless");
516  FAIL_IF_NULL(fd);
518  DetectFlowFree(fd);
519  PASS;
520 }
521 
522 /**
523  * \test DetectFlowTestParse04 is a test for setting the to_client flow opt
524  */
525 static int DetectFlowTestParse04 (void)
526 {
527  DetectFlowData *fd = NULL;
528  fd = DetectFlowParse("to_client");
529  FAIL_IF_NULL(fd);
531  DetectFlowFree(fd);
532  PASS;
533 }
534 
535 /**
536  * \test DetectFlowTestParse05 is a test for setting the to_server flow opt
537  */
538 static int DetectFlowTestParse05 (void)
539 {
540  DetectFlowData *fd = NULL;
541  fd = DetectFlowParse("to_server");
542  FAIL_IF_NULL(fd);
544  DetectFlowFree(fd);
545  PASS;
546 }
547 
548 /**
549  * \test DetectFlowTestParse06 is a test for setting the from_server flow opt
550  */
551 static int DetectFlowTestParse06 (void)
552 {
553  DetectFlowData *fd = NULL;
554  fd = DetectFlowParse("from_server");
555  FAIL_IF_NULL(fd);
557  DetectFlowFree(fd);
558  PASS;
559 }
560 
561 /**
562  * \test DetectFlowTestParse07 is a test for setting the from_client flow opt
563  */
564 static int DetectFlowTestParse07 (void)
565 {
566  DetectFlowData *fd = NULL;
567  fd = DetectFlowParse("from_client");
568  FAIL_IF_NULL(fd);
570  DetectFlowFree(fd);
571  PASS;
572 }
573 
574 /**
575  * \test DetectFlowTestParse08 is a test for setting the established,to_client flow opts
576  */
577 static int DetectFlowTestParse08 (void)
578 {
579  DetectFlowData *fd = NULL;
580  fd = DetectFlowParse("established,to_client");
581  FAIL_IF_NULL(fd);
583  DetectFlowFree(fd);
584  PASS;
585 }
586 
587 /**
588  * \test DetectFlowTestParse09 is a test for setting the to_client,stateless flow opts (order of state,dir reversed)
589  */
590 static int DetectFlowTestParse09 (void)
591 {
592  DetectFlowData *fd = NULL;
593  fd = DetectFlowParse("to_client,stateless");
594  FAIL_IF_NULL(fd);
597  fd->match_cnt == 2);
598  DetectFlowFree(fd);
599  PASS;
600 }
601 
602 /**
603  * \test DetectFlowTestParse10 is a test for setting the from_server,stateless flow opts (order of state,dir reversed)
604  */
605 static int DetectFlowTestParse10 (void)
606 {
607  DetectFlowData *fd = NULL;
608  fd = DetectFlowParse("from_server,stateless");
609  FAIL_IF_NULL(fd);
612  fd->match_cnt == 2);
613  DetectFlowFree(fd);
614  PASS;
615 }
616 
617 /**
618  * \test DetectFlowTestParse11 is a test for setting the from_server,stateless flow opts with spaces all around
619  */
620 static int DetectFlowTestParse11 (void)
621 {
622  DetectFlowData *fd = NULL;
623  fd = DetectFlowParse(" from_server , stateless ");
624  FAIL_IF_NULL(fd);
627  fd->match_cnt == 2);
628  DetectFlowFree(fd);
629  PASS;
630 }
631 
632 /**
633  * \test DetectFlowTestParseNocase01 is a test to make sure that we return "something"
634  * when given valid flow opt
635  */
636 static int DetectFlowTestParseNocase01 (void)
637 {
638  DetectFlowData *fd = NULL;
639  fd = DetectFlowParse("ESTABLISHED");
640  FAIL_IF_NULL(fd);
641  DetectFlowFree(fd);
642  PASS;
643 }
644 
645 /**
646  * \test DetectFlowTestParseNocase02 is a test for setting the established flow opt
647  */
648 static int DetectFlowTestParseNocase02 (void)
649 {
650  DetectFlowData *fd = NULL;
651  fd = DetectFlowParse("ESTABLISHED");
652  FAIL_IF_NULL(fd);
654  fd->match_cnt == 1);
655  DetectFlowFree(fd);
656  PASS;
657 }
658 
659 /**
660  * \test DetectFlowTestParseNocase03 is a test for setting the stateless flow opt
661  */
662 static int DetectFlowTestParseNocase03 (void)
663 {
664  DetectFlowData *fd = NULL;
665  fd = DetectFlowParse("STATELESS");
666  FAIL_IF_NULL(fd);
668  PASS;
669 }
670 
671 /**
672  * \test DetectFlowTestParseNocase04 is a test for setting the to_client flow opt
673  */
674 static int DetectFlowTestParseNocase04 (void)
675 {
676  DetectFlowData *fd = NULL;
677  fd = DetectFlowParse("TO_CLIENT");
678  FAIL_IF_NULL(fd);
680  DetectFlowFree(fd);
681  PASS;
682 }
683 
684 /**
685  * \test DetectFlowTestParseNocase05 is a test for setting the to_server flow opt
686  */
687 static int DetectFlowTestParseNocase05 (void)
688 {
689  DetectFlowData *fd = NULL;
690  fd = DetectFlowParse("TO_SERVER");
691  FAIL_IF_NULL(fd);
693  DetectFlowFree(fd);
694  PASS;
695 }
696 
697 /**
698  * \test DetectFlowTestParseNocase06 is a test for setting the from_server flow opt
699  */
700 static int DetectFlowTestParseNocase06 (void)
701 {
702  DetectFlowData *fd = NULL;
703  fd = DetectFlowParse("FROM_SERVER");
704  FAIL_IF_NULL(fd);
706  DetectFlowFree(fd);
707  PASS;
708 }
709 
710 /**
711  * \test DetectFlowTestParseNocase07 is a test for setting the from_client flow opt
712  */
713 static int DetectFlowTestParseNocase07 (void)
714 {
715  DetectFlowData *fd = NULL;
716  fd = DetectFlowParse("FROM_CLIENT");
717  FAIL_IF_NULL(fd);
719  DetectFlowFree(fd);
720  PASS;
721 }
722 
723 /**
724  * \test DetectFlowTestParseNocase08 is a test for setting the established,to_client flow opts
725  */
726 static int DetectFlowTestParseNocase08 (void)
727 {
728  DetectFlowData *fd = NULL;
729  fd = DetectFlowParse("ESTABLISHED,TO_CLIENT");
730  FAIL_IF_NULL(fd);
733  fd->match_cnt == 2);
734  DetectFlowFree(fd);
735  PASS;
736 }
737 
738 /**
739  * \test DetectFlowTestParseNocase09 is a test for setting the to_client,stateless flow opts (order of state,dir reversed)
740  */
741 static int DetectFlowTestParseNocase09 (void)
742 {
743  DetectFlowData *fd = NULL;
744  fd = DetectFlowParse("TO_CLIENT,STATELESS");
745  FAIL_IF_NULL(fd);
748  fd->match_cnt == 2);
749  DetectFlowFree(fd);
750  PASS;
751 }
752 
753 /**
754  * \test DetectFlowTestParseNocase10 is a test for setting the from_server,stateless flow opts (order of state,dir reversed)
755  */
756 static int DetectFlowTestParseNocase10 (void)
757 {
758  DetectFlowData *fd = NULL;
759  fd = DetectFlowParse("FROM_SERVER,STATELESS");
760  FAIL_IF_NULL(fd);
763  fd->match_cnt == 2);
764  DetectFlowFree(fd);
765  PASS;
766 }
767 
768 /**
769  * \test DetectFlowTestParseNocase11 is a test for setting the from_server,stateless flow opts with spaces all around
770  */
771 static int DetectFlowTestParseNocase11 (void)
772 {
773  DetectFlowData *fd = NULL;
774  fd = DetectFlowParse(" FROM_SERVER , STATELESS ");
775  FAIL_IF_NULL(fd);
778  fd->match_cnt == 2);
779  DetectFlowFree(fd);
780  PASS;
781 }
782 
783 /**
784  * \test DetectFlowTestParse12 is a test for setting an invalid seperator :
785  */
786 static int DetectFlowTestParse12 (void)
787 {
788  DetectFlowData *fd = NULL;
789  fd = DetectFlowParse("from_server:stateless");
790  FAIL_IF_NOT_NULL(fd);
791  PASS;
792 }
793 
794 /**
795  * \test DetectFlowTestParse13 is a test for an invalid option
796  */
797 static int DetectFlowTestParse13 (void)
798 {
799  DetectFlowData *fd = NULL;
800  fd = DetectFlowParse("invalidoptiontest");
801  FAIL_IF_NOT_NULL(fd);
802  PASS;
803 }
804 
805 /**
806  * \test DetectFlowTestParse14 is a test for a empty option
807  */
808 static int DetectFlowTestParse14 (void)
809 {
810  DetectFlowData *fd = NULL;
811  fd = DetectFlowParse("");
812  FAIL_IF_NOT_NULL(fd);
813  PASS;
814 }
815 
816 /**
817  * \test DetectFlowTestParse15 is a test for an invalid combo of options established,stateless
818  */
819 static int DetectFlowTestParse15 (void)
820 {
821  DetectFlowData *fd = NULL;
822  fd = DetectFlowParse("established,stateless");
823  FAIL_IF_NOT_NULL(fd);
824  PASS;
825 }
826 
827 /**
828  * \test DetectFlowTestParse16 is a test for an invalid combo of options to_client,to_server
829  */
830 static int DetectFlowTestParse16 (void)
831 {
832  DetectFlowData *fd = NULL;
833  fd = DetectFlowParse("to_client,to_server");
834  FAIL_IF_NOT_NULL(fd);
835  PASS;
836 }
837 
838 /**
839  * \test DetectFlowTestParse16 is a test for an invalid combo of options to_client,from_server
840  * flowbit flags are the same
841  */
842 static int DetectFlowTestParse17 (void)
843 {
844  DetectFlowData *fd = NULL;
845  fd = DetectFlowParse("to_client,from_server");
846  FAIL_IF_NOT_NULL(fd);
847  PASS;
848 }
849 
850 /**
851  * \test DetectFlowTestParse18 is a test for setting the from_server,stateless,only_stream flow opts (order of state,dir reversed)
852  */
853 static int DetectFlowTestParse18 (void)
854 {
855  DetectFlowData *fd = NULL;
856  fd = DetectFlowParse("from_server,established,only_stream");
857  FAIL_IF_NULL(fd);
861  fd->match_cnt == 3);
862  DetectFlowFree(fd);
863  PASS;
864 }
865 
866 /**
867  * \test DetectFlowTestParseNocase18 is a test for setting the from_server,stateless,only_stream flow opts (order of state,dir reversed)
868  */
869 static int DetectFlowTestParseNocase18 (void)
870 {
871  DetectFlowData *fd = NULL;
872  fd = DetectFlowParse("FROM_SERVER,ESTABLISHED,ONLY_STREAM");
873  FAIL_IF_NULL(fd);
877  fd->match_cnt == 3);
878  DetectFlowFree(fd);
879  PASS;
880 }
881 
882 
883 /**
884  * \test DetectFlowTestParse19 is a test for one to many options passed to DetectFlowParse
885  */
886 static int DetectFlowTestParse19 (void)
887 {
888  DetectFlowData *fd = NULL;
889  fd = DetectFlowParse("from_server,established,only_stream,a");
890  FAIL_IF_NOT_NULL(fd);
891  PASS;
892 }
893 
894 /**
895  * \test DetectFlowTestParse20 is a test for setting from_server, established, no_stream
896  */
897 static int DetectFlowTestParse20 (void)
898 {
899  DetectFlowData *fd = NULL;
900  fd = DetectFlowParse("from_server,established,no_stream");
901  FAIL_IF_NULL(fd);
905  fd->match_cnt == 3);
906  DetectFlowFree(fd);
907  PASS;
908 }
909 
910 /**
911  * \test DetectFlowTestParse20 is a test for setting from_server, established, no_stream
912  */
913 static int DetectFlowTestParseNocase20 (void)
914 {
915  DetectFlowData *fd = NULL;
916  fd = DetectFlowParse("FROM_SERVER,ESTABLISHED,NO_STREAM");
917  FAIL_IF_NULL(fd);
921  fd->match_cnt == 3);
922  DetectFlowFree(fd);
923  PASS;
924 }
925 
926 /**
927  * \test DetectFlowTestParse21 is a test for an invalid opt between to valid opts
928  */
929 static int DetectFlowTestParse21 (void)
930 {
931  DetectFlowData *fd = NULL;
932  fd = DetectFlowParse("from_server,a,no_stream");
933  FAIL_IF_NOT_NULL(fd);
934  PASS;
935 }
936 
937 static int DetectFlowSigTest01(void)
938 {
939  ThreadVars th_v;
940  DecodeThreadVars dtv;
941  DetectEngineCtx *de_ctx = NULL;
942  DetectEngineThreadCtx *det_ctx = NULL;
943  uint8_t *buf = (uint8_t *)"supernovaduper";
944  uint16_t buflen = strlen((char *)buf);
945 
946  Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
947  FAIL_IF_NULL(p);
948 
949  const char *sig1 = "alert tcp any any -> any any (msg:\"dummy\"; "
950  "content:\"nova\"; flow:no_stream; sid:1;)";
951 
952  memset(&dtv, 0, sizeof(DecodeThreadVars));
953  memset(&th_v, 0, sizeof(th_v));
954 
955  de_ctx = DetectEngineCtxInit();
956  FAIL_IF_NULL(de_ctx);
957  de_ctx->flags |= DE_QUIET;
958 
959  de_ctx->sig_list = SigInit(de_ctx, sig1);
960  FAIL_IF_NULL(de_ctx->sig_list);
961 
962  SigGroupBuild(de_ctx);
963  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
964 
965  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
966  FAIL_IF(PacketAlertCheck(p, 1) != 1);
967 
968  if (det_ctx != NULL)
969  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
970 
971  if (de_ctx != NULL) {
972  SigGroupCleanup(de_ctx);
973  SigCleanSignatures(de_ctx);
974  DetectEngineCtxFree(de_ctx);
975  }
976 
977  if (p != NULL)
978  UTHFreePacket(p);
979 
980  PASS;
981 }
982 
983 /**
984  * \test Test parsing of the not_established keyword.
985  */
986 static int DetectFlowTestParseNotEstablished(void)
987 {
988  DetectFlowData *fd = NULL;
989  fd = DetectFlowParse("not_established");
990  FAIL_IF_NULL(fd);
992  DetectFlowFree(fd);
993  PASS;
994 }
995 
996 /**
997  * \test Test parsing of the "no_frag" flow argument.
998  */
999 static int DetectFlowTestParseNoFrag(void)
1000 {
1001  DetectFlowData *fd = NULL;
1002  fd = DetectFlowParse("no_frag");
1003  FAIL_IF_NULL(fd);
1005  DetectFlowFree(fd);
1006  PASS;
1007 }
1008 
1009 /**
1010  * \test Test parsing of the "only_frag" flow argument.
1011  */
1012 static int DetectFlowTestParseOnlyFrag(void)
1013 {
1014  DetectFlowData *fd = NULL;
1015  fd = DetectFlowParse("only_frag");
1016  FAIL_IF_NULL(fd);
1018  DetectFlowFree(fd);
1019  PASS;
1020 }
1021 
1022 /**
1023  * \test Test that parsing of only_frag and no_frag together fails.
1024  */
1025 static int DetectFlowTestParseNoFragOnlyFrag(void)
1026 {
1027  DetectFlowData *fd = NULL;
1028  fd = DetectFlowParse("no_frag,only_frag");
1029  FAIL_IF_NOT_NULL(fd);
1030  PASS;
1031 }
1032 
1033 /**
1034  * \test Test no_frag matching.
1035  */
1036 static int DetectFlowTestNoFragMatch(void)
1037 {
1038  uint32_t pflags = 0;
1039  DetectFlowData *fd = DetectFlowParse("no_frag");
1040  FAIL_IF_NULL(fd);
1042  FAIL_IF_NOT(fd->match_cnt == 1);
1043  FAIL_IF_NOT(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
1044  pflags |= PKT_REBUILT_FRAGMENT;
1045  FAIL_IF(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
1046  PASS;
1047 }
1048 
1049 /**
1050  * \test Test only_frag matching.
1051  */
1052 static int DetectFlowTestOnlyFragMatch(void)
1053 {
1054  uint32_t pflags = 0;
1055  DetectFlowData *fd = DetectFlowParse("only_frag");
1056  FAIL_IF_NULL(fd);
1058  FAIL_IF_NOT(fd->match_cnt == 1);
1059  FAIL_IF(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
1060  pflags |= PKT_REBUILT_FRAGMENT;
1061  FAIL_IF_NOT(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
1062  PASS;
1063 }
1064 
1065 #endif /* UNITTESTS */
1066 
1067 /**
1068  * \brief this function registers unit tests for DetectFlow
1069  */
1071 {
1072 #ifdef UNITTESTS
1073  UtRegisterTest("DetectFlowTestParse01", DetectFlowTestParse01);
1074  UtRegisterTest("DetectFlowTestParse02", DetectFlowTestParse02);
1075  UtRegisterTest("DetectFlowTestParse03", DetectFlowTestParse03);
1076  UtRegisterTest("DetectFlowTestParse04", DetectFlowTestParse04);
1077  UtRegisterTest("DetectFlowTestParse05", DetectFlowTestParse05);
1078  UtRegisterTest("DetectFlowTestParse06", DetectFlowTestParse06);
1079  UtRegisterTest("DetectFlowTestParse07", DetectFlowTestParse07);
1080  UtRegisterTest("DetectFlowTestParse08", DetectFlowTestParse08);
1081  UtRegisterTest("DetectFlowTestParse09", DetectFlowTestParse09);
1082  UtRegisterTest("DetectFlowTestParse10", DetectFlowTestParse10);
1083  UtRegisterTest("DetectFlowTestParse11", DetectFlowTestParse11);
1084  UtRegisterTest("DetectFlowTestParseNocase01", DetectFlowTestParseNocase01);
1085  UtRegisterTest("DetectFlowTestParseNocase02", DetectFlowTestParseNocase02);
1086  UtRegisterTest("DetectFlowTestParseNocase03", DetectFlowTestParseNocase03);
1087  UtRegisterTest("DetectFlowTestParseNocase04", DetectFlowTestParseNocase04);
1088  UtRegisterTest("DetectFlowTestParseNocase05", DetectFlowTestParseNocase05);
1089  UtRegisterTest("DetectFlowTestParseNocase06", DetectFlowTestParseNocase06);
1090  UtRegisterTest("DetectFlowTestParseNocase07", DetectFlowTestParseNocase07);
1091  UtRegisterTest("DetectFlowTestParseNocase08", DetectFlowTestParseNocase08);
1092  UtRegisterTest("DetectFlowTestParseNocase09", DetectFlowTestParseNocase09);
1093  UtRegisterTest("DetectFlowTestParseNocase10", DetectFlowTestParseNocase10);
1094  UtRegisterTest("DetectFlowTestParseNocase11", DetectFlowTestParseNocase11);
1095  UtRegisterTest("DetectFlowTestParse12", DetectFlowTestParse12);
1096  UtRegisterTest("DetectFlowTestParse13", DetectFlowTestParse13);
1097  UtRegisterTest("DetectFlowTestParse14", DetectFlowTestParse14);
1098  UtRegisterTest("DetectFlowTestParse15", DetectFlowTestParse15);
1099  UtRegisterTest("DetectFlowTestParse16", DetectFlowTestParse16);
1100  UtRegisterTest("DetectFlowTestParse17", DetectFlowTestParse17);
1101  UtRegisterTest("DetectFlowTestParse18", DetectFlowTestParse18);
1102  UtRegisterTest("DetectFlowTestParseNocase18", DetectFlowTestParseNocase18);
1103  UtRegisterTest("DetectFlowTestParse19", DetectFlowTestParse19);
1104  UtRegisterTest("DetectFlowTestParse20", DetectFlowTestParse20);
1105  UtRegisterTest("DetectFlowTestParseNocase20", DetectFlowTestParseNocase20);
1106  UtRegisterTest("DetectFlowTestParse21", DetectFlowTestParse21);
1107  UtRegisterTest("DetectFlowTestParseNotEstablished",
1108  DetectFlowTestParseNotEstablished);
1109  UtRegisterTest("DetectFlowTestParseNoFrag", DetectFlowTestParseNoFrag);
1110  UtRegisterTest("DetectFlowTestParseOnlyFrag",
1111  DetectFlowTestParseOnlyFrag);
1112  UtRegisterTest("DetectFlowTestParseNoFragOnlyFrag",
1113  DetectFlowTestParseNoFragOnlyFrag);
1114  UtRegisterTest("DetectFlowTestNoFragMatch", DetectFlowTestNoFragMatch);
1115  UtRegisterTest("DetectFlowTestOnlyFragMatch", DetectFlowTestOnlyFragMatch);
1116 
1117  UtRegisterTest("DetectFlowSigTest01", DetectFlowSigTest01);
1118 #endif /* UNITTESTS */
1119 }
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1448
SignatureInitData * init_data
Definition: detect.h:591
uint16_t flags
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1186
#define SCLogDebug(...)
Definition: util-debug.h:335
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1189
int PrefilterSetupPacketHeader(DetectEngineCtx *de_ctx, SigGroupHead *sgh, int sm_type, void(*Set)(PrefilterPacketHeaderValue *v, void *), _Bool(*Compare)(PrefilterPacketHeaderValue v, void *), void(*Match)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx))
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
#define BUG_ON(x)
uint32_t flags
Definition: detect.h:523
_Bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1188
#define FALSE
#define DETECT_ENGINE_THREAD_CTX_STREAM_CONTENT_MATCH
Definition: detect.h:280
#define PASS
Pass the test.
#define unlikely(expr)
Definition: util-optimize.h:35
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
Signature * sig_list
Definition: detect.h:767
#define DETECT_FLOW_FLAG_NOT_ESTABLISHED
Definition: detect-flow.h:30
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:224
uint8_t match_cnt
Definition: detect-flow.h:39
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:203
void SigCleanSignatures(DetectEngineCtx *de_ctx)
uint16_t flags
Definition: detect-flow.h:38
void DetectFlowFree(void *)
this function will free memory associated with DetectFlowData
Definition: detect-flow.c:421
Container for matching data for a signature group.
Definition: detect.h:1336
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:223
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
const char * name
Definition: detect.h:1200
#define DETECT_FLOW_FLAG_STATELESS
Definition: detect-flow.h:31
#define MAX_SUBSTRINGS
Signature container.
Definition: detect.h:522
void DetectFlowRegister(void)
Registration function for flow: keyword.
Definition: detect-flow.c:64
#define TRUE
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:313
void DetectFlowRegisterTests(void)
this function registers unit tests for DetectFlow
Definition: detect-flow.c:1070
struct SigMatch_ * next
Definition: detect.h:322
main detection engine ctx
Definition: detect.h:761
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
#define DETECT_FLOW_FLAG_ESTABLISHED
Definition: detect-flow.h:29
#define DE_QUIET
Definition: detect.h:292
#define DETECT_FLOW_FLAG_NO_FRAG
Definition: detect-flow.h:34
#define SIG_FLAG_TOCLIENT
Definition: detect.h:237
int DetectFlowMatch(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
This function is used to match flow flags set on a packet with those passed via flow: ...
Definition: detect-flow.c:136
uint8_t flags
Definition: detect.h:762
void(* Free)(void *)
Definition: detect.h:1191
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
#define SIG_FLAG_INIT_FLOW
Definition: detect.h:258
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Structure to hold thread specific data for all decode modules.
Definition: decode.h:632
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1669
void DetectSetupParseRegexes(const char *parse_str, pcre **parse_regex, pcre_extra **parse_regex_study)
#define SIG_FLAG_TOSERVER
Definition: detect.h:236
#define SCEnter(...)
Definition: util-debug.h:337
PrefilterRuleStore pmq
Definition: detect.h:1102
#define DETECT_FLOW_FLAG_ONLY_FRAG
Definition: detect-flow.h:35
uint8_t flowflags
Definition: decode.h:439
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.
#define PKT_REBUILT_FRAGMENT
Definition: decode.h:1120
#define FLOW_PKT_TOSERVER
Definition: flow.h:201
#define DETECT_FLOW_FLAG_ONLYSTREAM
Definition: detect-flow.h:32
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1170
int SigGroupCleanup(DetectEngineCtx *de_ctx)
#define DETECT_FLOW_FLAG_TOCLIENT
Definition: detect-flow.h:28
uint8_t type
Definition: detect.h:319
#define SCReturnInt(x)
Definition: util-debug.h:341
const char * desc
Definition: detect.h:1202
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:346
struct SigMatch_ ** smlists
Definition: detect.h:516
SigMatchCtx * ctx
Definition: detect.h:321
#define SCMalloc(a)
Definition: util-mem.h:222
#define SCFree(a)
Definition: util-mem.h:322
PoolThreadReserved res
#define SIG_FLAG_BOTH
uint32_t init_flags
Definition: detect.h:486
void SigMatchFree(SigMatch *sm)
free a SigMatch
Definition: detect-parse.c:247
const char * url
Definition: detect.h:1203
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself...
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
#define DOC_URL
Definition: suricata.h:86
int DetectFlowSetupImplicit(Signature *s, uint32_t flags)
Definition: detect-flow.c:319
#define PARSE_REGEX
Regex for parsing our flow options.
Definition: detect-flow.c:47
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:232
Per thread variable structure.
Definition: threadvars.h:57
#define DETECT_FLOW_FLAG_TOSERVER
Definition: detect-flow.h:27
#define FLOW_PKT_TOCLIENT
Definition: flow.h:202
uint32_t flags
Definition: decode.h:443
#define DOC_VERSION
Definition: suricata.h:91
#define DETECT_FLOW_FLAG_NOSTREAM
Definition: detect-flow.h:33
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
void(* RegisterTests)(void)
Definition: detect.h:1192
a single match condition for a signature
Definition: detect.h:318
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
DetectEngineCtx * DetectEngineCtxInit(void)