suricata
detect-tcp-flags.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 Breno Silva <breno.silva@gmail.com>
22  *
23  * Implements the flags keyword
24  */
25 
26 #include "suricata-common.h"
27 #include "suricata.h"
28 #include "decode.h"
29 
30 #include "detect.h"
31 #include "detect-parse.h"
34 
35 #include "flow-var.h"
36 #include "decode-events.h"
37 
38 #include "detect-tcp-flags.h"
39 #include "util-unittest.h"
40 
41 #include "util-debug.h"
42 
43 /**
44  * Regex (by Brian Rectanus)
45  * flags: [!+*](SAPRFU120)[,SAPRFU12]
46  */
47 #define PARSE_REGEX "^\\s*(?:([\\+\\*!]))?\\s*([SAPRFU120CE\\+\\*!]+)(?:\\s*,\\s*([SAPRFU12CE]+))?\\s*$"
48 
49 /**
50  * Flags args[0] *(3) +(2) !(1)
51  *
52  */
53 
54 #define MODIFIER_NOT 1
55 #define MODIFIER_PLUS 2
56 #define MODIFIER_ANY 3
57 
58 static DetectParseRegex parse_regex;
59 
60 static int DetectFlagsMatch (DetectEngineThreadCtx *, Packet *,
61  const Signature *, const SigMatchCtx *);
62 static int DetectFlagsSetup (DetectEngineCtx *, Signature *, const char *);
63 static void DetectFlagsFree(DetectEngineCtx *, void *);
64 
65 static bool PrefilterTcpFlagsIsPrefilterable(const Signature *s);
66 static int PrefilterSetupTcpFlags(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
67 #ifdef UNITTESTS
68 static void FlagsRegisterTests(void);
69 #endif
70 
71 /**
72  * \brief Registration function for flags: keyword
73  */
74 
76 {
77  sigmatch_table[DETECT_FLAGS].name = "tcp.flags";
79  sigmatch_table[DETECT_FLAGS].desc = "detect which flags are set in the TCP header";
80  sigmatch_table[DETECT_FLAGS].url = "/rules/header-keywords.html#tcp-flags";
81  sigmatch_table[DETECT_FLAGS].Match = DetectFlagsMatch;
82  sigmatch_table[DETECT_FLAGS].Setup = DetectFlagsSetup;
83  sigmatch_table[DETECT_FLAGS].Free = DetectFlagsFree;
84 #ifdef UNITTESTS
85  sigmatch_table[DETECT_FLAGS].RegisterTests = FlagsRegisterTests;
86 #endif
87  sigmatch_table[DETECT_FLAGS].SupportsPrefilter = PrefilterTcpFlagsIsPrefilterable;
88  sigmatch_table[DETECT_FLAGS].SetupPrefilter = PrefilterSetupTcpFlags;
89 
90  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
91 }
92 
93 static inline int FlagsMatch(const uint8_t pflags, const uint8_t modifier,
94  const uint8_t dflags, const uint8_t iflags)
95 {
96  if (!dflags && pflags) {
97  if(modifier == MODIFIER_NOT) {
98  SCReturnInt(1);
99  }
100 
101  SCReturnInt(0);
102  }
103 
104  const uint8_t flags = pflags & iflags;
105 
106  switch (modifier) {
107  case MODIFIER_ANY:
108  if ((flags & dflags) > 0) {
109  SCReturnInt(1);
110  }
111  SCReturnInt(0);
112 
113  case MODIFIER_PLUS:
114  if (((flags & dflags) == dflags)) {
115  SCReturnInt(1);
116  }
117  SCReturnInt(0);
118 
119  case MODIFIER_NOT:
120  if ((flags & dflags) != dflags) {
121  SCReturnInt(1);
122  }
123  SCReturnInt(0);
124 
125  default:
126  SCLogDebug("flags %"PRIu8" and de->flags %"PRIu8"", flags, dflags);
127  if (flags == dflags) {
128  SCReturnInt(1);
129  }
130  }
131 
132  SCReturnInt(0);
133 }
134 
135 /**
136  * \internal
137  * \brief This function is used to match flags on a packet with those passed via flags:
138  *
139  * \param t pointer to thread vars
140  * \param det_ctx pointer to the pattern matcher thread
141  * \param p pointer to the current packet
142  * \param s pointer to the Signature
143  * \param m pointer to the sigmatch
144  *
145  * \retval 0 no match
146  * \retval 1 match
147  */
148 static int DetectFlagsMatch (DetectEngineThreadCtx *det_ctx, Packet *p,
149  const Signature *s, const SigMatchCtx *ctx)
150 {
151  SCEnter();
152 
153  if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) {
154  SCReturnInt(0);
155  }
156 
157  const DetectFlagsData *de = (const DetectFlagsData *)ctx;
158  const uint8_t flags = p->tcph->th_flags;
159 
160  return FlagsMatch(flags, de->modifier, de->flags, de->ignored_flags);
161 }
162 
163 /**
164  * \internal
165  * \brief This function is used to parse flags options passed via flags: keyword
166  *
167  * \param rawstr Pointer to the user provided flags options
168  *
169  * \retval de pointer to DetectFlagsData on success
170  * \retval NULL on failure
171  */
172 static DetectFlagsData *DetectFlagsParse (const char *rawstr)
173 {
174  SCEnter();
175 
176  int ret = 0, found = 0, ignore = 0, res = 0;
177  size_t pcre2len;
178  char *ptr;
179 
180  char arg1[16] = "";
181  char arg2[16] = "";
182  char arg3[16] = "";
183 
184  ret = DetectParsePcreExec(&parse_regex, rawstr, 0, 0);
185  SCLogDebug("input '%s', pcre said %d", rawstr, ret);
186  if (ret < 3) {
187  SCLogError(SC_ERR_PCRE_MATCH, "pcre match failed");
188  SCReturnPtr(NULL, "DetectFlagsData");
189  }
190 
191  pcre2len = sizeof(arg1);
192  res = SC_Pcre2SubstringCopy(parse_regex.match, 1, (PCRE2_UCHAR8 *)arg1, &pcre2len);
193  if (res < 0) {
194  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_copy_bynumber failed");
195  SCReturnPtr(NULL, "DetectFlagsData");
196  }
197  if (ret >= 2) {
198  pcre2len = sizeof(arg2);
199  res = pcre2_substring_copy_bynumber(parse_regex.match, 2, (PCRE2_UCHAR8 *)arg2, &pcre2len);
200  if (res < 0) {
201  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_copy_bynumber failed");
202  SCReturnPtr(NULL, "DetectFlagsData");
203  }
204  }
205  if (ret >= 3) {
206  pcre2len = sizeof(arg3);
207  res = SC_Pcre2SubstringCopy(parse_regex.match, 3, (PCRE2_UCHAR8 *)arg3, &pcre2len);
208  if (res < 0) {
209  SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_copy_bynumber failed");
210  SCReturnPtr(NULL, "DetectFlagsData");
211  }
212  }
213  SCLogDebug("args '%s', '%s', '%s'", arg1, arg2, arg3);
214 
215  if (strlen(arg2) == 0) {
216  SCLogDebug("empty argument");
217  SCReturnPtr(NULL, "DetectFlagsData");
218  }
219 
221  if (unlikely(de == NULL))
222  goto error;
223  memset(de, 0, sizeof(DetectFlagsData));
224  de->ignored_flags = 0xff;
225 
226  /** First parse args1 */
227  ptr = arg1;
228  while (*ptr != '\0') {
229  switch (*ptr) {
230  case 'S':
231  case 's':
232  de->flags |= TH_SYN;
233  found++;
234  break;
235  case 'A':
236  case 'a':
237  de->flags |= TH_ACK;
238  found++;
239  break;
240  case 'F':
241  case 'f':
242  de->flags |= TH_FIN;
243  found++;
244  break;
245  case 'R':
246  case 'r':
247  de->flags |= TH_RST;
248  found++;
249  break;
250  case 'P':
251  case 'p':
252  de->flags |= TH_PUSH;
253  found++;
254  break;
255  case 'U':
256  case 'u':
257  de->flags |= TH_URG;
258  found++;
259  break;
260  case '1':
261  de->flags |= TH_CWR;
262  found++;
263  break;
264  case '2':
265  de->flags |= TH_ECN;
266  found++;
267  break;
268  case 'C':
269  case 'c':
270  de->flags |= TH_CWR;
271  found++;
272  break;
273  case 'E':
274  case 'e':
275  de->flags |= TH_ECN;
276  found++;
277  break;
278  case '0':
279  de->flags = 0;
280  found++;
281  break;
282 
283  case '!':
284  de->modifier = MODIFIER_NOT;
285  break;
286  case '+':
287  de->modifier = MODIFIER_PLUS;
288  break;
289  case '*':
290  de->modifier = MODIFIER_ANY;
291  break;
292  }
293  ptr++;
294  }
295 
296  /** Second parse first set of flags */
297  if (strlen(arg2) > 0) {
298  ptr = arg2;
299  while (*ptr != '\0') {
300  switch (*ptr) {
301  case 'S':
302  case 's':
303  de->flags |= TH_SYN;
304  found++;
305  break;
306  case 'A':
307  case 'a':
308  de->flags |= TH_ACK;
309  found++;
310  break;
311  case 'F':
312  case 'f':
313  de->flags |= TH_FIN;
314  found++;
315  break;
316  case 'R':
317  case 'r':
318  de->flags |= TH_RST;
319  found++;
320  break;
321  case 'P':
322  case 'p':
323  de->flags |= TH_PUSH;
324  found++;
325  break;
326  case 'U':
327  case 'u':
328  de->flags |= TH_URG;
329  found++;
330  break;
331  case '1':
332  case 'C':
333  case 'c':
334  de->flags |= TH_CWR;
335  found++;
336  break;
337  case '2':
338  case 'E':
339  case 'e':
340  de->flags |= TH_ECN;
341  found++;
342  break;
343  case '0':
344  de->flags = 0;
345  found++;
346  break;
347 
348  case '!':
349  if (de->modifier != 0) {
350  SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
351  " one modifier at a time");
352  goto error;
353  }
354  de->modifier = MODIFIER_NOT;
355  SCLogDebug("NOT modifier is set");
356  break;
357  case '+':
358  if (de->modifier != 0) {
359  SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
360  " one modifier at a time");
361  goto error;
362  }
363  de->modifier = MODIFIER_PLUS;
364  SCLogDebug("PLUS modifier is set");
365  break;
366  case '*':
367  if (de->modifier != 0) {
368  SCLogError(SC_ERR_FLAGS_MODIFIER, "\"flags\" supports only"
369  " one modifier at a time");
370  goto error;
371  }
372  de->modifier = MODIFIER_ANY;
373  SCLogDebug("ANY modifier is set");
374  break;
375  default:
376  break;
377  }
378  ptr++;
379  }
380 
381  if (found == 0)
382  goto error;
383  }
384 
385  /** Finally parse ignored flags */
386  if (strlen(arg3) > 0) {
387  ptr = arg3;
388 
389  while (*ptr != '\0') {
390  switch (*ptr) {
391  case 'S':
392  case 's':
393  de->ignored_flags &= ~TH_SYN;
394  ignore++;
395  break;
396  case 'A':
397  case 'a':
398  de->ignored_flags &= ~TH_ACK;
399  ignore++;
400  break;
401  case 'F':
402  case 'f':
403  de->ignored_flags &= ~TH_FIN;
404  ignore++;
405  break;
406  case 'R':
407  case 'r':
408  de->ignored_flags &= ~TH_RST;
409  ignore++;
410  break;
411  case 'P':
412  case 'p':
413  de->ignored_flags &= ~TH_PUSH;
414  ignore++;
415  break;
416  case 'U':
417  case 'u':
418  de->ignored_flags &= ~TH_URG;
419  ignore++;
420  break;
421  case '1':
422  de->ignored_flags &= ~TH_CWR;
423  ignore++;
424  break;
425  case '2':
426  de->ignored_flags &= ~TH_ECN;
427  ignore++;
428  break;
429  case 'C':
430  case 'c':
431  de->ignored_flags &= ~TH_CWR;
432  ignore++;
433  break;
434  case 'E':
435  case 'e':
436  de->ignored_flags &= ~TH_ECN;
437  ignore++;
438  break;
439  case '0':
440  break;
441  default:
442  break;
443  }
444  ptr++;
445  }
446 
447  if (ignore == 0) {
448  SCLogDebug("ignore == 0");
449  goto error;
450  }
451  }
452 
453  SCLogDebug("found %"PRId32" ignore %"PRId32"", found, ignore);
454  SCReturnPtr(de, "DetectFlagsData");
455 
456 error:
457  if (de) {
458  SCFree(de);
459  }
460  SCReturnPtr(NULL, "DetectFlagsData");
461 }
462 
463 /**
464  * \internal
465  * \brief this function is used to add the parsed flags into the current signature
466  *
467  * \param de_ctx pointer to the Detection Engine Context
468  * \param s pointer to the Current Signature
469  * \param m pointer to the Current SigMatch
470  * \param rawstr pointer to the user provided flags options
471  *
472  * \retval 0 on Success
473  * \retval -1 on Failure
474  */
475 static int DetectFlagsSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
476 {
477  DetectFlagsData *de = NULL;
478  SigMatch *sm = NULL;
479 
480  de = DetectFlagsParse(rawstr);
481  if (de == NULL)
482  goto error;
483 
484  sm = SigMatchAlloc();
485  if (sm == NULL)
486  goto error;
487 
488  sm->type = DETECT_FLAGS;
489  sm->ctx = (SigMatchCtx *)de;
490 
493 
494  return 0;
495 
496 error:
497  if (de) SCFree(de);
498  if (sm) SCFree(sm);
499  return -1;
500 }
501 
502 /**
503  * \internal
504  * \brief this function will free memory associated with DetectFlagsData
505  *
506  * \param de pointer to DetectFlagsData
507  */
508 static void DetectFlagsFree(DetectEngineCtx *de_ctx, void *de_ptr)
509 {
510  DetectFlagsData *de = (DetectFlagsData *)de_ptr;
511  if(de) SCFree(de);
512 }
513 
515 {
516  const SigMatch *sm;
517  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
518  switch (sm->type) {
519  case DETECT_FLAGS:
520  {
521  const DetectFlagsData *fl = (const DetectFlagsData *)sm->ctx;
522 
523  if (!(fl->modifier == MODIFIER_NOT) && (fl->flags & TH_SYN)) {
524  return 1;
525  }
526  break;
527  }
528  }
529  }
530  return 0;
531 }
532 
534 {
535  const SigMatch *sm;
536  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
537  switch (sm->type) {
538  case DETECT_FLAGS:
539  {
540  const DetectFlagsData *fl = (const DetectFlagsData *)sm->ctx;
541 
542  if (!(fl->modifier == MODIFIER_NOT) && (fl->flags == TH_SYN)) {
543  return 1;
544  }
545  break;
546  }
547  }
548  }
549  return 0;
550 }
551 
552 static void
553 PrefilterPacketFlagsMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
554 {
555  if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) {
556  SCReturn;
557  }
558 
559  const PrefilterPacketHeaderCtx *ctx = pectx;
560  if (!PrefilterPacketHeaderExtraMatch(ctx, p))
561  return;
562 
563  const uint8_t flags = p->tcph->th_flags;
564  if (FlagsMatch(flags, ctx->v1.u8[0], ctx->v1.u8[1], ctx->v1.u8[2]))
565  {
566  SCLogDebug("packet matches TCP flags %02x", ctx->v1.u8[1]);
567  PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
568  }
569 }
570 
571 static void
572 PrefilterPacketFlagsSet(PrefilterPacketHeaderValue *v, void *smctx)
573 {
574  const DetectFlagsData *a = smctx;
575  v->u8[0] = a->modifier;
576  v->u8[1] = a->flags;
577  v->u8[2] = a->ignored_flags;
578  SCLogDebug("v->u8[0] = %02x", v->u8[0]);
579 }
580 
581 static bool
582 PrefilterPacketFlagsCompare(PrefilterPacketHeaderValue v, void *smctx)
583 {
584  const DetectFlagsData *a = smctx;
585  if (v.u8[0] == a->modifier &&
586  v.u8[1] == a->flags &&
587  v.u8[2] == a->ignored_flags)
588  return true;
589  return false;
590 }
591 
592 static int PrefilterSetupTcpFlags(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
593 {
595  PrefilterPacketFlagsSet,
596  PrefilterPacketFlagsCompare,
597  PrefilterPacketFlagsMatch);
598 
599 }
600 
601 static bool PrefilterTcpFlagsIsPrefilterable(const Signature *s)
602 {
603  const SigMatch *sm;
604  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
605  switch (sm->type) {
606  case DETECT_FLAGS:
607  return true;
608  }
609  }
610  return false;
611 }
612 
613 /*
614  * ONLY TESTS BELOW THIS COMMENT
615  */
616 
617 #ifdef UNITTESTS
618 /**
619  * \test FlagsTestParse01 is a test for a valid flags value
620  *
621  * \retval 1 on succces
622  * \retval 0 on failure
623  */
624 static int FlagsTestParse01 (void)
625 {
626  DetectFlagsData *de = DetectFlagsParse("S");
627  FAIL_IF_NULL(de);
628  FAIL_IF_NOT(de->flags == TH_SYN);
629  DetectFlagsFree(NULL, de);
630  PASS;
631 }
632 
633 /**
634  * \test FlagsTestParse02 is a test for an invalid flags value
635  *
636  * \retval 1 on succces
637  * \retval 0 on failure
638  */
639 static int FlagsTestParse02 (void)
640 {
641  DetectFlagsData *de = NULL;
642  de = DetectFlagsParse("G");
643  if (de) {
644  DetectFlagsFree(NULL, de);
645  return 0;
646  }
647 
648  return 1;
649 }
650 
651 /**
652  * \test FlagsTestParse03 test if ACK and PUSH are set. Must return success
653  *
654  * \retval 1 on success
655  * \retval 0 on failure
656  */
657 static int FlagsTestParse03 (void)
658 {
659  Packet *p = PacketGetFromAlloc();
660  if (unlikely(p == NULL))
661  return 0;
662  ThreadVars tv;
663  int ret = 0;
664  DetectFlagsData *de = NULL;
665  SigMatch *sm = NULL;
666  IPV4Hdr ipv4h;
667  TCPHdr tcph;
668 
669  memset(&tv, 0, sizeof(ThreadVars));
670  memset(&ipv4h, 0, sizeof(IPV4Hdr));
671  memset(&tcph, 0, sizeof(TCPHdr));
672 
673  p->ip4h = &ipv4h;
674  p->tcph = &tcph;
675  p->tcph->th_flags = TH_ACK|TH_PUSH|TH_SYN|TH_RST;
676 
677  de = DetectFlagsParse("AP+");
678 
679  if (de == NULL || (de->flags != (TH_ACK|TH_PUSH)) )
680  goto error;
681 
682  sm = SigMatchAlloc();
683  if (sm == NULL)
684  goto error;
685 
686  sm->type = DETECT_FLAGS;
687  sm->ctx = (SigMatchCtx *)de;
688 
689  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
690 
691  if(ret) {
692  if (de) SCFree(de);
693  if (sm) SCFree(sm);
694  SCFree(p);
695  return 1;
696  }
697 
698 error:
699  if (de) SCFree(de);
700  if (sm) SCFree(sm);
701  SCFree(p);
702  return 0;
703 }
704 
705 /**
706  * \test FlagsTestParse04 check if ACK bit is set. Must fails.
707  *
708  * \retval 1 on succces
709  * \retval 0 on failure
710  */
711 static int FlagsTestParse04 (void)
712 {
713  Packet *p = PacketGetFromAlloc();
714  if (unlikely(p == NULL))
715  return 0;
716  ThreadVars tv;
717  int ret = 0;
718  DetectFlagsData *de = NULL;
719  SigMatch *sm = NULL;
720  IPV4Hdr ipv4h;
721  TCPHdr tcph;
722 
723  memset(&tv, 0, sizeof(ThreadVars));
724  memset(&ipv4h, 0, sizeof(IPV4Hdr));
725  memset(&tcph, 0, sizeof(TCPHdr));
726 
727  p->ip4h = &ipv4h;
728  p->tcph = &tcph;
729  p->tcph->th_flags = TH_SYN;
730 
731  de = DetectFlagsParse("A");
732 
733  if (de == NULL || de->flags != TH_ACK)
734  goto error;
735 
736  sm = SigMatchAlloc();
737  if (sm == NULL)
738  goto error;
739 
740  sm->type = DETECT_FLAGS;
741  sm->ctx = (SigMatchCtx *)de;
742 
743  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
744 
745  if(ret) {
746  if (de) SCFree(de);
747  if (sm) SCFree(sm);
748  SCFree(p);
749  return 0;
750  }
751 
752  /* Error expected. */
753 error:
754  if (de) SCFree(de);
755  if (sm) SCFree(sm);
756  SCFree(p);
757  return 1;
758 }
759 
760 /**
761  * \test FlagsTestParse05 test if ACK+PUSH and more flags are set. Ignore SYN and RST bits.
762  * Must fails.
763  * \retval 1 on success
764  * \retval 0 on failure
765  */
766 static int FlagsTestParse05 (void)
767 {
768  Packet *p = PacketGetFromAlloc();
769  if (unlikely(p == NULL))
770  return 0;
771  ThreadVars tv;
772  int ret = 0;
773  DetectFlagsData *de = NULL;
774  SigMatch *sm = NULL;
775  IPV4Hdr ipv4h;
776  TCPHdr tcph;
777 
778  memset(&tv, 0, sizeof(ThreadVars));
779  memset(&ipv4h, 0, sizeof(IPV4Hdr));
780  memset(&tcph, 0, sizeof(TCPHdr));
781 
782  p->ip4h = &ipv4h;
783  p->tcph = &tcph;
784  p->tcph->th_flags = TH_ACK|TH_PUSH|TH_SYN|TH_RST;
785 
786  de = DetectFlagsParse("+AP,SR");
787 
788  if (de == NULL || (de->modifier != MODIFIER_PLUS) || (de->flags != (TH_ACK|TH_PUSH)) || (de->ignored_flags != (TH_SYN|TH_RST)))
789  goto error;
790 
791  sm = SigMatchAlloc();
792  if (sm == NULL)
793  goto error;
794 
795  sm->type = DETECT_FLAGS;
796  sm->ctx = (SigMatchCtx *)de;
797 
798  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
799 
800  if(ret) {
801  if (de) SCFree(de);
802  if (sm) SCFree(sm);
803  SCFree(p);
804  return 0;
805  }
806 
807  /* Error expected. */
808 error:
809  if (de) SCFree(de);
810  if (sm) SCFree(sm);
811  SCFree(p);
812  return 1;
813 }
814 
815 /**
816  * \test FlagsTestParse06 test if ACK+PUSH and more flags are set. Ignore URG and RST bits.
817  * Must return success.
818  * \retval 1 on success
819  * \retval 0 on failure
820  */
821 static int FlagsTestParse06 (void)
822 {
823  Packet *p = PacketGetFromAlloc();
824  if (unlikely(p == NULL))
825  return 0;
826  ThreadVars tv;
827  int ret = 0;
828  DetectFlagsData *de = NULL;
829  SigMatch *sm = NULL;
830  IPV4Hdr ipv4h;
831  TCPHdr tcph;
832 
833  memset(&tv, 0, sizeof(ThreadVars));
834  memset(&ipv4h, 0, sizeof(IPV4Hdr));
835  memset(&tcph, 0, sizeof(TCPHdr));
836 
837  p->ip4h = &ipv4h;
838  p->tcph = &tcph;
839  p->tcph->th_flags = TH_ACK|TH_PUSH|TH_SYN|TH_RST;
840 
841  de = DetectFlagsParse("+AP,UR");
842 
843  if (de == NULL || (de->modifier != MODIFIER_PLUS) || (de->flags != (TH_ACK|TH_PUSH)) || ((0xff - de->ignored_flags) != (TH_URG|TH_RST)))
844  goto error;
845 
846  sm = SigMatchAlloc();
847  if (sm == NULL)
848  goto error;
849 
850  sm->type = DETECT_FLAGS;
851  sm->ctx = (SigMatchCtx *)de;
852 
853  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
854 
855  if(ret) {
856  if (de) SCFree(de);
857  if (sm) SCFree(sm);
858  SCFree(p);
859  return 1;
860  }
861 
862 error:
863  if (de) SCFree(de);
864  if (sm) SCFree(sm);
865  SCFree(p);
866  return 0;
867 }
868 
869 /**
870  * \test FlagsTestParse07 test if SYN or RST are set. Must fails.
871  *
872  * \retval 1 on success
873  * \retval 0 on failure
874  */
875 static int FlagsTestParse07 (void)
876 {
877  Packet *p = PacketGetFromAlloc();
878  if (unlikely(p == NULL))
879  return 0;
880  ThreadVars tv;
881  int ret = 0;
882  DetectFlagsData *de = NULL;
883  SigMatch *sm = NULL;
884  IPV4Hdr ipv4h;
885  TCPHdr tcph;
886 
887  memset(&tv, 0, sizeof(ThreadVars));
888  memset(&ipv4h, 0, sizeof(IPV4Hdr));
889  memset(&tcph, 0, sizeof(TCPHdr));
890 
891  p->ip4h = &ipv4h;
892  p->tcph = &tcph;
893  p->tcph->th_flags = TH_SYN|TH_RST;
894 
895  de = DetectFlagsParse("*AP");
896 
897  if (de == NULL || (de->modifier != MODIFIER_ANY) || (de->flags != (TH_ACK|TH_PUSH)))
898  goto error;
899 
900  sm = SigMatchAlloc();
901  if (sm == NULL)
902  goto error;
903 
904  sm->type = DETECT_FLAGS;
905  sm->ctx = (SigMatchCtx *)de;
906 
907  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
908 
909  if(ret) {
910  if (de) SCFree(de);
911  if (sm) SCFree(sm);
912  SCFree(p);
913  return 0;
914  }
915 
916  /* Error expected. */
917 error:
918  if (de) SCFree(de);
919  if (sm) SCFree(sm);
920  SCFree(p);
921  return 1;
922 }
923 
924 /**
925  * \test FlagsTestParse08 test if SYN or RST are set. Must return success.
926  *
927  * \retval 1 on success
928  * \retval 0 on failure
929  */
930 static int FlagsTestParse08 (void)
931 {
932  Packet *p = PacketGetFromAlloc();
933  if (unlikely(p == NULL))
934  return 0;
935  ThreadVars tv;
936  int ret = 0;
937  DetectFlagsData *de = NULL;
938  SigMatch *sm = NULL;
939  IPV4Hdr ipv4h;
940  TCPHdr tcph;
941 
942  memset(&tv, 0, sizeof(ThreadVars));
943  memset(&ipv4h, 0, sizeof(IPV4Hdr));
944  memset(&tcph, 0, sizeof(TCPHdr));
945 
946  p->ip4h = &ipv4h;
947  p->tcph = &tcph;
948  p->tcph->th_flags = TH_SYN|TH_RST;
949 
950  de = DetectFlagsParse("*SA");
951 
952  if (de == NULL || (de->modifier != MODIFIER_ANY) || (de->flags != (TH_ACK|TH_SYN)))
953  goto error;
954 
955  sm = SigMatchAlloc();
956  if (sm == NULL)
957  goto error;
958 
959  sm->type = DETECT_FLAGS;
960  sm->ctx = (SigMatchCtx *)de;
961 
962  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
963 
964  if(ret) {
965  if (de) SCFree(de);
966  if (sm) SCFree(sm);
967  SCFree(p);
968  return 1;
969  }
970 
971 error:
972  if (de) SCFree(de);
973  if (sm) SCFree(sm);
974  SCFree(p);
975  return 0;
976 }
977 
978 /**
979  * \test FlagsTestParse09 test if SYN and RST are not set. Must fails.
980  *
981  * \retval 1 on success
982  * \retval 0 on failure
983  */
984 static int FlagsTestParse09 (void)
985 {
986  Packet *p = PacketGetFromAlloc();
987  if (unlikely(p == NULL))
988  return 0;
989  ThreadVars tv;
990  int ret = 0;
991  DetectFlagsData *de = NULL;
992  SigMatch *sm = NULL;
993  IPV4Hdr ipv4h;
994  TCPHdr tcph;
995 
996  memset(&tv, 0, sizeof(ThreadVars));
997  memset(&ipv4h, 0, sizeof(IPV4Hdr));
998  memset(&tcph, 0, sizeof(TCPHdr));
999 
1000  p->ip4h = &ipv4h;
1001  p->tcph = &tcph;
1002  p->tcph->th_flags = TH_SYN|TH_RST;
1003 
1004  de = DetectFlagsParse("!PA");
1005 
1006  if (de == NULL || (de->modifier != MODIFIER_NOT) || (de->flags != (TH_ACK|TH_PUSH)))
1007  goto error;
1008 
1009  sm = SigMatchAlloc();
1010  if (sm == NULL)
1011  goto error;
1012 
1013  sm->type = DETECT_FLAGS;
1014  sm->ctx = (SigMatchCtx *)de;
1015 
1016  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1017 
1018  if(ret) {
1019  if (de) SCFree(de);
1020  if (sm) SCFree(sm);
1021  SCFree(p);
1022  return 1;
1023  }
1024 
1025 error:
1026  if (de) SCFree(de);
1027  if (sm) SCFree(sm);
1028  SCFree(p);
1029  return 0;
1030 }
1031 
1032 /**
1033  * \test FlagsTestParse10 test if ACK and PUSH are not set. Must return success.
1034  *
1035  * \retval 1 on success
1036  * \retval 0 on failure
1037  */
1038 static int FlagsTestParse10 (void)
1039 {
1040  Packet *p = PacketGetFromAlloc();
1041  if (unlikely(p == NULL))
1042  return 0;
1043  ThreadVars tv;
1044  int ret = 0;
1045  DetectFlagsData *de = NULL;
1046  SigMatch *sm = NULL;
1047  IPV4Hdr ipv4h;
1048  TCPHdr tcph;
1049 
1050  memset(&tv, 0, sizeof(ThreadVars));
1051  memset(&ipv4h, 0, sizeof(IPV4Hdr));
1052  memset(&tcph, 0, sizeof(TCPHdr));
1053 
1054  p->ip4h = &ipv4h;
1055  p->tcph = &tcph;
1056  p->tcph->th_flags = TH_SYN|TH_RST;
1057 
1058  de = DetectFlagsParse("!AP");
1059 
1060  if (de == NULL || (de->modifier != MODIFIER_NOT) || (de->flags != (TH_ACK|TH_PUSH)))
1061  goto error;
1062 
1063  sm = SigMatchAlloc();
1064  if (sm == NULL)
1065  goto error;
1066 
1067  sm->type = DETECT_FLAGS;
1068  sm->ctx = (SigMatchCtx *)de;
1069 
1070  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1071 
1072  if(ret) {
1073  if (de) SCFree(de);
1074  if (sm) SCFree(sm);
1075  SCFree(p);
1076  return 1;
1077  }
1078 
1079 error:
1080  if (de) SCFree(de);
1081  if (sm) SCFree(sm);
1082  SCFree(p);
1083  return 0;
1084 }
1085 
1086 /**
1087  * \test FlagsTestParse11 test if ACK or PUSH are set. Ignore SYN and RST. Must fails.
1088  *
1089  * \retval 1 on success
1090  * \retval 0 on failure
1091  */
1092 static int FlagsTestParse11 (void)
1093 {
1094  Packet *p = PacketGetFromAlloc();
1095  if (unlikely(p == NULL))
1096  return 0;
1097  ThreadVars tv;
1098  int ret = 0;
1099  DetectFlagsData *de = NULL;
1100  SigMatch *sm = NULL;
1101  IPV4Hdr ipv4h;
1102  TCPHdr tcph;
1103 
1104  memset(&tv, 0, sizeof(ThreadVars));
1105  memset(&ipv4h, 0, sizeof(IPV4Hdr));
1106  memset(&tcph, 0, sizeof(TCPHdr));
1107 
1108  p->ip4h = &ipv4h;
1109  p->tcph = &tcph;
1110  p->tcph->th_flags = TH_SYN|TH_RST|TH_URG;
1111 
1112  de = DetectFlagsParse("*AP,SR");
1113 
1114  if (de == NULL || (de->modifier != MODIFIER_ANY) || (de->flags != (TH_ACK|TH_PUSH)) || ((0xff - de->ignored_flags) != (TH_SYN|TH_RST)))
1115  goto error;
1116 
1117  sm = SigMatchAlloc();
1118  if (sm == NULL)
1119  goto error;
1120 
1121  sm->type = DETECT_FLAGS;
1122  sm->ctx = (SigMatchCtx *)de;
1123 
1124  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1125 
1126  if(ret) {
1127  if (de) SCFree(de);
1128  if (sm) SCFree(sm);
1129  SCFree(p);
1130  return 0;
1131  }
1132 
1133  /* Expected. */
1134 error:
1135  if (de) SCFree(de);
1136  if (sm) SCFree(sm);
1137  SCFree(p);
1138  return 1;
1139 }
1140 
1141 /**
1142  * \test FlagsTestParse12 check if no flags are set. Must fails.
1143  *
1144  * \retval 1 on succces
1145  * \retval 0 on failure
1146  */
1147 static int FlagsTestParse12 (void)
1148 {
1149  Packet *p = PacketGetFromAlloc();
1150  if (unlikely(p == NULL))
1151  return 0;
1152  ThreadVars tv;
1153  int ret = 0;
1154  DetectFlagsData *de = NULL;
1155  SigMatch *sm = NULL;
1156  IPV4Hdr ipv4h;
1157  TCPHdr tcph;
1158 
1159  memset(&tv, 0, sizeof(ThreadVars));
1160  memset(&ipv4h, 0, sizeof(IPV4Hdr));
1161  memset(&tcph, 0, sizeof(TCPHdr));
1162 
1163  p->ip4h = &ipv4h;
1164  p->tcph = &tcph;
1165  p->tcph->th_flags = TH_SYN;
1166 
1167  de = DetectFlagsParse("0");
1168 
1169  if (de == NULL || de->flags != 0) {
1170  printf("de setup: ");
1171  goto error;
1172  }
1173 
1174  sm = SigMatchAlloc();
1175  if (sm == NULL)
1176  goto error;
1177 
1178  sm->type = DETECT_FLAGS;
1179  sm->ctx = (SigMatchCtx *)de;
1180 
1181  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1182 
1183  if(ret) {
1184  if (de) SCFree(de);
1185  if (sm) SCFree(sm);
1186  SCFree(p);
1187  return 0;
1188  }
1189 
1190  /* Expected. */
1191 error:
1192  if (de) SCFree(de);
1193  if (sm) SCFree(sm);
1194  SCFree(p);
1195  return 1;
1196 }
1197 
1198 /**
1199  * \test test for a valid flags value
1200  *
1201  * \retval 1 on succces
1202  * \retval 0 on failure
1203  */
1204 static int FlagsTestParse13 (void)
1205 {
1206  DetectFlagsData *de = NULL;
1207  de = DetectFlagsParse("+S*");
1208  if (de != NULL) {
1209  DetectFlagsFree(NULL, de);
1210  return 0;
1211  }
1212 
1213  return 1;
1214 }
1215 
1216 /**
1217  * \test Parse 'C' and 'E' flags.
1218  *
1219  * \retval 1 on success.
1220  * \retval 0 on failure.
1221  */
1222 static int FlagsTestParse14(void)
1223 {
1224  DetectFlagsData *de = DetectFlagsParse("CE");
1225  if (de != NULL && (de->flags == (TH_CWR | TH_ECN)) ) {
1226  DetectFlagsFree(NULL, de);
1227  return 1;
1228  }
1229 
1230  return 0;
1231 }
1232 
1233 static int FlagsTestParse15(void)
1234 {
1235  Packet *p = PacketGetFromAlloc();
1236  if (unlikely(p == NULL))
1237  return 0;
1238  ThreadVars tv;
1239  int ret = 0;
1240  DetectFlagsData *de = NULL;
1241  SigMatch *sm = NULL;
1242  IPV4Hdr ipv4h;
1243  TCPHdr tcph;
1244 
1245  memset(&tv, 0, sizeof(ThreadVars));
1246  memset(&ipv4h, 0, sizeof(IPV4Hdr));
1247  memset(&tcph, 0, sizeof(TCPHdr));
1248 
1249  p->ip4h = &ipv4h;
1250  p->tcph = &tcph;
1251  p->tcph->th_flags = TH_ECN | TH_CWR | TH_SYN | TH_RST;
1252 
1253  de = DetectFlagsParse("EC+");
1254 
1255  if (de == NULL || (de->flags != (TH_ECN | TH_CWR)) )
1256  goto error;
1257 
1258  sm = SigMatchAlloc();
1259  if (sm == NULL)
1260  goto error;
1261 
1262  sm->type = DETECT_FLAGS;
1263  sm->ctx = (SigMatchCtx *)de;
1264 
1265  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1266 
1267  if (ret) {
1268  if (de)
1269  SCFree(de);
1270  if (sm)
1271  SCFree(sm);
1272  SCFree(p);
1273  return 1;
1274  }
1275 
1276 error:
1277  if (de)
1278  SCFree(de);
1279  if (sm)
1280  SCFree(sm);
1281  SCFree(p);
1282  return 0;
1283 }
1284 
1285 static int FlagsTestParse16(void)
1286 {
1287  Packet *p = PacketGetFromAlloc();
1288  if (unlikely(p == NULL))
1289  return 0;
1290  ThreadVars tv;
1291  int ret = 0;
1292  DetectFlagsData *de = NULL;
1293  SigMatch *sm = NULL;
1294  IPV4Hdr ipv4h;
1295  TCPHdr tcph;
1296 
1297  memset(&tv, 0, sizeof(ThreadVars));
1298  memset(&ipv4h, 0, sizeof(IPV4Hdr));
1299  memset(&tcph, 0, sizeof(TCPHdr));
1300 
1301  p->ip4h = &ipv4h;
1302  p->tcph = &tcph;
1303  p->tcph->th_flags = TH_ECN | TH_SYN | TH_RST;
1304 
1305  de = DetectFlagsParse("EC*");
1306 
1307  if (de == NULL || (de->flags != (TH_ECN | TH_CWR)) )
1308  goto error;
1309 
1310  sm = SigMatchAlloc();
1311  if (sm == NULL)
1312  goto error;
1313 
1314  sm->type = DETECT_FLAGS;
1315  sm->ctx = (SigMatchCtx *)de;
1316 
1317  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1318 
1319  if (ret) {
1320  if (de)
1321  SCFree(de);
1322  if (sm)
1323  SCFree(sm);
1324  SCFree(p);
1325  return 1;
1326  }
1327 
1328 error:
1329  if (de)
1330  SCFree(de);
1331  if (sm)
1332  SCFree(sm);
1333  SCFree(p);
1334  return 0;
1335 }
1336 
1337 /**
1338  * \test Negative test.
1339  */
1340 static int FlagsTestParse17(void)
1341 {
1342  Packet *p = PacketGetFromAlloc();
1343  if (unlikely(p == NULL))
1344  return 0;
1345  ThreadVars tv;
1346  int ret = 0;
1347  DetectFlagsData *de = NULL;
1348  SigMatch *sm = NULL;
1349  IPV4Hdr ipv4h;
1350  TCPHdr tcph;
1351 
1352  memset(&tv, 0, sizeof(ThreadVars));
1353  memset(&ipv4h, 0, sizeof(IPV4Hdr));
1354  memset(&tcph, 0, sizeof(TCPHdr));
1355 
1356  p->ip4h = &ipv4h;
1357  p->tcph = &tcph;
1358  p->tcph->th_flags = TH_ECN | TH_SYN | TH_RST;
1359 
1360  de = DetectFlagsParse("EC+");
1361 
1362  if (de == NULL || (de->flags != (TH_ECN | TH_CWR)) )
1363  goto error;
1364 
1365  sm = SigMatchAlloc();
1366  if (sm == NULL)
1367  goto error;
1368 
1369  sm->type = DETECT_FLAGS;
1370  sm->ctx = (SigMatchCtx *)de;
1371 
1372  ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1373 
1374  if (ret == 0) {
1375  if (de)
1376  SCFree(de);
1377  if (sm)
1378  SCFree(sm);
1379  SCFree(p);
1380  return 1;
1381  }
1382 
1383 error:
1384  if (de)
1385  SCFree(de);
1386  if (sm)
1387  SCFree(sm);
1388  SCFree(p);
1389  return 0;
1390 }
1391 
1392 /**
1393  * \brief this function registers unit tests for Flags
1394  */
1395 static void FlagsRegisterTests(void)
1396 {
1397  UtRegisterTest("FlagsTestParse01", FlagsTestParse01);
1398  UtRegisterTest("FlagsTestParse02", FlagsTestParse02);
1399  UtRegisterTest("FlagsTestParse03", FlagsTestParse03);
1400  UtRegisterTest("FlagsTestParse04", FlagsTestParse04);
1401  UtRegisterTest("FlagsTestParse05", FlagsTestParse05);
1402  UtRegisterTest("FlagsTestParse06", FlagsTestParse06);
1403  UtRegisterTest("FlagsTestParse07", FlagsTestParse07);
1404  UtRegisterTest("FlagsTestParse08", FlagsTestParse08);
1405  UtRegisterTest("FlagsTestParse09", FlagsTestParse09);
1406  UtRegisterTest("FlagsTestParse10", FlagsTestParse10);
1407  UtRegisterTest("FlagsTestParse11", FlagsTestParse11);
1408  UtRegisterTest("FlagsTestParse12", FlagsTestParse12);
1409  UtRegisterTest("FlagsTestParse13", FlagsTestParse13);
1410  UtRegisterTest("FlagsTestParse14", FlagsTestParse14);
1411  UtRegisterTest("FlagsTestParse15", FlagsTestParse15);
1412  UtRegisterTest("FlagsTestParse16", FlagsTestParse16);
1413  UtRegisterTest("FlagsTestParse17", FlagsTestParse17);
1414 }
1415 #endif /* UNITTESTS */
detect-tcp-flags.h
DetectParseRegex::match
pcre2_match_data * match
Definition: detect-parse.h:45
SigTableElmt_::url
const char * url
Definition: detect.h:1270
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
DetectFlagsSignatureNeedsSynOnlyPackets
int DetectFlagsSignatureNeedsSynOnlyPackets(const Signature *s)
Definition: detect-tcp-flags.c:533
SigTableElmt_::desc
const char * desc
Definition: detect.h:1269
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, const char *str, int start_offset, int options)
Definition: detect-parse.c:2474
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1257
DetectParseRegex
Definition: detect-parse.h:42
SigTableElmt_::name
const char * name
Definition: detect.h:1267
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1224
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1425
DetectFlagsData_::modifier
uint8_t modifier
Definition: detect-tcp-flags.h:43
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectFlagsData_::flags
uint8_t flags
Definition: detect-tcp-flags.h:42
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
PARSE_REGEX
#define PARSE_REGEX
Definition: detect-tcp-flags.c:47
MODIFIER_NOT
#define MODIFIER_NOT
Definition: detect-tcp-flags.c:54
TH_RST
#define TH_RST
Definition: decode-tcp.h:36
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1167
TH_FIN
#define TH_FIN
Definition: decode-tcp.h:34
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:811
DetectFlagsSignatureNeedsSynPackets
int DetectFlagsSignatureNeedsSynPackets(const Signature *s)
Definition: detect-tcp-flags.c:514
PrefilterPacketHeaderCtx_::sigs_array
SigIntId * sigs_array
Definition: detect-engine-prefilter-common.h:41
PrefilterPacketHeaderValue::u8
uint8_t u8[16]
Definition: detect-engine-prefilter-common.h:22
PrefilterPacketHeaderCtx_::sigs_cnt
uint32_t sigs_cnt
Definition: detect-engine-prefilter-common.h:40
SC_ERR_PCRE_GET_SUBSTRING
@ SC_ERR_PCRE_GET_SUBSTRING
Definition: util-error.h:34
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1252
detect-engine-prefilter.h
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
SigTableElmt_::SetupPrefilter
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1255
PKT_IS_TCP
#define PKT_IS_TCP(p)
Definition: decode.h:264
PrefilterPacketHeaderCtx_
Definition: detect-engine-prefilter-common.h:33
decode.h
util-debug.h
SC_ERR_PCRE_MATCH
@ SC_ERR_PCRE_MATCH
Definition: util-error.h:32
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
DetectEngineThreadCtx_
Definition: detect.h:1060
MODIFIER_PLUS
#define MODIFIER_PLUS
Definition: detect-tcp-flags.c:55
de
uint8_t de
Definition: app-layer-htp.c:563
res
PoolThreadReserved res
Definition: stream-tcp-private.h:0
DetectSetupParseRegexes
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
Definition: detect-parse.c:2597
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:325
TH_ACK
#define TH_ACK
Definition: decode-tcp.h:38
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:89
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:324
SCReturn
#define SCReturn
Definition: util-debug.h:302
Signature_::flags
uint32_t flags
Definition: detect.h:549
DetectFlagsData_::ignored_flags
uint8_t ignored_flags
Definition: detect-tcp-flags.h:44
Packet_
Definition: decode.h:427
Packet_::ip4h
IPV4Hdr * ip4h
Definition: decode.h:525
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:619
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:316
TH_ECN
#define TH_ECN
Definition: decode-tcp.h:41
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1235
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:542
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:235
TH_URG
#define TH_URG
Definition: decode-tcp.h:39
decode-events.h
PrefilterPacketHeaderCtx_::v1
PrefilterPacketHeaderValue v1
Definition: detect-engine-prefilter-common.h:34
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:316
IPV4Hdr_
Definition: decode-ipv4.h:71
TH_PUSH
#define TH_PUSH
Definition: decode-tcp.h:37
TH_SYN
#define TH_SYN
Definition: decode-tcp.h:35
flags
uint8_t flags
Definition: decode-gre.h:0
SigTableElmt_::alias
const char * alias
Definition: detect.h:1268
suricata-common.h
SigMatch_::type
uint16_t type
Definition: detect.h:322
Packet_::tcph
TCPHdr * tcph
Definition: decode.h:547
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:29
PrefilterSetupPacketHeader
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))
Definition: detect-engine-prefilter-common.c:417
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:173
DetectFlagsRegister
void DetectFlagsRegister(void)
Registration function for flags: keyword.
Definition: detect-tcp-flags.c:75
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SigTableElmt_::SupportsPrefilter
bool(* SupportsPrefilter)(const Signature *s)
Definition: detect.h:1254
detect-parse.h
Signature_
Signature container.
Definition: detect.h:548
SigMatch_
a single match condition for a signature
Definition: detect.h:321
TH_CWR
#define TH_CWR
Definition: decode-tcp.h:43
DetectFlagsData_
Definition: detect-tcp-flags.h:41
SC_Pcre2SubstringCopy
int SC_Pcre2SubstringCopy(pcre2_match_data *match_data, uint32_t number, PCRE2_UCHAR *buffer, PCRE2_SIZE *bufflen)
Definition: detect-parse.c:2573
suricata.h
SC_ERR_FLAGS_MODIFIER
@ SC_ERR_FLAGS_MODIFIER
Definition: util-error.h:133
MODIFIER_ANY
#define MODIFIER_ANY
Definition: detect-tcp-flags.c:56
PrefilterPacketHeaderValue
Definition: detect-engine-prefilter-common.h:21
detect-engine-prefilter-common.h
DETECT_FLAGS
@ DETECT_FLAGS
Definition: detect-engine-register.h:40
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
flow-var.h
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:349
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1259
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:223