suricata
detect-flowbits.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2022 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  * \author Breno Silva <breno.silva@gmail.com>
23  *
24  * Implements the flowbits keyword
25  */
26 
27 #include "suricata-common.h"
28 #include "decode.h"
29 #include "detect.h"
30 #include "threads.h"
31 #include "flow.h"
32 #include "flow-bit.h"
33 #include "flow-util.h"
34 #include "detect-flowbits.h"
35 #include "util-spm.h"
36 
37 #include "app-layer-parser.h"
38 
39 #include "detect-parse.h"
40 #include "detect-engine.h"
41 #include "detect-engine-mpm.h"
42 #include "detect-engine-state.h"
43 #include "detect-engine-build.h"
44 
45 #include "util-var-name.h"
46 #include "util-unittest.h"
47 #include "util-debug.h"
48 #include "util-conf.h"
49 
50 #define PARSE_REGEX "^([a-z]+)(?:,\\s*(.*))?"
51 static DetectParseRegex parse_regex;
52 
53 #define MAX_TOKENS 100
54 
56  const Signature *, const SigMatchCtx *);
57 static int DetectFlowbitSetup (DetectEngineCtx *, Signature *, const char *);
58 static int FlowbitOrAddData(DetectEngineCtx *, DetectFlowbitsData *, char *);
59 void DetectFlowbitFree (DetectEngineCtx *, void *);
60 #ifdef UNITTESTS
61 void FlowBitsRegisterTests(void);
62 #endif
63 
65 {
66  sigmatch_table[DETECT_FLOWBITS].name = "flowbits";
67  sigmatch_table[DETECT_FLOWBITS].desc = "operate on flow flag";
68  sigmatch_table[DETECT_FLOWBITS].url = "/rules/flow-keywords.html#flowbits";
70  sigmatch_table[DETECT_FLOWBITS].Setup = DetectFlowbitSetup;
72 #ifdef UNITTESTS
74 #endif
75  /* this is compatible to ip-only signatures */
77 
78  DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
79 }
80 
81 static int FlowbitOrAddData(DetectEngineCtx *de_ctx, DetectFlowbitsData *cd, char *arrptr)
82 {
83  char *strarr[MAX_TOKENS];
84  char *token;
85  char *saveptr = NULL;
86  uint8_t i = 0;
87 
88  while ((token = strtok_r(arrptr, "|", &saveptr))) {
89  // Check for leading/trailing spaces in the token
90  while(isspace((unsigned char)*token))
91  token++;
92  if (*token == 0)
93  goto next;
94  char *end = token + strlen(token) - 1;
95  while(end > token && isspace((unsigned char)*end))
96  *(end--) = '\0';
97 
98  // Check for spaces in between the flowbit names
99  if (strchr(token, ' ') != NULL) {
100  SCLogError("Spaces are not allowed in flowbit names.");
101  return -1;
102  }
103 
104  if (i == MAX_TOKENS) {
105  SCLogError("Number of flowbits exceeds "
106  "maximum allowed: %d.",
107  MAX_TOKENS);
108  return -1;
109  }
110  strarr[i++] = token;
111  next:
112  arrptr = NULL;
113  }
114 
115  cd->or_list_size = i;
116  cd->or_list = SCCalloc(cd->or_list_size, sizeof(uint32_t));
117  if (unlikely(cd->or_list == NULL))
118  return -1;
119  for (uint8_t j = 0; j < cd->or_list_size ; j++) {
120  cd->or_list[j] = VarNameStoreSetupAdd(strarr[j], VAR_TYPE_FLOW_BIT);
122  }
123 
124  return 1;
125 }
126 
127 static int DetectFlowbitMatchToggle (Packet *p, const DetectFlowbitsData *fd)
128 {
129  if (p->flow == NULL)
130  return 0;
131 
132  FlowBitToggle(p->flow,fd->idx);
133 
134  return 1;
135 }
136 
137 static int DetectFlowbitMatchUnset (Packet *p, const DetectFlowbitsData *fd)
138 {
139  if (p->flow == NULL)
140  return 0;
141 
142  FlowBitUnset(p->flow,fd->idx);
143 
144  return 1;
145 }
146 
147 static int DetectFlowbitMatchSet (Packet *p, const DetectFlowbitsData *fd)
148 {
149  if (p->flow == NULL)
150  return 0;
151 
152  FlowBitSet(p->flow,fd->idx);
153 
154  return 1;
155 }
156 
157 static int DetectFlowbitMatchIsset (Packet *p, const DetectFlowbitsData *fd)
158 {
159  if (p->flow == NULL)
160  return 0;
161  if (fd->or_list_size > 0) {
162  for (uint8_t i = 0; i < fd->or_list_size; i++) {
163  if (FlowBitIsset(p->flow, fd->or_list[i]) == 1)
164  return 1;
165  }
166  return 0;
167  }
168 
169  return FlowBitIsset(p->flow,fd->idx);
170 }
171 
172 static int DetectFlowbitMatchIsnotset (Packet *p, const DetectFlowbitsData *fd)
173 {
174  if (p->flow == NULL)
175  return 0;
176  if (fd->or_list_size > 0) {
177  for (uint8_t i = 0; i < fd->or_list_size; i++) {
178  if (FlowBitIsnotset(p->flow, fd->or_list[i]) == 1)
179  return 1;
180  }
181  return 0;
182  }
183  return FlowBitIsnotset(p->flow,fd->idx);
184 }
185 
186 /*
187  * returns 0: no match
188  * 1: match
189  * -1: error
190  */
191 
193  const Signature *s, const SigMatchCtx *ctx)
194 {
195  const DetectFlowbitsData *fd = (const DetectFlowbitsData *)ctx;
196  if (fd == NULL)
197  return 0;
198 
199  switch (fd->cmd) {
201  return DetectFlowbitMatchIsset(p,fd);
203  return DetectFlowbitMatchIsnotset(p,fd);
205  return DetectFlowbitMatchSet(p,fd);
207  return DetectFlowbitMatchUnset(p,fd);
209  return DetectFlowbitMatchToggle(p,fd);
210  default:
211  SCLogError("unknown cmd %" PRIu32 "", fd->cmd);
212  return 0;
213  }
214 
215  return 0;
216 }
217 
218 static int DetectFlowbitParse(const char *str, char *cmd, int cmd_len, char *name,
219  int name_len)
220 {
221  int count, rc;
222  size_t pcre2len;
223 
224  count = DetectParsePcreExec(&parse_regex, str, 0, 0);
225  if (count != 2 && count != 3) {
226  SCLogError("\"%s\" is not a valid setting for flowbits.", str);
227  return 0;
228  }
229 
230  pcre2len = cmd_len;
231  rc = pcre2_substring_copy_bynumber(parse_regex.match, 1, (PCRE2_UCHAR8 *)cmd, &pcre2len);
232  if (rc < 0) {
233  SCLogError("pcre2_substring_copy_bynumber failed");
234  return 0;
235  }
236 
237  if (count == 3) {
238  pcre2len = name_len;
239  rc = pcre2_substring_copy_bynumber(parse_regex.match, 2, (PCRE2_UCHAR8 *)name, &pcre2len);
240  if (rc < 0) {
241  SCLogError("pcre2_substring_copy_bynumber failed");
242  return 0;
243  }
244 
245  /* Trim trailing whitespace. */
246  while (strlen(name) > 0 && isblank(name[strlen(name) - 1])) {
247  name[strlen(name) - 1] = '\0';
248  }
249 
250  if (strchr(name, '|') == NULL) {
251  /* Validate name, spaces are not allowed. */
252  for (size_t i = 0; i < strlen(name); i++) {
253  if (isblank(name[i])) {
254  SCLogError("spaces not allowed in flowbit names");
255  return 0;
256  }
257  }
258  }
259  }
260 
261  return 1;
262 }
263 
264 int DetectFlowbitSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
265 {
266  DetectFlowbitsData *cd = NULL;
267  SigMatch *sm = NULL;
268  uint8_t fb_cmd = 0;
269  char fb_cmd_str[16] = "", fb_name[256] = "";
270 
271  if (!DetectFlowbitParse(rawstr, fb_cmd_str, sizeof(fb_cmd_str), fb_name,
272  sizeof(fb_name))) {
273  return -1;
274  }
275 
276  if (strcmp(fb_cmd_str,"noalert") == 0) {
278  } else if (strcmp(fb_cmd_str,"isset") == 0) {
279  fb_cmd = DETECT_FLOWBITS_CMD_ISSET;
280  } else if (strcmp(fb_cmd_str,"isnotset") == 0) {
282  } else if (strcmp(fb_cmd_str,"set") == 0) {
283  fb_cmd = DETECT_FLOWBITS_CMD_SET;
284  } else if (strcmp(fb_cmd_str,"unset") == 0) {
285  fb_cmd = DETECT_FLOWBITS_CMD_UNSET;
286  } else if (strcmp(fb_cmd_str,"toggle") == 0) {
288  } else {
289  SCLogError("ERROR: flowbits action \"%s\" is not supported.", fb_cmd_str);
290  goto error;
291  }
292 
293  switch (fb_cmd) {
295  if (strlen(fb_name) != 0)
296  goto error;
297  s->flags |= SIG_FLAG_NOALERT;
298  return 0;
304  default:
305  if (strlen(fb_name) == 0)
306  goto error;
307  break;
308  }
309 
310  cd = SCCalloc(1, sizeof(DetectFlowbitsData));
311  if (unlikely(cd == NULL))
312  goto error;
313  if (strchr(fb_name, '|') != NULL) {
314  int retval = FlowbitOrAddData(de_ctx, cd, fb_name);
315  if (retval == -1) {
316  goto error;
317  }
318  cd->cmd = fb_cmd;
319  } else {
322  cd->cmd = fb_cmd;
323  cd->or_list_size = 0;
324  cd->or_list = NULL;
325  SCLogDebug("idx %" PRIu32 ", cmd %s, name %s",
326  cd->idx, fb_cmd_str, strlen(fb_name) ? fb_name : "(none)");
327  }
328  /* Okay so far so good, lets get this into a SigMatch
329  * and put it in the Signature. */
330  sm = SigMatchAlloc();
331  if (sm == NULL)
332  goto error;
333 
334  sm->type = DETECT_FLOWBITS;
335  sm->ctx = (SigMatchCtx *)cd;
336 
337  switch (fb_cmd) {
338  /* case DETECT_FLOWBITS_CMD_NOALERT can't happen here */
339 
342  /* checks, so packet list */
344  break;
345 
349  /* modifiers, only run when entire sig has matched */
351  break;
352 
353  // suppress coverity warning as scan-build-7 warns w/o this.
354  // coverity[deadcode : FALSE]
355  default:
356  goto error;
357  }
358 
359  return 0;
360 
361 error:
362  if (cd != NULL)
364  if (sm != NULL)
365  SCFree(sm);
366  return -1;
367 }
368 
370 {
372  if (fd == NULL)
373  return;
374  if (fd->or_list != NULL)
375  SCFree(fd->or_list);
376  SCFree(fd);
377 }
378 
379 struct FBAnalyze {
382 
383  uint32_t *set_sids;
384  uint32_t set_sids_idx;
385  uint32_t set_sids_size;
386 
387  uint32_t *isset_sids;
388  uint32_t isset_sids_idx;
389  uint32_t isset_sids_size;
390 
391  uint32_t *isnotset_sids;
394 
395  uint32_t *unset_sids;
396  uint32_t unset_sids_idx;
397  uint32_t unset_sids_size;
398 
399  uint32_t *toggle_sids;
400  uint32_t toggle_sids_idx;
402 };
403 
404 extern int rule_engine_analysis_set;
405 static void DetectFlowbitsAnalyzeDump(const DetectEngineCtx *de_ctx,
406  struct FBAnalyze *array, uint32_t elements);
407 
409 {
410  const uint32_t max_fb_id = de_ctx->max_fb_id;
411  if (max_fb_id == 0)
412  return 0;
413 
414 #define MAX_SIDS 8
415  uint32_t array_size = max_fb_id + 1;
416  struct FBAnalyze *array = SCCalloc(array_size, sizeof(struct FBAnalyze));
417 
418  if (array == NULL) {
419  SCLogError("Unable to allocate flowbit analyze array");
420  return -1;
421  }
422 
423  SCLogDebug("fb analyzer array size: %"PRIu64,
424  (uint64_t)(array_size * sizeof(struct FBAnalyze)));
425 
426  /* fill flowbit array, updating counters per sig */
427  for (uint32_t i = 0; i < de_ctx->sig_array_len; i++) {
428  const Signature *s = de_ctx->sig_array[i];
429  bool has_state = false;
430 
431  /* see if the signature uses stateful matching */
432  for (uint32_t x = DETECT_SM_LIST_DYNAMIC_START; x < s->init_data->smlists_array_size; x++) {
433  if (s->init_data->smlists[x] == NULL)
434  continue;
435  has_state = true;
436  break;
437  }
438 
439  for (const SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
440  switch (sm->type) {
441  case DETECT_FLOWBITS:
442  {
443  /* figure out the flowbit action */
444  const DetectFlowbitsData *fb = (DetectFlowbitsData *)sm->ctx;
445  // Handle flowbit array in case of ORed flowbits
446  for (uint8_t k = 0; k < fb->or_list_size; k++) {
447  array[fb->or_list[k]].cnts[fb->cmd]++;
448  if (has_state)
449  array[fb->or_list[k]].state_cnts[fb->cmd]++;
450  if (fb->cmd == DETECT_FLOWBITS_CMD_ISSET) {
451  if (array[fb->or_list[k]].isset_sids_idx >= array[fb->or_list[k]].isset_sids_size) {
452  uint32_t old_size = array[fb->or_list[k]].isset_sids_size;
453  uint32_t new_size = MAX(2 * old_size, MAX_SIDS);
454 
455  void *ptr = SCRealloc(array[fb->or_list[k]].isset_sids, new_size * sizeof(uint32_t));
456  if (ptr == NULL)
457  goto end;
458  array[fb->or_list[k]].isset_sids_size = new_size;
459  array[fb->or_list[k]].isset_sids = ptr;
460  }
461 
462  array[fb->or_list[k]].isset_sids[array[fb->or_list[k]].isset_sids_idx] = s->num;
463  array[fb->or_list[k]].isset_sids_idx++;
464  } else if (fb->cmd == DETECT_FLOWBITS_CMD_ISNOTSET) {
465  if (array[fb->or_list[k]].isnotset_sids_idx >= array[fb->or_list[k]].isnotset_sids_size) {
466  uint32_t old_size = array[fb->or_list[k]].isnotset_sids_size;
467  uint32_t new_size = MAX(2 * old_size, MAX_SIDS);
468 
469  void *ptr = SCRealloc(array[fb->or_list[k]].isnotset_sids, new_size * sizeof(uint32_t));
470  if (ptr == NULL)
471  goto end;
472  array[fb->or_list[k]].isnotset_sids_size = new_size;
473  array[fb->or_list[k]].isnotset_sids = ptr;
474  }
475 
476  array[fb->or_list[k]].isnotset_sids[array[fb->or_list[k]].isnotset_sids_idx] = s->num;
477  array[fb->or_list[k]].isnotset_sids_idx++;
478  }
479  }
480  if (fb->or_list_size == 0) {
481  array[fb->idx].cnts[fb->cmd]++;
482  if (has_state)
483  array[fb->idx].state_cnts[fb->cmd]++;
484  if (fb->cmd == DETECT_FLOWBITS_CMD_ISSET) {
485  if (array[fb->idx].isset_sids_idx >= array[fb->idx].isset_sids_size) {
486  uint32_t old_size = array[fb->idx].isset_sids_size;
487  uint32_t new_size = MAX(2 * old_size, MAX_SIDS);
488 
489  void *ptr = SCRealloc(array[fb->idx].isset_sids, new_size * sizeof(uint32_t));
490  if (ptr == NULL)
491  goto end;
492  array[fb->idx].isset_sids_size = new_size;
493  array[fb->idx].isset_sids = ptr;
494  }
495 
496  array[fb->idx].isset_sids[array[fb->idx].isset_sids_idx] = s->num;
497  array[fb->idx].isset_sids_idx++;
498  } else if (fb->cmd == DETECT_FLOWBITS_CMD_ISNOTSET) {
499  if (array[fb->idx].isnotset_sids_idx >= array[fb->idx].isnotset_sids_size) {
500  uint32_t old_size = array[fb->idx].isnotset_sids_size;
501  uint32_t new_size = MAX(2 * old_size, MAX_SIDS);
502 
503  void *ptr = SCRealloc(array[fb->idx].isnotset_sids, new_size * sizeof(uint32_t));
504  if (ptr == NULL)
505  goto end;
506  array[fb->idx].isnotset_sids_size = new_size;
507  array[fb->idx].isnotset_sids = ptr;
508  }
509 
510  array[fb->idx].isnotset_sids[array[fb->idx].isnotset_sids_idx] = s->num;
511  array[fb->idx].isnotset_sids_idx++;
512  }
513  }
514  }
515  }
516  }
517  for (const SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_POSTMATCH] ; sm != NULL; sm = sm->next) {
518  switch (sm->type) {
519  case DETECT_FLOWBITS:
520  {
521  /* figure out what flowbit action */
522  const DetectFlowbitsData *fb = (DetectFlowbitsData *)sm->ctx;
523  array[fb->idx].cnts[fb->cmd]++;
524  if (has_state)
525  array[fb->idx].state_cnts[fb->cmd]++;
526  if (fb->cmd == DETECT_FLOWBITS_CMD_SET) {
527  if (array[fb->idx].set_sids_idx >= array[fb->idx].set_sids_size) {
528  uint32_t old_size = array[fb->idx].set_sids_size;
529  uint32_t new_size = MAX(2 * old_size, MAX_SIDS);
530 
531  void *ptr = SCRealloc(array[fb->idx].set_sids, new_size * sizeof(uint32_t));
532  if (ptr == NULL)
533  goto end;
534  array[fb->idx].set_sids_size = new_size;
535  array[fb->idx].set_sids = ptr;
536  }
537 
538  array[fb->idx].set_sids[array[fb->idx].set_sids_idx] = s->num;
539  array[fb->idx].set_sids_idx++;
540  }
541  else if (fb->cmd == DETECT_FLOWBITS_CMD_UNSET) {
542  if (array[fb->idx].unset_sids_idx >= array[fb->idx].unset_sids_size) {
543  uint32_t old_size = array[fb->idx].unset_sids_size;
544  uint32_t new_size = MAX(2 * old_size, MAX_SIDS);
545 
546  void *ptr = SCRealloc(array[fb->idx].unset_sids, new_size * sizeof(uint32_t));
547  if (ptr == NULL)
548  goto end;
549  array[fb->idx].unset_sids_size = new_size;
550  array[fb->idx].unset_sids = ptr;
551  }
552 
553  array[fb->idx].unset_sids[array[fb->idx].unset_sids_idx] = s->num;
554  array[fb->idx].unset_sids_idx++;
555  }
556  else if (fb->cmd == DETECT_FLOWBITS_CMD_TOGGLE) {
557  if (array[fb->idx].toggle_sids_idx >= array[fb->idx].toggle_sids_size) {
558  uint32_t old_size = array[fb->idx].toggle_sids_size;
559  uint32_t new_size = MAX(2 * old_size, MAX_SIDS);
560 
561  void *ptr = SCRealloc(array[fb->idx].toggle_sids, new_size * sizeof(uint32_t));
562  if (ptr == NULL)
563  goto end;
564  array[fb->idx].toggle_sids_size = new_size;
565  array[fb->idx].toggle_sids = ptr;
566  }
567 
568  array[fb->idx].toggle_sids[array[fb->idx].toggle_sids_idx] = s->num;
569  array[fb->idx].toggle_sids_idx++;
570  }
571  }
572  }
573  }
574  }
575 
576  /* walk array to see if all bits make sense */
577  for (uint32_t i = 0; i < array_size; i++) {
578  char *varname = VarNameStoreSetupLookup(i, VAR_TYPE_FLOW_BIT);
579  if (varname == NULL)
580  continue;
581 
582  bool to_state = false;
583 
584  if (array[i].cnts[DETECT_FLOWBITS_CMD_ISSET] &&
585  array[i].cnts[DETECT_FLOWBITS_CMD_TOGGLE] == 0 &&
586  array[i].cnts[DETECT_FLOWBITS_CMD_SET] == 0) {
587 
588  const Signature *s = de_ctx->sig_array[array[i].isset_sids[0]];
589  SCLogWarning("flowbit '%s' is checked but not "
590  "set. Checked in %u and %u other sigs",
591  varname, s->id, array[i].isset_sids_idx - 1);
592  }
593  if (array[i].state_cnts[DETECT_FLOWBITS_CMD_ISSET] &&
594  array[i].state_cnts[DETECT_FLOWBITS_CMD_SET] == 0)
595  {
596  SCLogDebug("flowbit %s/%u: isset in state, set not in state", varname, i);
597  }
598 
599  /* if signature depends on 'stateful' flowbits, then turn the
600  * sig into a stateful sig itself */
601  if (array[i].cnts[DETECT_FLOWBITS_CMD_ISSET] > 0 &&
602  array[i].state_cnts[DETECT_FLOWBITS_CMD_ISSET] == 0 &&
604  {
605  SCLogDebug("flowbit %s/%u: isset not in state, set in state", varname, i);
606  to_state = true;
607  }
608 
609  SCLogDebug("ALL flowbit %s/%u: sets %u toggles %u unsets %u isnotsets %u issets %u", varname, i,
612  array[i].cnts[DETECT_FLOWBITS_CMD_ISSET]);
613  SCLogDebug("STATE flowbit %s/%u: sets %u toggles %u unsets %u isnotsets %u issets %u", varname, i,
617  for (uint32_t x = 0; x < array[i].set_sids_idx; x++) {
618  SCLogDebug("SET flowbit %s/%u: SID %u", varname, i,
619  de_ctx->sig_array[array[i].set_sids[x]]->id);
620  }
621  for (uint32_t x = 0; x < array[i].isset_sids_idx; x++) {
622  Signature *s = de_ctx->sig_array[array[i].isset_sids[x]];
623  SCLogDebug("GET flowbit %s/%u: SID %u", varname, i, s->id);
624 
625  if (to_state) {
627  SCLogDebug("made SID %u stateful because it depends on "
628  "stateful rules that set flowbit %s", s->id, varname);
629  }
630  }
631  SCFree(varname);
632  }
633 
635  DetectFlowbitsAnalyzeDump(de_ctx, array, array_size);
636  }
637 
638 end:
639  for (uint32_t i = 0; i < array_size; i++) {
640  SCFree(array[i].set_sids);
641  SCFree(array[i].unset_sids);
642  SCFree(array[i].isset_sids);
643  SCFree(array[i].isnotset_sids);
644  SCFree(array[i].toggle_sids);
645  }
646  SCFree(array);
647 
648  return 0;
649 }
650 
652 static void DetectFlowbitsAnalyzeDump(const DetectEngineCtx *de_ctx,
653  struct FBAnalyze *array, uint32_t elements)
654 {
655  JsonBuilder *js = jb_new_object();
656  if (js == NULL)
657  return;
658 
659  jb_open_array(js, "flowbits");
660  for (uint32_t x = 0; x < elements; x++) {
661  char *varname = VarNameStoreSetupLookup(x, VAR_TYPE_FLOW_BIT);
662  if (varname == NULL)
663  continue;
664 
665  const struct FBAnalyze *e = &array[x];
666 
667  jb_start_object(js);
668  jb_set_string(js, "name", varname);
669  jb_set_uint(js, "internal_id", x);
670  jb_set_uint(js, "set_cnt", e->cnts[DETECT_FLOWBITS_CMD_SET]);
671  jb_set_uint(js, "unset_cnt", e->cnts[DETECT_FLOWBITS_CMD_UNSET]);
672  jb_set_uint(js, "toggle_cnt", e->cnts[DETECT_FLOWBITS_CMD_TOGGLE]);
673  jb_set_uint(js, "isset_cnt", e->cnts[DETECT_FLOWBITS_CMD_ISSET]);
674  jb_set_uint(js, "isnotset_cnt", e->cnts[DETECT_FLOWBITS_CMD_ISNOTSET]);
675 
676  // sets
677  if (e->cnts[DETECT_FLOWBITS_CMD_SET]) {
678  jb_open_array(js, "sets");
679  for (uint32_t i = 0; i < e->set_sids_idx; i++) {
680  const Signature *s = de_ctx->sig_array[e->set_sids[i]];
681  jb_append_uint(js, s->id);
682  }
683  jb_close(js);
684  }
685  // gets
687  jb_open_array(js, "isset");
688  for (uint32_t i = 0; i < e->isset_sids_idx; i++) {
689  const Signature *s = de_ctx->sig_array[e->isset_sids[i]];
690  jb_append_uint(js, s->id);
691  }
692  jb_close(js);
693  }
694  // isnotset
696  jb_open_array(js, "isnotset");
697  for (uint32_t i = 0; i < e->isnotset_sids_idx; i++) {
698  const Signature *s = de_ctx->sig_array[e->isnotset_sids[i]];
699  jb_append_uint(js, s->id);
700  }
701  jb_close(js);
702  }
703  // unset
705  jb_open_array(js, "unset");
706  for (uint32_t i = 0; i < e->unset_sids_idx; i++) {
707  const Signature *s = de_ctx->sig_array[e->unset_sids[i]];
708  jb_append_uint(js, s->id);
709  }
710  jb_close(js);
711  }
712  // toggle
714  jb_open_array(js, "toggle");
715  for (uint32_t i = 0; i < e->toggle_sids_idx; i++) {
716  const Signature *s = de_ctx->sig_array[e->toggle_sids[i]];
717  jb_append_uint(js, s->id);
718  }
719  jb_close(js);
720  }
721  SCFree(varname);
722  jb_close(js);
723  }
724  jb_close(js); // array
725  jb_close(js); // object
726 
727  const char *filename = "flowbits.json";
728  const char *log_dir = ConfigGetLogDirectory();
729  char log_path[PATH_MAX] = "";
730  snprintf(log_path, sizeof(log_path), "%s/%s", log_dir, filename);
731 
733  FILE *fp = fopen(log_path, "w");
734  if (fp != NULL) {
735  fwrite(jb_ptr(js), jb_len(js), 1, fp);
736  fprintf(fp, "\n");
737  fclose(fp);
738  }
740 
741  jb_free(js);
742 }
743 
744 #ifdef UNITTESTS
745 
746 static int FlowBitsTestParse01(void)
747 {
748  char command[16] = "", name[16] = "";
749 
750  /* Single argument version. */
751  FAIL_IF(!DetectFlowbitParse("noalert", command, sizeof(command), name,
752  sizeof(name)));
753  FAIL_IF(strcmp(command, "noalert") != 0);
754 
755  /* No leading or trailing spaces. */
756  FAIL_IF(!DetectFlowbitParse("set,flowbit", command, sizeof(command), name,
757  sizeof(name)));
758  FAIL_IF(strcmp(command, "set") != 0);
759  FAIL_IF(strcmp(name, "flowbit") != 0);
760 
761  /* Leading space. */
762  FAIL_IF(!DetectFlowbitParse("set, flowbit", command, sizeof(command), name,
763  sizeof(name)));
764  FAIL_IF(strcmp(command, "set") != 0);
765  FAIL_IF(strcmp(name, "flowbit") != 0);
766 
767  /* Trailing space. */
768  FAIL_IF(!DetectFlowbitParse("set,flowbit ", command, sizeof(command), name,
769  sizeof(name)));
770  FAIL_IF(strcmp(command, "set") != 0);
771  FAIL_IF(strcmp(name, "flowbit") != 0);
772 
773  /* Leading and trailing space. */
774  FAIL_IF(!DetectFlowbitParse("set, flowbit ", command, sizeof(command), name,
775  sizeof(name)));
776  FAIL_IF(strcmp(command, "set") != 0);
777  FAIL_IF(strcmp(name, "flowbit") != 0);
778 
779  /* Spaces are not allowed in the name. */
780  FAIL_IF(DetectFlowbitParse("set,namewith space", command, sizeof(command),
781  name, sizeof(name)));
782 
783  PASS;
784 }
785 
786 /**
787  * \test FlowBitsTestSig01 is a test for a valid noalert flowbits option
788  *
789  * \retval 1 on succces
790  * \retval 0 on failure
791  */
792 
793 static int FlowBitsTestSig01(void)
794 {
795  Signature *s = NULL;
796  DetectEngineCtx *de_ctx = NULL;
797 
800 
801  de_ctx->flags |= DE_QUIET;
802 
803  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Noalert\"; flowbits:noalert,wrongusage; content:\"GET \"; sid:1;)");
804  FAIL_IF_NOT_NULL(s);
805 
808  PASS;
809 }
810 
811 /**
812  * \test FlowBitsTestSig02 is a test for a valid isset,set,isnotset,unset,toggle flowbits options
813  *
814  * \retval 1 on succces
815  * \retval 0 on failure
816  */
817 
818 static int FlowBitsTestSig02(void)
819 {
820  Signature *s = NULL;
821  ThreadVars th_v;
822  DetectEngineCtx *de_ctx = NULL;
823 
824  memset(&th_v, 0, sizeof(th_v));
825 
828 
829  de_ctx->flags |= DE_QUIET;
830 
831  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"isset rule need an option\"; flowbits:isset; content:\"GET \"; sid:1;)");
832  FAIL_IF_NOT_NULL(s);
833 
834  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"isnotset rule need an option\"; flowbits:isnotset; content:\"GET \"; sid:2;)");
835  FAIL_IF_NOT_NULL(s);
836 
837  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"set rule need an option\"; flowbits:set; content:\"GET \"; sid:3;)");
838  FAIL_IF_NOT_NULL(s);
839 
840  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"unset rule need an option\"; flowbits:unset; content:\"GET \"; sid:4;)");
841  FAIL_IF_NOT_NULL(s);
842 
843  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"toggle rule need an option\"; flowbits:toggle; content:\"GET \"; sid:5;)");
844  FAIL_IF_NOT_NULL(s);
845 
846  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"!set is not an option\"; flowbits:!set,myerr; content:\"GET \"; sid:6;)");
847  FAIL_IF_NOT_NULL(s);
848 
851 
852  PASS;
853 }
854 
855 /**
856  * \test FlowBitsTestSig03 is a test for a invalid flowbits option
857  *
858  * \retval 1 on succces
859  * \retval 0 on failure
860  */
861 
862 static int FlowBitsTestSig03(void)
863 {
864  Signature *s = NULL;
865  DetectEngineCtx *de_ctx = NULL;
866 
869 
870  de_ctx->flags |= DE_QUIET;
871 
872  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Unknown cmd\"; flowbits:wrongcmd; content:\"GET \"; sid:1;)");
873  FAIL_IF_NOT_NULL(s);
874 
877  PASS;
878 }
879 
880 /**
881  * \test FlowBitsTestSig04 is a test check idx value
882  *
883  * \retval 1 on succces
884  * \retval 0 on failure
885  */
886 
887 static int FlowBitsTestSig04(void)
888 {
889  Signature *s = NULL;
890  DetectEngineCtx *de_ctx = NULL;
891  int idx = 0;
894 
895  de_ctx->flags |= DE_QUIET;
896 
897  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"isset option\"; flowbits:isset,fbt; content:\"GET \"; sid:1;)");
898  FAIL_IF_NULL(s);
899 
901  FAIL_IF(idx != 1);
902 
905  PASS;
906 }
907 
908 /**
909  * \test FlowBitsTestSig05 is a test check noalert flag
910  *
911  * \retval 1 on succces
912  * \retval 0 on failure
913  */
914 
915 static int FlowBitsTestSig05(void)
916 {
917  Signature *s = NULL;
918  DetectEngineCtx *de_ctx = NULL;
919 
922 
923  de_ctx->flags |= DE_QUIET;
924 
925  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Noalert\"; flowbits:noalert; content:\"GET \"; sid:1;)");
926  FAIL_IF_NULL(s);
928 
931  PASS;
932 }
933 
934 /**
935  * \test FlowBitsTestSig06 is a test set flowbits option
936  *
937  * \retval 1 on succces
938  * \retval 0 on failure
939  */
940 
941 static int FlowBitsTestSig06(void)
942 {
943  uint8_t *buf = (uint8_t *)
944  "GET /one/ HTTP/1.1\r\n"
945  "Host: one.example.org\r\n"
946  "\r\n";
947  uint16_t buflen = strlen((char *)buf);
948  Packet *p = PacketGetFromAlloc();
949  FAIL_IF_NULL(p);
950  Signature *s = NULL;
951  ThreadVars th_v;
952  DetectEngineThreadCtx *det_ctx = NULL;
953  DetectEngineCtx *de_ctx = NULL;
954  Flow f;
955  GenericVar flowvar, *gv = NULL;
956  int result = 0;
957  uint32_t idx = 0;
958 
959  memset(&th_v, 0, sizeof(th_v));
960  memset(&f, 0, sizeof(Flow));
961  memset(&flowvar, 0, sizeof(GenericVar));
962 
963  FLOW_INITIALIZE(&f);
964  p->flow = &f;
965  p->flow->flowvar = &flowvar;
966 
967  p->src.family = AF_INET;
968  p->dst.family = AF_INET;
969  p->payload = buf;
970  p->payload_len = buflen;
971  p->proto = IPPROTO_TCP;
972  p->flags |= PKT_HAS_FLOW;
974 
977 
978  de_ctx->flags |= DE_QUIET;
979 
980  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Flowbit set\"; flowbits:set,myflow; sid:10;)");
981  FAIL_IF_NULL(s);
982 
983  idx = VarNameStoreSetupAdd("myflow", VAR_TYPE_FLOW_BIT);
985  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
986 
987  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
988 
989  gv = p->flow->flowvar;
990  FAIL_IF_NULL(gv);
991  for ( ; gv != NULL; gv = gv->next) {
992  if (gv->type == DETECT_FLOWBITS && gv->idx == idx) {
993  result = 1;
994  }
995  }
996  FAIL_IF_NOT(result);
997 
998  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1000 
1001  FLOW_DESTROY(&f);
1002 
1003  SCFree(p);
1004  PASS;
1005 }
1006 
1007 /**
1008  * \test FlowBitsTestSig07 is a test unset flowbits option
1009  *
1010  * \retval 1 on succces
1011  * \retval 0 on failure
1012  */
1013 
1014 static int FlowBitsTestSig07(void)
1015 {
1016  uint8_t *buf = (uint8_t *)
1017  "GET /one/ HTTP/1.1\r\n"
1018  "Host: one.example.org\r\n"
1019  "\r\n";
1020  uint16_t buflen = strlen((char *)buf);
1021  Packet *p = PacketGetFromAlloc();
1022  FAIL_IF_NULL(p);
1023  Signature *s = NULL;
1024  ThreadVars th_v;
1025  DetectEngineThreadCtx *det_ctx = NULL;
1026  DetectEngineCtx *de_ctx = NULL;
1027  Flow f;
1028  GenericVar flowvar, *gv = NULL;
1029  int result = 0;
1030  uint32_t idx = 0;
1031 
1032  memset(&th_v, 0, sizeof(th_v));
1033  memset(&f, 0, sizeof(Flow));
1034  memset(&flowvar, 0, sizeof(GenericVar));
1035 
1036  FLOW_INITIALIZE(&f);
1037  p->flow = &f;
1038  p->flow->flowvar = &flowvar;
1039 
1040  p->src.family = AF_INET;
1041  p->dst.family = AF_INET;
1042  p->payload = buf;
1043  p->payload_len = buflen;
1044  p->proto = IPPROTO_TCP;
1045 
1048 
1049  de_ctx->flags |= DE_QUIET;
1050 
1051  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Flowbit set\"; flowbits:set,myflow2; sid:10;)");
1052  FAIL_IF_NULL(s);
1053 
1054  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Flowbit unset\"; flowbits:unset,myflow2; sid:11;)");
1055  FAIL_IF_NULL(s);
1056 
1057  idx = VarNameStoreSetupAdd("myflow", VAR_TYPE_FLOW_BIT);
1059  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1060 
1061  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1062 
1063  gv = p->flow->flowvar;
1064  FAIL_IF_NULL(gv);
1065 
1066  for ( ; gv != NULL; gv = gv->next) {
1067  if (gv->type == DETECT_FLOWBITS && gv->idx == idx) {
1068  result = 1;
1069  }
1070  }
1071  FAIL_IF(result);
1072 
1073  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1075 
1076  FLOW_DESTROY(&f);
1077 
1078  SCFree(p);
1079  PASS;
1080 }
1081 
1082 /**
1083  * \test FlowBitsTestSig08 is a test toogle flowbits option
1084  *
1085  * \retval 1 on succces
1086  * \retval 0 on failure
1087  */
1088 
1089 static int FlowBitsTestSig08(void)
1090 {
1091  uint8_t *buf = (uint8_t *)
1092  "GET /one/ HTTP/1.1\r\n"
1093  "Host: one.example.org\r\n"
1094  "\r\n";
1095  uint16_t buflen = strlen((char *)buf);
1096  Packet *p = PacketGetFromAlloc();
1097  if (unlikely(p == NULL))
1098  return 0;
1099  Signature *s = NULL;
1100  ThreadVars th_v;
1101  DetectEngineThreadCtx *det_ctx = NULL;
1102  DetectEngineCtx *de_ctx = NULL;
1103  Flow f;
1104  GenericVar flowvar, *gv = NULL;
1105  int result = 0;
1106  uint32_t idx = 0;
1107 
1108  memset(&th_v, 0, sizeof(th_v));
1109  memset(&f, 0, sizeof(Flow));
1110  memset(&flowvar, 0, sizeof(GenericVar));
1111 
1112  FLOW_INITIALIZE(&f);
1113  p->flow = &f;
1114  p->flow->flowvar = &flowvar;
1115 
1116  p->src.family = AF_INET;
1117  p->dst.family = AF_INET;
1118  p->payload = buf;
1119  p->payload_len = buflen;
1120  p->proto = IPPROTO_TCP;
1121 
1124 
1125  de_ctx->flags |= DE_QUIET;
1126 
1127  s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Flowbit set\"; flowbits:set,myflow2; sid:10;)");
1128  FAIL_IF_NULL(s);
1129 
1130  s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Flowbit unset\"; flowbits:toggle,myflow2; sid:11;)");
1131  FAIL_IF_NULL(s);
1132 
1133  idx = VarNameStoreSetupAdd("myflow", VAR_TYPE_FLOW_BIT);
1135  DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1136 
1137  SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1138 
1139  gv = p->flow->flowvar;
1140  FAIL_IF_NULL(gv);
1141 
1142  for ( ; gv != NULL; gv = gv->next) {
1143  if (gv->type == DETECT_FLOWBITS && gv->idx == idx) {
1144  result = 1;
1145  }
1146  }
1147  FAIL_IF(result);
1148 
1149  DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1151 
1152  FLOW_DESTROY(&f);
1153 
1154  SCFree(p);
1155  PASS;
1156 }
1157 
1158 /**
1159  * \brief this function registers unit tests for FlowBits
1160  */
1162 {
1163  UtRegisterTest("FlowBitsTestParse01", FlowBitsTestParse01);
1164  UtRegisterTest("FlowBitsTestSig01", FlowBitsTestSig01);
1165  UtRegisterTest("FlowBitsTestSig02", FlowBitsTestSig02);
1166  UtRegisterTest("FlowBitsTestSig03", FlowBitsTestSig03);
1167  UtRegisterTest("FlowBitsTestSig04", FlowBitsTestSig04);
1168  UtRegisterTest("FlowBitsTestSig05", FlowBitsTestSig05);
1169  UtRegisterTest("FlowBitsTestSig06", FlowBitsTestSig06);
1170  UtRegisterTest("FlowBitsTestSig07", FlowBitsTestSig07);
1171  UtRegisterTest("FlowBitsTestSig08", FlowBitsTestSig08);
1172 }
1173 #endif /* UNITTESTS */
FBAnalyze::cnts
uint16_t cnts[DETECT_FLOWBITS_CMD_MAX]
Definition: detect-flowbits.c:380
GenericVar_::type
uint8_t type
Definition: util-var.h:49
FBAnalyze::isset_sids
uint32_t * isset_sids
Definition: detect-flowbits.c:387
DetectParseRegex::match
pcre2_match_data * match
Definition: detect-parse.h:47
SigTableElmt_::url
const char * url
Definition: detect.h:1241
Packet_::proto
uint8_t proto
Definition: decode.h:450
FBAnalyze::isnotset_sids_idx
uint32_t isnotset_sids_idx
Definition: detect-flowbits.c:392
g_flowbits_dump_write_m
SCMutex g_flowbits_dump_write_m
Definition: detect-flowbits.c:651
DetectFlowbitsData_::or_list_size
uint8_t or_list_size
Definition: detect-flowbits.h:39
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_FLOWBITS_CMD_MAX
#define DETECT_FLOWBITS_CMD_MAX
Definition: detect-flowbits.h:34
SigTableElmt_::desc
const char * desc
Definition: detect.h:1240
DetectParsePcreExec
int DetectParsePcreExec(DetectParseRegex *parse_regex, const char *str, int start_offset, int options)
Definition: detect-parse.c:2488
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1003
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1228
flow-util.h
DetectParseRegex
Definition: detect-parse.h:44
SigTableElmt_::name
const char * name
Definition: detect.h:1238
Signature_::num
SigIntId num
Definition: detect.h:551
FBAnalyze::isnotset_sids
uint32_t * isnotset_sids
Definition: detect-flowbits.c:391
FlowBitsRegisterTests
void FlowBitsRegisterTests(void)
this function registers unit tests for FlowBits
Definition: detect-flowbits.c:1161
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
MAX_SIDS
#define MAX_SIDS
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
FBAnalyze::unset_sids_size
uint32_t unset_sids_size
Definition: detect-flowbits.c:397
MAX_TOKENS
#define MAX_TOKENS
Definition: detect-flowbits.c:53
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DETECT_SM_LIST_DYNAMIC_START
@ DETECT_SM_LIST_DYNAMIC_START
Definition: detect.h:98
DETECT_FLOWBITS_CMD_ISNOTSET
#define DETECT_FLOWBITS_CMD_ISNOTSET
Definition: detect-flowbits.h:31
Packet_::payload
uint8_t * payload
Definition: decode.h:573
Packet_::flags
uint32_t flags
Definition: decode.h:463
threads.h
Flow_
Flow data structure.
Definition: flow.h:357
DetectFlowbitsAnalyze
int DetectFlowbitsAnalyze(DetectEngineCtx *de_ctx)
Definition: detect-flowbits.c:408
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1232
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:785
VarNameStoreSetupLookup
char * VarNameStoreSetupLookup(uint32_t idx, const enum VarTypes type)
Definition: util-var-name.c:332
DetectFlowbitsData_::cmd
uint8_t cmd
Definition: detect-flowbits.h:38
DetectEngineCtxFree
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Definition: detect-engine.c:2442
flow-bit.h
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:227
util-var-name.h
DE_QUIET
#define DE_QUIET
Definition: detect.h:287
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1809
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
SignatureInitData_::init_flags
uint32_t init_flags
Definition: detect.h:503
DETECT_FLOWBITS_CMD_TOGGLE
#define DETECT_FLOWBITS_CMD_TOGGLE
Definition: detect-flowbits.h:29
DETECT_FLOWBITS_CMD_ISSET
#define DETECT_FLOWBITS_CMD_ISSET
Definition: detect-flowbits.h:32
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:459
MAX
#define MAX(x, y)
Definition: suricata-common.h:384
SigTableElmt_::Setup
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1223
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:574
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
Signature_::next
struct Signature_ * next
Definition: detect.h:614
FlowBitUnset
void FlowBitUnset(Flow *f, uint32_t idx)
Definition: flow-bit.c:89
DetectFlowbitsData_
Definition: detect-flowbits.h:36
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:87
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:40
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
GenericVar_::next
struct GenericVar_ * next
Definition: util-var.h:52
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
PARSE_REGEX
#define PARSE_REGEX
Definition: detect-flowbits.c:50
DetectEngineThreadCtx_
Definition: detect.h:1025
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
DetectSetupParseRegexes
void DetectSetupParseRegexes(const char *parse_str, DetectParseRegex *detect_parse)
Definition: detect-parse.c:2609
FlowBitSet
void FlowBitSet(Flow *f, uint32_t idx)
Definition: flow-bit.c:84
detect-engine-mpm.h
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
FBAnalyze::toggle_sids_idx
uint32_t toggle_sids_idx
Definition: detect-flowbits.c:400
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:317
FBAnalyze::set_sids_size
uint32_t set_sids_size
Definition: detect-flowbits.c:385
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:78
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
SigInit
Signature * SigInit(DetectEngineCtx *de_ctx, const char *sigstr)
Parses a signature and adds it to the Detection Engine Context.
Definition: detect-parse.c:2129
app-layer-parser.h
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:316
GenericVar_::idx
uint32_t idx
Definition: util-var.h:51
FBAnalyze::unset_sids
uint32_t * unset_sids
Definition: detect-flowbits.c:395
DetectFlowbitFree
void DetectFlowbitFree(DetectEngineCtx *, void *)
Definition: detect-flowbits.c:369
DetectFlowbitsRegister
void DetectFlowbitsRegister(void)
Definition: detect-flowbits.c:64
Signature_::flags
uint32_t flags
Definition: detect.h:541
FBAnalyze::set_sids
uint32_t * set_sids
Definition: detect-flowbits.c:383
DetectEngineCtx_::max_fb_id
uint32_t max_fb_id
Definition: detect.h:851
Packet_
Definition: decode.h:428
detect-engine-build.h
DetectFlowbitsData_::idx
uint32_t idx
Definition: detect-flowbits.h:37
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:611
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1206
FBAnalyze::toggle_sids
uint32_t * toggle_sids
Definition: detect-flowbits.c:399
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:534
FBAnalyze::isset_sids_idx
uint32_t isset_sids_idx
Definition: detect-flowbits.c:388
detect-flowbits.h
SigMatchAlloc
SigMatch * SigMatchAlloc(void)
Definition: detect-parse.c:239
FlowBitToggle
void FlowBitToggle(Flow *f, uint32_t idx)
Definition: flow-bit.c:94
Flow_::flowvar
GenericVar * flowvar
Definition: flow.h:492
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:1951
FBAnalyze::unset_sids_idx
uint32_t unset_sids_idx
Definition: detect-flowbits.c:396
FBAnalyze::toggle_sids_size
uint32_t toggle_sids_size
Definition: detect-flowbits.c:401
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
SIG_FLAG_INIT_STATE_MATCH
#define SIG_FLAG_INIT_STATE_MATCH
Definition: detect.h:254
SigMatchCtx_
Used to start a pointer to SigMatch context Should never be dereferenced without casting to something...
Definition: detect.h:308
util-conf.h
Packet_::flow
struct Flow_ * flow
Definition: decode.h:465
DETECT_FLOWBITS_CMD_NOALERT
#define DETECT_FLOWBITS_CMD_NOALERT
Definition: detect-flowbits.h:33
DetectEngineThreadCtxInit
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
Definition: detect-engine.c:3153
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
VAR_TYPE_FLOW_BIT
@ VAR_TYPE_FLOW_BIT
Definition: util-var.h:35
FBAnalyze::state_cnts
uint16_t state_cnts[DETECT_FLOWBITS_CMD_MAX]
Definition: detect-flowbits.c:381
suricata-common.h
DetectEngineThreadCtxDeinit
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
Definition: detect-engine.c:3367
SigMatch_::type
uint16_t type
Definition: detect.h:314
GenericVar_
Definition: util-var.h:48
rule_engine_analysis_set
int rule_engine_analysis_set
Definition: detect-engine-loader.c:54
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:76
util-spm.h
VarNameStoreSetupAdd
uint32_t VarNameStoreSetupAdd(const char *name, const enum VarTypes type)
add to staging or return existing id if already in there
Definition: util-var-name.c:323
FBAnalyze::set_sids_idx
uint32_t set_sids_idx
Definition: detect-flowbits.c:384
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:791
SIG_FLAG_NOALERT
#define SIG_FLAG_NOALERT
Definition: detect.h:205
DETECT_FLOWBITS
@ DETECT_FLOWBITS
Definition: detect-engine-register.h:90
PacketGetFromAlloc
Packet * PacketGetFromAlloc(void)
Get a malloced packet.
Definition: decode.c:173
ConfigGetLogDirectory
const char * ConfigGetLogDirectory(void)
Definition: util-conf.c:37
FlowBitIsset
int FlowBitIsset(Flow *f, uint32_t idx)
Definition: flow-bit.c:104
str
#define str(s)
Definition: suricata-common.h:280
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
FBAnalyze::isset_sids_size
uint32_t isset_sids_size
Definition: detect-flowbits.c:389
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DetectFlowbitsData_::or_list
uint32_t * or_list
Definition: detect-flowbits.h:40
Signature_::id
uint32_t id
Definition: detect.h:574
DETECT_FLOWBITS_CMD_UNSET
#define DETECT_FLOWBITS_CMD_UNSET
Definition: detect-flowbits.h:30
detect-parse.h
Signature_
Signature container.
Definition: detect.h:540
SigMatch_
a single match condition for a signature
Definition: detect.h:313
FBAnalyze::isnotset_sids_size
uint32_t isnotset_sids_size
Definition: detect-flowbits.c:393
DetectEngineCtxInit
DetectEngineCtx * DetectEngineCtxInit(void)
Definition: detect-engine.c:2403
DetectFlowbitMatch
int DetectFlowbitMatch(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect-flowbits.c:192
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:800
Address_::family
char family
Definition: decode.h:115
Packet_::dst
Address dst
Definition: decode.h:433
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:786
flow.h
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DetectEngineCtx_::sig_array_len
uint32_t sig_array_len
Definition: detect.h:802
FBAnalyze
Definition: detect-flowbits.c:379
SIGMATCH_IPONLY_COMPAT
#define SIGMATCH_IPONLY_COMPAT
Definition: detect.h:1425
SCMutex
#define SCMutex
Definition: threads-debug.h:114
SigMatchAppendSMToList
void SigMatchAppendSMToList(Signature *s, SigMatch *new, int list)
Append a SigMatch to the list type.
Definition: detect-parse.c:354
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:129
Packet_::src
Address src
Definition: decode.h:432
FlowBitIsnotset
int FlowBitIsnotset(Flow *f, uint32_t idx)
Definition: flow-bit.c:116
DETECT_FLOWBITS_CMD_SET
#define DETECT_FLOWBITS_CMD_SET
Definition: detect-flowbits.h:28
SigTableElmt_::RegisterTests
void(* RegisterTests)(void)
Definition: detect.h:1230
SignatureInitData_::smlists_array_size
uint32_t smlists_array_size
Definition: detect.h:532