suricata
detect-engine-build.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2025 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 #include "suricata-common.h"
19 #include "detect.h"
20 #include "detect-engine.h"
21 #include "detect-parse.h"
22 #include "detect-content.h"
23 
24 #include "detect-engine-build.h"
25 #include "detect-engine-address.h"
26 #include "detect-engine-analyzer.h"
27 #include "detect-engine-iponly.h"
28 #include "detect-engine-mpm.h"
29 #include "detect-engine-siggroup.h"
30 #include "detect-engine-port.h"
32 #include "detect-engine-proto.h"
34 
35 #include "detect-dsize.h"
36 #include "detect-tcp-flags.h"
37 #include "detect-flow.h"
38 #include "detect-config.h"
39 #include "detect-flowbits.h"
40 
41 #include "app-layer-events.h"
42 
44 #include "util-profiling.h"
45 #include "util-validate.h"
46 #include "util-var-name.h"
47 #include "util-conf.h"
48 
49 /* Magic numbers to make the rules of a certain order fall in the same group */
50 #define DETECT_PGSCORE_RULE_PORT_PRIORITIZED 111 /* Rule port group contains a priority port */
51 #define DETECT_PGSCORE_RULE_MPM_FAST_PATTERN 99 /* Rule contains an MPM fast pattern */
52 #define DETECT_PGSCORE_RULE_MPM_NEGATED 77 /* Rule contains a negated MPM */
53 #define DETECT_PGSCORE_RULE_NO_MPM 55 /* Rule does not contain MPM */
54 #define DETECT_PGSCORE_RULE_SYN_ONLY 33 /* Rule needs SYN check */
55 
57 {
58  if (de_ctx == NULL)
59  return;
60 
61  for (Signature *s = de_ctx->sig_list; s != NULL;) {
62  Signature *ns = s->next;
63  SigFree(de_ctx, s);
64  s = ns;
65  }
66  de_ctx->sig_list = NULL;
67 
69  de_ctx->sig_list = NULL;
70 }
71 
72 /** \brief Find a specific signature by sid and gid
73  * \param de_ctx detection engine ctx
74  * \param sid the signature id
75  * \param gid the signature group id
76  *
77  * \retval s sig found
78  * \retval NULL sig not found
79  */
81 {
82  if (de_ctx == NULL)
83  return NULL;
84 
85  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
86  if (s->id == sid && s->gid == gid)
87  return s;
88  }
89 
90  return NULL;
91 }
92 
93 /**
94  * \brief Check if a signature contains the filestore keyword.
95  *
96  * \param s signature
97  *
98  * \retval 0 no
99  * \retval 1 yes
100  */
102 {
103  if (s == NULL)
104  return 0;
105 
106  if (s->flags & SIG_FLAG_FILESTORE)
107  return 1;
108 
109  return 0;
110 }
111 
112 /**
113  * \brief Check if a signature contains the filemagic keyword.
114  *
115  * \param s signature
116  *
117  * \retval 0 no
118  * \retval 1 yes
119  */
121 {
122  if (s == NULL)
123  return 0;
124 
126  return 1;
127 
128  return 0;
129 }
130 
131 /**
132  * \brief Check if a signature contains the filemd5 keyword.
133  *
134  * \param s signature
135  *
136  * \retval 0 no
137  * \retval 1 yes
138  */
140 {
141  if ((s != NULL) && (s->file_flags & FILE_SIG_NEED_MD5))
142  return 1;
143 
144  return 0;
145 }
146 
147 /**
148  * \brief Check if a signature contains the filesha1 keyword.
149  *
150  * \param s signature
151  *
152  * \retval 0 no
153  * \retval 1 yes
154  */
156 {
157  if ((s != NULL) && (s->file_flags & FILE_SIG_NEED_SHA1))
158  return 1;
159 
160  return 0;
161 }
162 
163 /**
164  * \brief Check if a signature contains the filesha256 keyword.
165  *
166  * \param s signature
167  *
168  * \retval 0 no
169  * \retval 1 yes
170  */
172 {
173  if ((s != NULL) && (s->file_flags & FILE_SIG_NEED_SHA256))
174  return 1;
175 
176  return 0;
177 }
178 
179 /**
180  * \brief Check if a signature contains the filesize keyword.
181  *
182  * \param s signature
183  *
184  * \retval 0 no
185  * \retval 1 yes
186  */
188 {
189  if (s == NULL)
190  return 0;
191 
193  return 1;
194 
195  return 0;
196 }
197 
198 static bool SignatureInspectsBuffers(const Signature *s)
199 {
200  return (s->init_data->buffer_index > 0);
201 }
202 
203 /** \brief Test is a initialized signature is IP only
204  * \param de_ctx detection engine ctx
205  * \param s the signature
206  * \retval 1 sig is ip only
207  * \retval 2 sig is like ip only
208  * \retval 0 sig is not ip only
209  */
211 {
212  /* explicit hook means no IP-only */
214  return 0;
215 
216  if (s->alproto != ALPROTO_UNKNOWN)
217  return 0;
218 
219  if (s->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL)
220  return 0;
221 
222  // may happen for 'config' keyword, postmatch
223  if (s->flags & SIG_FLAG_APPLAYER)
224  return 0;
225 
226  /* if flow dir is set we can't process it in ip-only */
227  if (!(((s->flags & (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)) == 0) ||
230  return 0;
231 
232  /* for now assume that all registered buffer types are incompatible */
233  if (SignatureInspectsBuffers(s)) {
234  SCReturnInt(0);
235  }
236 
237  /* TMATCH list can be ignored, it contains TAGs and
238  * tags are compatible to IP-only. */
239 
241  for (; sm != NULL; sm = sm->next) {
243  return 0;
244  /* we have enabled flowbits to be compatible with ip only sigs, as long
245  * as the sig only has a "set" flowbits */
246  if (sm->type == DETECT_FLOWBITS &&
247  (((DetectFlowbitsData *)sm->ctx)->cmd != DETECT_FLOWBITS_CMD_SET)) {
248  return 0;
249  }
250  }
252  for ( ; sm != NULL; sm = sm->next) {
254  return 0;
255  /* we have enabled flowbits to be compatible with ip only sigs, as long
256  * as the sig only has a "set" flowbits */
257  if (sm->type == DETECT_FLOWBITS &&
258  (((DetectFlowbitsData *)sm->ctx)->cmd != DETECT_FLOWBITS_CMD_SET) ) {
259  return 0;
260  }
261  }
262 
264  /* Rule is IP only, but contains negated addresses. */
265  return 2;
266  }
267  if (!(de_ctx->flags & DE_QUIET)) {
268  SCLogDebug("IP-ONLY (%" PRIu32 "): source %s, dest %s", s->id,
269  s->flags & SIG_FLAG_SRC_ANY ? "ANY" : "SET",
270  s->flags & SIG_FLAG_DST_ANY ? "ANY" : "SET");
271  }
272  return 1;
273 }
274 
275 /** \internal
276  * \brief Test is a initialized signature is inspecting protocol detection only
277  * \param de_ctx detection engine ctx
278  * \param s the signature
279  * \retval 1 sig is dp only
280  * \retval 0 sig is not dp only
281  */
282 static int SignatureIsPDOnly(const DetectEngineCtx *de_ctx, const Signature *s)
283 {
284  /* explicit hook means no PD-only */
286  return 0;
287 
288  if (s->alproto != ALPROTO_UNKNOWN)
289  return 0;
290 
291  if (s->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL)
292  return 0;
293 
294  /* for now assume that all registered buffer types are incompatible */
295  if (SignatureInspectsBuffers(s)) {
296  SCReturnInt(0);
297  }
298 
299  /* TMATCH list can be ignored, it contains TAGs and
300  * tags are compatible to DP-only. */
301 
302  /* match list matches may be compatible to DP only. We follow the same
303  * logic as IP-only so we can use that flag */
304 
306  if (sm == NULL)
307  return 0;
308 
309  int pd = 0;
310  for ( ; sm != NULL; sm = sm->next) {
311  if (sm->type == DETECT_APP_LAYER_PROTOCOL) {
312  pd = 1;
313  } else {
314  /* flowbits are supported for dp only sigs, as long
315  * as the sig only has a "set" flowbits */
316  if (sm->type == DETECT_FLOWBITS) {
317  if ((((DetectFlowbitsData *)sm->ctx)->cmd != DETECT_FLOWBITS_CMD_SET) ) {
318  SCLogDebug("%u: not PD-only: flowbit settings other than 'set'", s->id);
319  return 0;
320  }
321  } else if (sm->type == DETECT_FLOW) {
323  SCLogDebug("%u: not PD-only: flow settings other than toserver/toclient", s->id);
324  return 0;
325  }
326  } else if ( !(sigmatch_table[sm->type].flags & SIGMATCH_IPONLY_COMPAT)) {
327  SCLogDebug("%u: not PD-only: %s not PD/IP-only compat", s->id, sigmatch_table[sm->type].name);
328  return 0;
329  }
330  }
331  }
332 
333  if (pd) {
334  SCLogDebug("PD-ONLY (%" PRIu32 ")", s->id);
335  }
336  return pd;
337 }
338 
339 /**
340  * \internal
341  * \brief Check if the initialized signature is inspecting the packet payload
342  * \param de_ctx detection engine ctx
343  * \param s the signature
344  * \retval 1 sig is inspecting the payload
345  * \retval 0 sig is not inspecting the payload
346  */
347 static int SignatureIsInspectingPayload(DetectEngineCtx *de_ctx, const Signature *s)
348 {
349 
350  if (s->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL) {
351  return 1;
352  }
353  return 0;
354 }
355 
356 /**
357  * \internal
358  * \brief check if a signature is decoder event matching only
359  * \param de_ctx detection engine
360  * \param s the signature to test
361  * \retval 0 not a DEOnly sig
362  * \retval 1 DEOnly sig
363  */
364 static int SignatureIsDEOnly(DetectEngineCtx *de_ctx, const Signature *s)
365 {
366  /* explicit hook means no DE-only */
368  SCReturnInt(0);
369 
370  if (s->alproto != ALPROTO_UNKNOWN) {
371  SCReturnInt(0);
372  }
373 
374  if (s->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL)
375  {
376  SCReturnInt(0);
377  }
378 
379  /* for now assume that all registered buffer types are incompatible */
380  if (SignatureInspectsBuffers(s)) {
381  SCReturnInt(0);
382  }
383 
384  /* check for conflicting keywords */
386  for ( ;sm != NULL; sm = sm->next) {
388  SCReturnInt(0);
389  }
390 
391  /* need at least one decode event keyword to be considered decode event. */
393  for ( ;sm != NULL; sm = sm->next) {
394  if (sm->type == DETECT_DECODE_EVENT)
395  goto deonly;
396  if (sm->type == DETECT_ENGINE_EVENT)
397  goto deonly;
398  if (sm->type == DETECT_STREAM_EVENT)
399  goto deonly;
400  }
401 
402  SCReturnInt(0);
403 
404 deonly:
405  if (!(de_ctx->flags & DE_QUIET)) {
406  SCLogDebug("DE-ONLY (%" PRIu32 "): source %s, dest %s", s->id,
407  s->flags & SIG_FLAG_SRC_ANY ? "ANY" : "SET",
408  s->flags & SIG_FLAG_DST_ANY ? "ANY" : "SET");
409  }
410 
411  SCReturnInt(1);
412 }
413 
414 #define MASK_TCP_INITDEINIT_FLAGS (TH_SYN|TH_RST|TH_FIN)
415 #define MASK_TCP_UNUSUAL_FLAGS (TH_URG|TH_ECN|TH_CWR)
416 
417 /* Create mask for this packet + it's flow if it has one
418  */
419 void
421  bool app_decoder_events)
422 {
423  if (!(PKT_IS_PSEUDOPKT(p))) {
424  (*mask) |= SIG_MASK_REQUIRE_REAL_PKT;
425  }
426  if (!(p->flags & PKT_NOPAYLOAD_INSPECTION) && p->payload_len > 0) {
427  SCLogDebug("packet has payload");
428  (*mask) |= SIG_MASK_REQUIRE_PAYLOAD;
429  } else if (p->flags & PKT_DETECT_HAS_STREAMDATA) {
430  SCLogDebug("stream data available");
431  (*mask) |= SIG_MASK_REQUIRE_PAYLOAD;
432  } else {
433  SCLogDebug("packet has no payload");
434  (*mask) |= SIG_MASK_REQUIRE_NO_PAYLOAD;
435  }
436 
437  if (p->events.cnt > 0 || app_decoder_events != 0 ||
438  (p->app_layer_events != NULL && p->app_layer_events->cnt)) {
439  SCLogDebug("packet/flow has events set");
441  }
442 
443  if (!(PKT_IS_PSEUDOPKT(p)) && PacketIsTCP(p)) {
444  const TCPHdr *tcph = PacketGetTCP(p);
445  if ((tcph->th_flags & MASK_TCP_INITDEINIT_FLAGS) != 0) {
447  }
448  if ((tcph->th_flags & MASK_TCP_UNUSUAL_FLAGS) != 0) {
450  }
451  }
452 
453  if (p->flags & PKT_HAS_FLOW) {
454  SCLogDebug("packet has flow");
455  (*mask) |= SIG_MASK_REQUIRE_FLOW;
456  }
457 }
458 
459 static int SignatureCreateMask(Signature *s)
460 {
461  SCEnter();
462 
466  }
467  if (s->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL) {
469  SCLogDebug("sig requires payload");
470  }
471 
472  SigMatch *sm;
473  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
474  switch(sm->type) {
475  case DETECT_FLOWBITS:
476  {
477  /* figure out what flowbit action */
479  if (fb->cmd == DETECT_FLOWBITS_CMD_ISSET) {
480  /* not a mask flag, but still set it here */
482 
483  SCLogDebug("SIG_FLAG_REQUIRE_FLOWVAR set as sig has "
484  "flowbit isset option.");
485  }
486 
487  /* flow is required for any flowbit manipulation */
489  SCLogDebug("sig requires flow to be able to manipulate "
490  "flowbit(s)");
491  break;
492  }
493  case DETECT_FLOWINT:
494  /* flow is required for any flowint manipulation */
496  SCLogDebug("sig requires flow to be able to manipulate "
497  "flowint(s)");
498  break;
499  case DETECT_FLAGS:
500  {
501  DetectFlagsData *fl = (DetectFlagsData *)sm->ctx;
502 
503  if (fl->flags & MASK_TCP_INITDEINIT_FLAGS) {
505  SCLogDebug("sig requires SIG_MASK_REQUIRE_FLAGS_INITDEINIT");
506  }
507  if (fl->flags & MASK_TCP_UNUSUAL_FLAGS) {
509  SCLogDebug("sig requires SIG_MASK_REQUIRE_FLAGS_UNUSUAL");
510  }
511  break;
512  }
513  case DETECT_DSIZE:
514  {
515  DetectU16Data *ds = (DetectU16Data *)sm->ctx;
516  /* LT will include 0, so no payload.
517  * if GT is used in the same rule the
518  * flag will be set anyway. */
519  if (ds->mode == DETECT_UINT_RA || ds->mode == DETECT_UINT_GT ||
520  ds->mode == DETECT_UINT_NE || ds->mode == DETECT_UINT_GTE) {
521 
523  SCLogDebug("sig requires payload");
524 
525  } else if (ds->mode == DETECT_UINT_EQ) {
526  if (ds->arg1 > 0) {
528  SCLogDebug("sig requires payload");
529  } else {
531  SCLogDebug("sig requires no payload");
532  }
533  }
534  break;
535  }
536  case DETECT_DECODE_EVENT:
537  // fallthrough
538  case DETECT_STREAM_EVENT:
539  // fallthrough
541  // fallthrough
542  case DETECT_ENGINE_EVENT:
544  break;
545  }
546  }
547 
548  for (sm = s->init_data->smlists[DETECT_SM_LIST_POSTMATCH]; sm != NULL; sm = sm->next) {
549  switch (sm->type) {
550  case DETECT_CONFIG: {
552  if (fd->scope == CONFIG_SCOPE_FLOW) {
554  }
555  break;
556  }
557  }
558  }
559 
562  SCLogDebug("sig requires flow");
563  }
564 
565  if (s->flags & SIG_FLAG_APPLAYER) {
567  SCLogDebug("sig requires flow");
568  }
569 
570  SCLogDebug("mask %02X", s->mask);
571  SCReturnInt(0);
572 }
573 
574 static void SigInitStandardMpmFactoryContexts(DetectEngineCtx *de_ctx)
575 {
577 }
578 
579 /** \brief Pure-PCRE or bytetest rule */
580 static bool RuleInspectsPayloadHasNoMpm(const Signature *s)
581 {
582  if (s->init_data->mpm_sm == NULL && s->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL)
583  return true;
584  return false;
585 }
586 
587 static int RuleGetMpmPatternSize(const Signature *s)
588 {
589  if (s->init_data->mpm_sm == NULL)
590  return -1;
591  int mpm_list = s->init_data->mpm_sm_list;
592  if (mpm_list < 0)
593  return -1;
594  const DetectContentData *cd = (const DetectContentData *)s->init_data->mpm_sm->ctx;
595  if (cd == NULL)
596  return -1;
597  return (int)cd->content_len;
598 }
599 
600 static bool RuleMpmIsNegated(const Signature *s)
601 {
602  if (s->flags & SIG_FLAG_MPM_NEG)
603  return true;
604  if (s->init_data->mpm_sm == NULL)
605  return false;
606  int mpm_list = s->init_data->mpm_sm_list;
607  if (mpm_list < 0)
608  return false;
609  const DetectContentData *cd = (const DetectContentData *)s->init_data->mpm_sm->ctx;
610  if (cd == NULL)
611  return false;
612  return (cd->flags & DETECT_CONTENT_NEGATED) ? true : false;
613 }
614 
615 static SCJsonBuilder *RulesGroupPrintSghStats(const DetectEngineCtx *de_ctx,
616  const SigGroupHead *sgh, const int add_rules, const int add_mpm_stats)
617 {
618  uint32_t prefilter_cnt = 0;
619  uint32_t mpm_cnt = 0;
620  uint32_t nonmpm_cnt = 0;
621  uint32_t mpm_depth_cnt = 0;
622  uint32_t mpm_endswith_cnt = 0;
623  uint32_t negmpm_cnt = 0;
624  uint32_t any5_cnt = 0;
625  uint32_t payload_no_mpm_cnt = 0;
626  uint32_t syn_cnt = 0;
627 
628  uint32_t mpms_min = 0;
629  uint32_t mpms_max = 0;
630 
631  int max_buffer_type_id = de_ctx->buffer_type_id;
632 
633  struct {
634  uint32_t total;
635  uint32_t cnt;
636  uint32_t min;
637  uint32_t max;
638  } mpm_stats[max_buffer_type_id];
639  memset(mpm_stats, 0x00, sizeof(mpm_stats));
640 
641  uint32_t alstats[g_alproto_max];
642  memset(alstats, 0, g_alproto_max * sizeof(uint32_t));
643  uint32_t mpm_sizes[max_buffer_type_id][256];
644  memset(mpm_sizes, 0, sizeof(mpm_sizes));
645  uint32_t alproto_mpm_bufs[g_alproto_max][max_buffer_type_id];
646  memset(alproto_mpm_bufs, 0, sizeof(alproto_mpm_bufs));
647 
648  DEBUG_VALIDATE_BUG_ON(sgh->init == NULL);
649  if (sgh->init == NULL)
650  return NULL;
651 
652  SCJsonBuilder *js = SCJbNewObject();
653  if (unlikely(js == NULL))
654  return NULL;
655 
656  SCJbSetUint(js, "id", sgh->id);
657 
658  SCJbOpenArray(js, "rules");
659  for (uint32_t x = 0; x < sgh->init->sig_cnt; x++) {
660  const Signature *s = sgh->init->match_array[x];
661  if (s == NULL)
662  continue;
663 
664  int any = 0;
665  if (s->proto.flags & DETECT_PROTO_ANY) {
666  any++;
667  }
668  if (s->flags & SIG_FLAG_DST_ANY) {
669  any++;
670  }
671  if (s->flags & SIG_FLAG_SRC_ANY) {
672  any++;
673  }
674  if (s->flags & SIG_FLAG_DP_ANY) {
675  any++;
676  }
677  if (s->flags & SIG_FLAG_SP_ANY) {
678  any++;
679  }
680  if (any == 5) {
681  any5_cnt++;
682  }
683 
684  prefilter_cnt += (s->init_data->prefilter_sm != NULL);
685  if (s->init_data->mpm_sm == NULL) {
686  nonmpm_cnt++;
687 
688  if (s->sm_arrays[DETECT_SM_LIST_MATCH] != NULL) {
689  SCLogDebug("SGH %p Non-MPM inspecting only packets. Rule %u", sgh, s->id);
690  }
691 
692  DetectPort *sp = s->sp;
693  DetectPort *dp = s->dp;
694 
695  if (s->flags & SIG_FLAG_TOSERVER && (dp->port == 0 && dp->port2 == 65535)) {
696  SCLogDebug("SGH %p Non-MPM toserver and to 'any'. Rule %u", sgh, s->id);
697  }
698  if (s->flags & SIG_FLAG_TOCLIENT && (sp->port == 0 && sp->port2 == 65535)) {
699  SCLogDebug("SGH %p Non-MPM toclient and to 'any'. Rule %u", sgh, s->id);
700  }
701 
703  syn_cnt++;
704  }
705 
706  } else {
707  int mpm_list = s->init_data->mpm_sm_list;
708  BUG_ON(mpm_list < 0);
709  const DetectContentData *cd = (const DetectContentData *)s->init_data->mpm_sm->ctx;
710  uint32_t size = cd->content_len < 256 ? cd->content_len : 255;
711 
712  mpm_sizes[mpm_list][size]++;
713  alproto_mpm_bufs[s->alproto][mpm_list]++;
714 
715  if (mpm_list == DETECT_SM_LIST_PMATCH) {
716  if (size == 1) {
717  DetectPort *sp = s->sp;
718  DetectPort *dp = s->dp;
719  if (s->flags & SIG_FLAG_TOSERVER) {
720  if (dp->port == 0 && dp->port2 == 65535) {
721  SCLogDebug("SGH %p toserver 1byte fast_pattern to ANY. Rule %u", sgh, s->id);
722  } else {
723  SCLogDebug("SGH %p toserver 1byte fast_pattern to port(s) %u-%u. Rule %u", sgh, dp->port, dp->port2, s->id);
724  }
725  }
726  if (s->flags & SIG_FLAG_TOCLIENT) {
727  if (sp->port == 0 && sp->port2 == 65535) {
728  SCLogDebug("SGH %p toclient 1byte fast_pattern to ANY. Rule %u", sgh, s->id);
729  } else {
730  SCLogDebug("SGH %p toclient 1byte fast_pattern to port(s) %u-%u. Rule %u", sgh, sp->port, sp->port2, s->id);
731  }
732  }
733  }
734  }
735 
736  uint32_t w = PatternStrength(cd->content, cd->content_len);
737  if (mpms_min == 0)
738  mpms_min = w;
739  if (w < mpms_min)
740  mpms_min = w;
741  if (w > mpms_max)
742  mpms_max = w;
743 
744  BUG_ON(mpm_list >= max_buffer_type_id);
745  mpm_stats[mpm_list].total += w;
746  mpm_stats[mpm_list].cnt++;
747  if (mpm_stats[mpm_list].min == 0 || w < mpm_stats[mpm_list].min)
748  mpm_stats[mpm_list].min = w;
749  if (w > mpm_stats[mpm_list].max)
750  mpm_stats[mpm_list].max = w;
751 
752  mpm_cnt++;
753 
754  if (w < 10) {
755  SCLogDebug("SGH %p Weak MPM Pattern on %s. Rule %u", sgh, DetectListToString(mpm_list), s->id);
756  }
757  if (w < 10 && any == 5) {
758  SCLogDebug("SGH %p Weak MPM Pattern on %s, rule is 5xAny. Rule %u", sgh, DetectListToString(mpm_list), s->id);
759  }
760 
761  if (cd->flags & DETECT_CONTENT_NEGATED) {
762  SCLogDebug("SGH %p MPM Pattern on %s, is negated. Rule %u", sgh, DetectListToString(mpm_list), s->id);
763  negmpm_cnt++;
764  }
765  if (cd->flags & DETECT_CONTENT_ENDS_WITH) {
766  mpm_endswith_cnt++;
767  }
768  if (cd->flags & DETECT_CONTENT_DEPTH) {
769  mpm_depth_cnt++;
770  }
771  }
772 
773  if (RuleInspectsPayloadHasNoMpm(s)) {
774  SCLogDebug("SGH %p No MPM. Payload inspecting. Rule %u", sgh, s->id);
775  payload_no_mpm_cnt++;
776  }
777 
778  alstats[s->alproto]++;
779 
780  if (add_rules) {
781  SCJsonBuilder *e = SCJbNewObject();
782  if (e != NULL) {
783  SCJbSetUint(e, "sig_id", s->id);
784  SCJbClose(e);
785  SCJbAppendObject(js, e);
786  SCJbFree(e);
787  }
788  }
789  }
790  SCJbClose(js);
791 
792  SCJbOpenObject(js, "stats");
793  SCJbSetUint(js, "total", sgh->init->sig_cnt);
794 
795  SCJbOpenObject(js, "types");
796  SCJbSetUint(js, "mpm", mpm_cnt);
797  SCJbSetUint(js, "non_mpm", nonmpm_cnt);
798  SCJbSetUint(js, "mpm_depth", mpm_depth_cnt);
799  SCJbSetUint(js, "mpm_endswith", mpm_endswith_cnt);
800  SCJbSetUint(js, "negated_mpm", negmpm_cnt);
801  SCJbSetUint(js, "payload_but_no_mpm", payload_no_mpm_cnt);
802  SCJbSetUint(js, "prefilter", prefilter_cnt);
803  SCJbSetUint(js, "syn", syn_cnt);
804  SCJbSetUint(js, "any5", any5_cnt);
805  SCJbClose(js);
806 
807  for (AppProto i = 0; i < g_alproto_max; i++) {
808  if (alstats[i] > 0) {
809  const char *proto_name = (i == ALPROTO_UNKNOWN) ? "payload" : AppProtoToString(i);
810  SCJbOpenObject(js, proto_name);
811  SCJbSetUint(js, "total", alstats[i]);
812 
813  for (int y = 0; y < max_buffer_type_id; y++) {
814  if (alproto_mpm_bufs[i][y] == 0)
815  continue;
816 
817  const char *name;
820  else
822 
823  SCJbSetUint(js, name, alproto_mpm_bufs[i][y]);
824  }
825  SCJbClose(js);
826  }
827  }
828 
829  if (add_mpm_stats) {
830  SCJbOpenObject(js, "mpm");
831 
832  for (int i = 0; i < max_buffer_type_id; i++) {
833  if (mpm_stats[i].cnt > 0) {
834  const char *name;
837  else
839 
840  SCJbOpenArray(js, name);
841 
842  for (int y = 0; y < 256; y++) {
843  if (mpm_sizes[i][y] == 0)
844  continue;
845 
846  SCJsonBuilder *e = SCJbNewObject();
847  if (e != NULL) {
848  SCJbSetUint(e, "size", y);
849  SCJbSetUint(e, "count", mpm_sizes[i][y]);
850  SCJbClose(e);
851  SCJbAppendObject(js, e);
852  SCJbFree(e);
853  }
854  }
855 
856  SCJsonBuilder *e = SCJbNewObject();
857  if (e != NULL) {
858  SCJbSetUint(e, "total", mpm_stats[i].cnt);
859  SCJbSetUint(e, "avg_strength", mpm_stats[i].total / mpm_stats[i].cnt);
860  SCJbSetUint(e, "min_strength", mpm_stats[i].min);
861  SCJbSetUint(e, "max_strength", mpm_stats[i].max);
862  SCJbClose(e);
863  SCJbAppendObject(js, e);
864  SCJbFree(e);
865  }
866 
867  SCJbClose(js);
868  }
869  }
870  SCJbClose(js);
871  }
872  SCJbClose(js);
873 
874  SCJbSetUint(js, "score", sgh->init->score);
875  SCJbClose(js);
876 
877  return js;
878 }
879 
880 static void RulesDumpGrouping(const DetectEngineCtx *de_ctx,
881  const int add_rules, const int add_mpm_stats)
882 {
883  SCJsonBuilder *js = SCJbNewObject();
884  if (unlikely(js == NULL))
885  return;
886 
887  for (int p = 0; p < 256; p++) {
888  if (p == IPPROTO_TCP || p == IPPROTO_UDP) {
889  const char *name = (p == IPPROTO_TCP) ? "tcp" : "udp";
890 
891  SCJbOpenObject(js, name);
892  SCJbOpenArray(js, "toserver");
893  const DetectPort *list =
894  (p == IPPROTO_TCP) ? de_ctx->flow_gh[1].tcp : de_ctx->flow_gh[1].udp;
895  while (list != NULL) {
896  SCJsonBuilder *port = SCJbNewObject();
897  SCJbSetUint(port, "port", list->port);
898  SCJbSetUint(port, "port2", list->port2);
899 
900  SCJsonBuilder *stats =
901  RulesGroupPrintSghStats(de_ctx, list->sh, add_rules, add_mpm_stats);
902  SCJbSetObject(port, "rulegroup", stats);
903  SCJbFree(stats);
904  SCJbClose(port);
905  SCJbAppendObject(js, port);
906  SCJbFree(port);
907 
908  list = list->next;
909  }
910  SCJbClose(js); // toserver array
911 
912  SCJbOpenArray(js, "toclient");
913  list = (p == IPPROTO_TCP) ? de_ctx->flow_gh[0].tcp :
914  de_ctx->flow_gh[0].udp;
915  while (list != NULL) {
916  SCJsonBuilder *port = SCJbNewObject();
917  SCJbSetUint(port, "port", list->port);
918  SCJbSetUint(port, "port2", list->port2);
919 
920  SCJsonBuilder *stats =
921  RulesGroupPrintSghStats(de_ctx, list->sh, add_rules, add_mpm_stats);
922  SCJbSetObject(port, "rulegroup", stats);
923  SCJbFree(stats);
924  SCJbClose(port);
925  SCJbAppendObject(js, port);
926  SCJbFree(port);
927 
928  list = list->next;
929  }
930  SCJbClose(js); // toclient array
931  SCJbClose(js);
932  } else if (p == IPPROTO_ICMP || p == IPPROTO_ICMPV6) {
933  const char *name = (p == IPPROTO_ICMP) ? "icmpv4" : "icmpv6";
934  SCJbOpenObject(js, name);
935  if (de_ctx->flow_gh[1].sgh[p]) {
936  SCJbOpenObject(js, "toserver");
937  SCJsonBuilder *stats = RulesGroupPrintSghStats(
938  de_ctx, de_ctx->flow_gh[1].sgh[p], add_rules, add_mpm_stats);
939  SCJbSetObject(js, "rulegroup", stats);
940  SCJbFree(stats);
941  SCJbClose(js);
942  }
943  if (de_ctx->flow_gh[0].sgh[p]) {
944  SCJbOpenObject(js, "toclient");
945  SCJsonBuilder *stats = RulesGroupPrintSghStats(
946  de_ctx, de_ctx->flow_gh[0].sgh[p], add_rules, add_mpm_stats);
947  SCJbSetObject(js, "rulegroup", stats);
948  SCJbFree(stats);
949  SCJbClose(js);
950  }
951  SCJbClose(js);
952  }
953  }
954  SCJbClose(js);
955 
956  const char *filename = "rule_group.json";
957  const char *log_dir = SCConfigGetLogDirectory();
958  char log_path[PATH_MAX] = "";
959  snprintf(log_path, sizeof(log_path), "%s/%s", log_dir, filename);
960 
961  FILE *fp = fopen(log_path, "w");
962  if (fp != NULL) {
963  fwrite(SCJbPtr(js), SCJbLen(js), 1, fp);
964  (void)fclose(fp);
965  }
966  SCJbFree(js);
967 }
968 
969 static int RulesGroupByIPProto(DetectEngineCtx *de_ctx)
970 {
971  Signature *s = de_ctx->sig_list;
972 
973  SigGroupHead *sgh_ts[256] = {NULL};
974  SigGroupHead *sgh_tc[256] = {NULL};
975 
976  for ( ; s != NULL; s = s->next) {
977  if (s->type == SIG_TYPE_IPONLY)
978  continue;
979 
980  /* traverse over IP protocol list from libc */
981  for (int p = 0; p < 256; p++) {
982  if (p == IPPROTO_TCP || p == IPPROTO_UDP) {
983  continue;
984  }
985  if (!(s->proto.proto[p / 8] & (1<<(p % 8)) || (s->proto.flags & DETECT_PROTO_ANY))) {
986  continue;
987  }
988 
989  /* Signatures that are ICMP, SCTP, not IP only are handled here */
990  if (s->flags & SIG_FLAG_TOCLIENT) {
991  SigGroupHeadAppendSig(de_ctx, &sgh_tc[p], s);
992  }
993  if (s->flags & SIG_FLAG_TOSERVER) {
994  SigGroupHeadAppendSig(de_ctx, &sgh_ts[p], s);
995  }
996  }
997  }
998 
999  /* lets look at deduplicating this list */
1002 
1003  uint32_t cnt = 0;
1004  uint32_t own = 0;
1005  uint32_t ref = 0;
1006  int p;
1007  for (p = 0; p < 256; p++) {
1008  if (p == IPPROTO_TCP || p == IPPROTO_UDP)
1009  continue;
1010  if (sgh_ts[p] == NULL)
1011  continue;
1012 
1013  cnt++;
1014 
1015  SigGroupHead *lookup_sgh = SigGroupHeadHashLookup(de_ctx, sgh_ts[p]);
1016  if (lookup_sgh == NULL) {
1017  SCLogDebug("proto group %d sgh %p is the original", p, sgh_ts[p]);
1018 
1019  SigGroupHeadSetSigCnt(sgh_ts[p], 0);
1020  SigGroupHeadBuildMatchArray(de_ctx, sgh_ts[p], 0);
1021 
1022  SigGroupHeadHashAdd(de_ctx, sgh_ts[p]);
1023  SigGroupHeadStore(de_ctx, sgh_ts[p]);
1024  own++;
1025  } else {
1026  SCLogDebug("proto group %d sgh %p is a copy", p, sgh_ts[p]);
1027 
1028  SigGroupHeadFree(de_ctx, sgh_ts[p]);
1029  sgh_ts[p] = lookup_sgh;
1030  ref++;
1031  }
1032  }
1033  SCLogPerf("OTHER %s: %u proto groups, %u unique SGH's, %u copies",
1034  "toserver", cnt, own, ref);
1035 
1036  cnt = 0;
1037  own = 0;
1038  ref = 0;
1039  for (p = 0; p < 256; p++) {
1040  if (p == IPPROTO_TCP || p == IPPROTO_UDP)
1041  continue;
1042  if (sgh_tc[p] == NULL)
1043  continue;
1044 
1045  cnt++;
1046 
1047  SigGroupHead *lookup_sgh = SigGroupHeadHashLookup(de_ctx, sgh_tc[p]);
1048  if (lookup_sgh == NULL) {
1049  SCLogDebug("proto group %d sgh %p is the original", p, sgh_tc[p]);
1050 
1051  SigGroupHeadSetSigCnt(sgh_tc[p], 0);
1052  SigGroupHeadBuildMatchArray(de_ctx, sgh_tc[p], 0);
1053 
1054  SigGroupHeadHashAdd(de_ctx, sgh_tc[p]);
1055  SigGroupHeadStore(de_ctx, sgh_tc[p]);
1056  own++;
1057 
1058  } else {
1059  SCLogDebug("proto group %d sgh %p is a copy", p, sgh_tc[p]);
1060 
1061  SigGroupHeadFree(de_ctx, sgh_tc[p]);
1062  sgh_tc[p] = lookup_sgh;
1063  ref++;
1064  }
1065  }
1066  SCLogPerf("OTHER %s: %u proto groups, %u unique SGH's, %u copies",
1067  "toclient", cnt, own, ref);
1068 
1069  for (p = 0; p < 256; p++) {
1070  if (p == IPPROTO_TCP || p == IPPROTO_UDP)
1071  continue;
1072 
1073  de_ctx->flow_gh[0].sgh[p] = sgh_tc[p];
1074  de_ctx->flow_gh[1].sgh[p] = sgh_ts[p];
1075  }
1076 
1077  return 0;
1078 }
1079 
1080 static int PortIsPriority(const DetectEngineCtx *de_ctx, const DetectPort *a, int ipproto)
1081 {
1083  if (ipproto == IPPROTO_UDP)
1085 
1086  while (w) {
1087  /* Make sure the priority port falls in the port range of a */
1088  DEBUG_VALIDATE_BUG_ON(a->port > a->port2);
1089  if (a->port == w->port && w->port2 == a->port2) {
1090  return 1;
1091  }
1092  w = w->next;
1093  }
1094 
1095  return 0;
1096 }
1097 
1098 static int RuleSetScore(Signature *s)
1099 {
1100  DetectPort *p = NULL;
1101  if (s->flags & SIG_FLAG_TOSERVER)
1102  p = s->dp;
1103  else if (s->flags & SIG_FLAG_TOCLIENT)
1104  p = s->sp;
1105  else
1106  return 0;
1107 
1108  /* for sigs that don't use 'any' as port, see if we want to
1109  * prioritize poor sigs */
1110  int wl = 0;
1111  if (!(p->port == 0 && p->port2 == 65535)) {
1112  /* pure pcre, bytetest, etc rules */
1113  if (RuleInspectsPayloadHasNoMpm(s)) {
1114  SCLogDebug("Rule %u MPM has 1 byte fast_pattern. Prioritizing SGH's.", s->id);
1116 
1117  } else if (RuleMpmIsNegated(s)) {
1118  SCLogDebug("Rule %u MPM is negated. Prioritizing SGH's.", s->id);
1120 
1121  /* one byte pattern in packet/stream payloads */
1122  } else if (s->init_data->mpm_sm != NULL &&
1124  RuleGetMpmPatternSize(s) == 1) {
1125  SCLogDebug("Rule %u No MPM. Payload inspecting. Prioritizing SGH's.", s->id);
1127 
1129  SCLogDebug("Rule %u Needs SYN, so inspected often. Prioritizing SGH's.", s->id);
1131  }
1132  }
1133 
1134  s->init_data->score = wl;
1135  return wl;
1136 }
1137 
1138 static int SortCompare(const void *a, const void *b)
1139 {
1140  const DetectPort *pa = *(const DetectPort **)a;
1141  const DetectPort *pb = *(const DetectPort **)b;
1142 
1143  if (pa->sh->init->score < pb->sh->init->score) {
1144  return 1;
1145  } else if (pa->sh->init->score > pb->sh->init->score) {
1146  return -1;
1147  }
1148 
1149  if (pa->sh->init->sig_cnt < pb->sh->init->sig_cnt) {
1150  return 1;
1151  } else if (pa->sh->init->sig_cnt > pb->sh->init->sig_cnt) {
1152  return -1;
1153  }
1154 
1155  /* Hack to make the qsort output deterministic across platforms.
1156  * This had to be done because the order of equal elements sorted
1157  * by qsort is undeterministic and showed different output on BSD,
1158  * MacOS and Windows. Sorting based on id makes it deterministic. */
1159  if (pa->sh->id < pb->sh->id)
1160  return -1;
1161 
1162  return 1;
1163 }
1164 
1165 static inline void SortGroupList(
1166  uint32_t *groups, DetectPort **list, int (*CompareFunc)(const void *, const void *))
1167 {
1168  int cnt = 0;
1169  for (DetectPort *x = *list; x != NULL; x = x->next) {
1170  DEBUG_VALIDATE_BUG_ON(x->port > x->port2);
1171  cnt++;
1172  }
1173  if (cnt <= 1)
1174  return;
1175 
1176  /* build temporary array to sort with qsort */
1177  DetectPort **array = (DetectPort **)SCCalloc(cnt, sizeof(DetectPort *));
1178  if (array == NULL)
1179  return;
1180 
1181  int idx = 0;
1182  for (DetectPort *x = *list; x != NULL;) {
1183  /* assign a temporary id to resolve otherwise equal groups */
1184  x->sh->id = idx + 1;
1185  SigGroupHeadSetSigCnt(x->sh, 0);
1186  DetectPort *next = x->next;
1187  x->next = x->prev = x->last = NULL;
1188  DEBUG_VALIDATE_BUG_ON(x->port > x->port2);
1189  array[idx++] = x;
1190  x = next;
1191  }
1192  DEBUG_VALIDATE_BUG_ON(cnt != idx);
1193 
1194  qsort(array, idx, sizeof(DetectPort *), SortCompare);
1195 
1196  /* rebuild the list based on the qsort-ed array */
1197  DetectPort *new_list = NULL, *tail = NULL;
1198  for (int i = 0; i < idx; i++) {
1199  DetectPort *p = array[i];
1200  /* unset temporary group id */
1201  p->sh->id = 0;
1202 
1203  if (new_list == NULL) {
1204  new_list = p;
1205  }
1206  if (tail != NULL) {
1207  tail->next = p;
1208  }
1209  p->prev = tail;
1210  tail = p;
1211  }
1212 
1213  *list = new_list;
1214  *groups = idx;
1215 
1216 #if DEBUG
1217  int dbgcnt = 0;
1218  SCLogDebug("SORTED LIST:");
1219  for (DetectPort *tmp = *list; tmp != NULL; tmp = tmp->next) {
1220  SCLogDebug("item:= [%u:%u]; score: %d; sig_cnt: %d", tmp->port, tmp->port2,
1221  tmp->sh->init->score, tmp->sh->init->sig_cnt);
1222  dbgcnt++;
1223  BUG_ON(dbgcnt > cnt);
1224  }
1225 #endif
1226  SCFree(array);
1227 }
1228 /** \internal
1229  * \brief Create a list of DetectPort objects sorted based on CompareFunc's
1230  * logic.
1231  *
1232  * List can limit the number of groups. In this case an extra "join" group
1233  * is created that contains the sigs belonging to that. It's *appended* to
1234  * the list, meaning that if the list is walked linearly it's found last.
1235  * The joingr is meant to be a catch all.
1236  *
1237  */
1238 static int CreateGroupedPortList(DetectEngineCtx *de_ctx, DetectPort *port_list,
1239  DetectPort **newhead, uint32_t unique_groups,
1240  int (*CompareFunc)(const void *, const void *))
1241 {
1242  DetectPort *tmplist = NULL, *joingr = NULL;
1243  uint32_t groups = 0;
1244 
1245  /* insert the ports into the tmplist, where it will
1246  * be sorted descending on 'cnt' and on whether a group
1247  * is prioritized. */
1248  tmplist = port_list;
1249  SortGroupList(&groups, &tmplist, SortCompare);
1250  uint32_t left = unique_groups;
1251  if (left == 0)
1252  left = groups;
1253 
1254  /* create another list: take the port groups from above
1255  * and add them to the 2nd list until we have met our
1256  * count. The rest is added to the 'join' group. */
1257  DetectPort *tmplist2 = NULL, *tmplist2_tail = NULL;
1258  DetectPort *gr, *next_gr;
1259  for (gr = tmplist; gr != NULL;) {
1260  next_gr = gr->next;
1261 
1262  SCLogDebug("temp list gr %p %u:%u", gr, gr->port, gr->port2);
1263  DetectPortPrint(gr);
1264 
1265  /* if we've set up all the unique groups, add the rest to the
1266  * catch-all joingr */
1267  if (left == 0) {
1268  if (joingr == NULL) {
1269  DetectPortParse(de_ctx, &joingr, "0:65535");
1270  if (joingr == NULL) {
1271  goto error;
1272  }
1273  SCLogDebug("joingr => %u-%u", joingr->port, joingr->port2);
1274  joingr->next = NULL;
1275  }
1276  SigGroupHeadCopySigs(de_ctx, gr->sh, &joingr->sh);
1277 
1278  /* when a group's sigs are added to the joingr, we can free it */
1279  gr->next = NULL;
1280  DetectPortFree(de_ctx, gr);
1281  /* append */
1282  } else {
1283  gr->next = NULL;
1284 
1285  if (tmplist2 == NULL) {
1286  tmplist2 = gr;
1287  tmplist2_tail = gr;
1288  } else {
1289  tmplist2_tail->next = gr;
1290  tmplist2_tail = gr;
1291  }
1292  }
1293 
1294  if (left > 0)
1295  left--;
1296 
1297  gr = next_gr;
1298  }
1299 
1300  /* if present, append the joingr that covers the rest */
1301  if (joingr != NULL) {
1302  SCLogDebug("appending joingr %p %u:%u", joingr, joingr->port, joingr->port2);
1303 
1304  if (tmplist2 == NULL) {
1305  tmplist2 = joingr;
1306  // tmplist2_tail = joingr;
1307  } else {
1308  tmplist2_tail->next = joingr;
1309  // tmplist2_tail = joingr;
1310  }
1311  } else {
1312  SCLogDebug("no joingr");
1313  }
1314 
1315  /* pass back our new list to the caller */
1316  *newhead = tmplist2;
1317  DetectPortPrintList(*newhead);
1318 
1319  return 0;
1320 error:
1321  return -1;
1322 }
1323 
1324 #define UNDEFINED_PORT 0
1325 #define RANGE_PORT 1
1326 #define SINGLE_PORT 2
1328 typedef struct UniquePortPoint_ {
1329  uint16_t port; /* value of the port */
1330  bool single; /* is the port single or part of a range */
1332 
1333 /**
1334  * \brief Function to set unique port points. Consider all the ports
1335  * flattened out on one line, set the points that correspond
1336  * to a valid port. Also store whether the port point stored
1337  * was a single port or part of a range.
1338  *
1339  * \param p Port object to be set
1340  * \param unique_list List of unique port points to be updated
1341  * \param size_list Current size of the list
1342  *
1343  * \return Updated size of the list
1344  */
1345 static inline uint32_t SetUniquePortPoints(
1346  const DetectPort *p, uint8_t *unique_list, uint32_t size_list)
1347 {
1348  if (unique_list[p->port] == UNDEFINED_PORT) {
1349  if (p->port == p->port2) {
1350  unique_list[p->port] = SINGLE_PORT;
1351  } else {
1352  unique_list[p->port] = RANGE_PORT;
1353  }
1354  size_list++;
1355  } else if (((unique_list[p->port] == SINGLE_PORT) && (p->port != p->port2)) ||
1356  ((unique_list[p->port] == RANGE_PORT) && (p->port == p->port2))) {
1357  if ((p->port != UINT16_MAX) && (unique_list[p->port + 1] == UNDEFINED_PORT)) {
1358  unique_list[p->port + 1] = RANGE_PORT;
1359  size_list++;
1360  }
1361  }
1362 
1363  /* Treat right boundary as single point to avoid creating unneeded
1364  * ranges later on */
1365  if (unique_list[p->port2] == UNDEFINED_PORT) {
1366  size_list++;
1367  }
1368  unique_list[p->port2] = SINGLE_PORT;
1369  return size_list;
1370 }
1371 
1372 /**
1373  * \brief Function to set the *final* unique port points and save them
1374  * for later use. The points are already sorted because of the way
1375  * they have been retrieved and saved earlier for use at this point.
1376  *
1377  * \param unique_list List of the unique port points to be used
1378  * \param size_unique_arr Number of unique port points
1379  * \param final_arr List of the final unique port points to be created
1380  */
1381 static inline void SetFinalUniquePortPoints(
1382  const uint8_t *unique_list, const uint32_t size_unique_arr, UniquePortPoint *final_arr)
1383 {
1384  for (uint32_t i = 0, j = 0; i < (UINT16_MAX + 1); i++) {
1385  DEBUG_VALIDATE_BUG_ON(j > size_unique_arr);
1386  if (unique_list[i] == RANGE_PORT) {
1387  final_arr[j].port = (uint16_t)i;
1388  final_arr[j++].single = false;
1389  } else if (unique_list[i] == SINGLE_PORT) {
1390  final_arr[j].port = (uint16_t)i;
1391  final_arr[j++].single = true;
1392  }
1393  }
1394 }
1395 
1396 /**
1397  * \brief Function to create the list of ports with the smallest ranges
1398  * by resolving overlaps and end point conditions. These contain the
1399  * correct SGHs as well after going over the interval tree to find
1400  * any range overlaps.
1401  *
1402  * \param de_ctx Detection Engine Context
1403  * \param unique_list Final list of unique port points
1404  * \param size_list Size of the unique_list
1405  * \param it Pointer to the interval tree
1406  * \param list Pointer to the list where final ports will be stored
1407  *
1408  * \return 0 on success, -1 otherwise
1409  */
1410 static inline int CreatePortList(DetectEngineCtx *de_ctx, const uint8_t *unique_list,
1411  const uint32_t size_list, SCPortIntervalTree *it, DetectPort **list)
1412 {
1413  /* Only do the operations if there is at least one unique port */
1414  if (size_list == 0)
1415  return 0;
1416  UniquePortPoint *final_unique_points =
1417  (UniquePortPoint *)SCCalloc(size_list, sizeof(UniquePortPoint));
1418  if (final_unique_points == NULL)
1419  return -1;
1420  SetFinalUniquePortPoints(unique_list, size_list, final_unique_points);
1421  /* Handle edge case when there is just one unique port */
1422  if (size_list == 1) {
1424  de_ctx, final_unique_points[0].port, final_unique_points[0].port, &it->tree, list);
1425  } else {
1426  UniquePortPoint *p1 = &final_unique_points[0];
1427  UniquePortPoint *p2 = &final_unique_points[1];
1428  uint16_t port = p1 ? p1->port : 0; // just for cppcheck
1429  uint16_t port2 = p2->port;
1430  for (uint32_t i = 1; i < size_list; i++) {
1431  DEBUG_VALIDATE_BUG_ON(port > port2);
1432  if ((p1 && p1->single) && p2->single) {
1433  SCPortIntervalFindOverlappingRanges(de_ctx, port, port, &it->tree, list);
1434  SCPortIntervalFindOverlappingRanges(de_ctx, port2, port2, &it->tree, list);
1435  port = port2 + 1;
1436  } else if (p1 && p1->single) {
1437  SCPortIntervalFindOverlappingRanges(de_ctx, port, port, &it->tree, list);
1438  if ((port2 > port + 1)) {
1440  de_ctx, port + 1, port2 - 1, &it->tree, list);
1441  port = port2;
1442  } else {
1443  port = port + 1;
1444  }
1445  } else if (p2->single) {
1446  /* If port2 is boundary and less or equal to port + 1, create a range
1447  * keeping the boundary away as it is single port */
1448  if ((port2 >= port + 1)) {
1449  SCPortIntervalFindOverlappingRanges(de_ctx, port, port2 - 1, &it->tree, list);
1450  }
1451  /* Deal with port2 as it is a single port */
1452  SCPortIntervalFindOverlappingRanges(de_ctx, port2, port2, &it->tree, list);
1453  port = port2 + 1;
1454  } else {
1455  if ((port2 > port + 1)) {
1456  SCPortIntervalFindOverlappingRanges(de_ctx, port, port2 - 1, &it->tree, list);
1457  port = port2;
1458  } else {
1459  SCPortIntervalFindOverlappingRanges(de_ctx, port, port2, &it->tree, list);
1460  port = port2 + 1;
1461  }
1462  }
1463  /* if the current port matches the p2->port, assign it to p1 so that
1464  * there is a UniquePortPoint object to check other info like whether
1465  * the port with this value is single */
1466  if (port == p2->port) {
1467  p1 = p2;
1468  } else {
1469  p1 = NULL;
1470  }
1471  if (i + 1 < size_list) {
1472  p2 = &final_unique_points[i + 1];
1473  port2 = p2->port;
1474  }
1475  }
1476  }
1477  /* final_unique_points array is no longer needed */
1478  SCFree(final_unique_points);
1479  return 0;
1480 }
1481 
1482 static DetectPort *RulesGroupByPorts(DetectEngineCtx *de_ctx, uint8_t ipproto, uint32_t direction)
1483 {
1484  /* step 1: create a hash of 'DetectPort' objects based on all the
1485  * rules. Each object will have a SGH with the sigs added
1486  * that belong to the SGH. */
1488 
1489  uint32_t size_unique_port_arr = 0;
1490  const Signature *s = de_ctx->sig_list;
1491  DetectPort *list = NULL;
1492 
1493  uint8_t *unique_port_points = (uint8_t *)SCCalloc(UINT16_MAX + 1, sizeof(uint8_t));
1494  if (unique_port_points == NULL)
1495  return NULL;
1496 
1497  while (s) {
1498  /* IP Only rules are handled separately */
1499  if (s->type == SIG_TYPE_IPONLY)
1500  goto next;
1501  /* Protocol does not match the Signature protocol and is neither IP or pkthdr */
1502  if (!(s->proto.proto[ipproto / 8] & (1<<(ipproto % 8)) || (s->proto.flags & DETECT_PROTO_ANY)))
1503  goto next;
1504  /* Direction does not match Signature direction */
1505  if (direction == SIG_FLAG_TOSERVER) {
1506  if (!(s->flags & SIG_FLAG_TOSERVER))
1507  goto next;
1508  } else if (direction == SIG_FLAG_TOCLIENT) {
1509  if (!(s->flags & SIG_FLAG_TOCLIENT))
1510  goto next;
1511  }
1512 
1513  /* see if we want to exclude directionless sigs that really care only for
1514  * to_server syn scans/floods */
1518  (!(s->dp->port == 0 && s->dp->port2 == 65535))) {
1519  SCLogWarning("rule %u: SYN-only to port(s) %u:%u "
1520  "w/o direction specified, disabling for toclient direction",
1521  s->id, s->dp->port, s->dp->port2);
1522  goto next;
1523  }
1524 
1525  DetectPort *p = NULL;
1526  if (direction == SIG_FLAG_TOSERVER)
1527  p = s->dp;
1528  else if (direction == SIG_FLAG_TOCLIENT)
1529  p = s->sp;
1530  else
1531  BUG_ON(1);
1532 
1533  int wl = s->init_data->score;
1534  while (p) {
1535  int pwl = PortIsPriority(de_ctx, p, ipproto) ? DETECT_PGSCORE_RULE_PORT_PRIORITIZED : 0;
1536  pwl = MAX(wl,pwl);
1537 
1538  DetectPort *lookup = DetectPortHashLookup(de_ctx, p);
1539  if (lookup) {
1540  SigGroupHeadAppendSig(de_ctx, &lookup->sh, s);
1541  lookup->sh->init->score = MAX(lookup->sh->init->score, pwl);
1542  } else {
1544  BUG_ON(tmp2 == NULL);
1545  SigGroupHeadAppendSig(de_ctx, &tmp2->sh, s);
1546  tmp2->sh->init->score = pwl;
1547  DetectPortHashAdd(de_ctx, tmp2);
1548  size_unique_port_arr =
1549  SetUniquePortPoints(tmp2, unique_port_points, size_unique_port_arr);
1550  }
1551 
1552  p = p->next;
1553  }
1554  next:
1555  s = s->next;
1556  }
1557 
1558  /* step 2: create a list of the smallest port ranges with
1559  * appropriate SGHs */
1560 
1561  /* Create an interval tree of all the given ports to make the search
1562  * for overlaps later on easier */
1564  if (it == NULL)
1565  goto error;
1566 
1567  HashListTableBucket *htb = NULL;
1568  for (htb = HashListTableGetListHead(de_ctx->dport_hash_table); htb != NULL;
1569  htb = HashListTableGetListNext(htb)) {
1571  if (SCPortIntervalInsert(de_ctx, it, p) != SC_OK) {
1572  SCLogDebug("Port was not inserted in the tree");
1573  goto error;
1574  }
1575  }
1576 
1577  /* Create a sorted list of ports in ascending order after resolving overlaps
1578  * and corresponding SGHs */
1579  if (CreatePortList(de_ctx, unique_port_points, size_unique_port_arr, it, &list) < 0)
1580  goto error;
1581 
1582  /* unique_port_points array is no longer needed */
1583  SCFree(unique_port_points);
1584 
1585  /* Port hashes are no longer needed */
1587 
1588  SCLogDebug("rules analyzed");
1589 
1590  /* step 3: group the list and shrink it if necessary */
1591  DetectPort *newlist = NULL;
1592  uint16_t groupmax = (direction == SIG_FLAG_TOCLIENT) ? de_ctx->max_uniq_toclient_groups :
1594  CreateGroupedPortList(de_ctx, list, &newlist, groupmax, SortCompare);
1595  list = newlist;
1596 
1597  /* step 4: deduplicate the SGH's */
1600 
1601  uint32_t cnt = 0;
1602  uint32_t own = 0;
1603  uint32_t ref = 0;
1604  DetectPort *iter;
1605  for (iter = list ; iter != NULL; iter = iter->next) {
1606  BUG_ON (iter->sh == NULL);
1607  DEBUG_VALIDATE_BUG_ON(own + ref != cnt);
1608  cnt++;
1609 
1610  SigGroupHead *lookup_sgh = SigGroupHeadHashLookup(de_ctx, iter->sh);
1611  if (lookup_sgh == NULL) {
1612  SCLogDebug("port group %p sgh %p is the original", iter, iter->sh);
1613 
1614  SigGroupHeadSetSigCnt(iter->sh, 0);
1616  SigGroupHeadSetProtoAndDirection(iter->sh, ipproto, direction);
1617  SigGroupHeadHashAdd(de_ctx, iter->sh);
1618  SigGroupHeadStore(de_ctx, iter->sh);
1619  iter->flags |= PORT_SIGGROUPHEAD_COPY;
1620  own++;
1621  } else {
1622  SCLogDebug("port group %p sgh %p is a copy", iter, iter->sh);
1623 
1624  SigGroupHeadFree(de_ctx, iter->sh);
1625  iter->sh = lookup_sgh;
1626  iter->flags |= PORT_SIGGROUPHEAD_COPY;
1627  ref++;
1628  }
1629  }
1630 #if 0
1631  for (iter = list ; iter != NULL; iter = iter->next) {
1632  SCLogInfo("PORT %u-%u %p (sgh=%s, prioritized=%s/%d)",
1633  iter->port, iter->port2, iter->sh,
1634  iter->flags & PORT_SIGGROUPHEAD_COPY ? "ref" : "own",
1635  iter->sh->init->score ? "true" : "false",
1636  iter->sh->init->score);
1637  }
1638 #endif
1639  SCLogPerf("%s %s: %u port groups, %u unique SGH's, %u copies",
1640  ipproto == 6 ? "TCP" : "UDP",
1641  direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient",
1642  cnt, own, ref);
1644  return list;
1645 
1646 error:
1647  if (unique_port_points != NULL)
1648  SCFree(unique_port_points);
1649  if (it != NULL)
1651 
1652  return NULL;
1653 }
1654 
1656 {
1657  BUG_ON(s->type != SIG_TYPE_NOT_SET);
1658  int iponly = 0;
1659 
1661  s->type = SIG_TYPE_APP_TX;
1662  SCLogDebug("%u: set to app_tx due to hook type app", s->id);
1663  SCReturn;
1664  }
1665 
1666  /* see if the sig is dp only */
1667  if (SignatureIsPDOnly(de_ctx, s) == 1) {
1668  s->type = SIG_TYPE_PDONLY;
1669 
1670  /* see if the sig is ip only */
1671  } else if ((iponly = SignatureIsIPOnly(de_ctx, s)) > 0) {
1672  if (iponly == 1) {
1673  s->type = SIG_TYPE_IPONLY;
1674  } else if (iponly == 2) {
1676  }
1677  } else if (SignatureIsDEOnly(de_ctx, s) == 1) {
1678  s->type = SIG_TYPE_DEONLY;
1679 
1680  } else {
1681  const bool has_match = s->init_data->smlists[DETECT_SM_LIST_MATCH] != NULL;
1682  const bool has_pmatch = s->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL;
1683  bool has_buffer_frame_engine = false;
1684  bool has_buffer_packet_engine = false;
1685  bool has_buffer_app_engine = false;
1686 
1687  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
1688  const uint32_t id = s->init_data->buffers[x].id;
1689 
1691  has_buffer_packet_engine = true;
1693  has_buffer_frame_engine = true;
1694  } else {
1695  has_buffer_app_engine = true;
1696  }
1697  }
1698 
1699  if (has_buffer_packet_engine) {
1700  s->type = SIG_TYPE_PKT;
1701  } else if (has_buffer_frame_engine || has_buffer_app_engine) {
1702  s->type = SIG_TYPE_APP_TX;
1703  } else if (has_pmatch) {
1706  s->type = SIG_TYPE_PKT;
1707  } else if ((s->flags & (SIG_FLAG_REQUIRE_PACKET | SIG_FLAG_REQUIRE_STREAM)) ==
1709  s->type = SIG_TYPE_STREAM;
1710  } else {
1712  }
1713  } else if (has_match) {
1714  s->type = SIG_TYPE_PKT;
1715 
1716  /* app-layer but no inspect engines */
1717  } else if (s->flags & SIG_FLAG_APPLAYER) {
1718  s->type = SIG_TYPE_APPLAYER;
1719  } else {
1720  s->type = SIG_TYPE_PKT;
1721  }
1722  }
1723 }
1724 
1725 /**
1726  * \brief Preprocess signature, classify ip-only, etc, build sig array
1727  *
1728  * \param de_ctx Pointer to the Detection Engine Context
1729  *
1730  * \retval 0 on success
1731  * \retval -1 on failure
1732  */
1734 {
1735  uint32_t cnt_iponly = 0;
1736  uint32_t cnt_payload = 0;
1737  uint32_t cnt_applayer = 0;
1738  uint32_t cnt_deonly = 0;
1739 
1740  if (!(de_ctx->flags & DE_QUIET)) {
1741  SCLogDebug("building signature grouping structure, stage 1: "
1742  "preprocessing rules...");
1743  }
1744 
1747  if (de_ctx->sig_array == NULL)
1748  goto error;
1749 
1750  /* now for every rule add the source group */
1751  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
1752  de_ctx->sig_array[s->iid] = s;
1753 
1754  SCLogDebug("Signature %" PRIu32 ", internal id %" PRIu32 ", ptrs %p %p ", s->id, s->iid, s,
1755  de_ctx->sig_array[s->iid]);
1756 
1757  if (s->type == SIG_TYPE_PDONLY) {
1758  SCLogDebug("Signature %"PRIu32" is considered \"PD only\"", s->id);
1759  } else if (s->type == SIG_TYPE_IPONLY) {
1760  SCLogDebug("Signature %"PRIu32" is considered \"IP only\"", s->id);
1761  cnt_iponly++;
1762  } else if (SignatureIsInspectingPayload(de_ctx, s) == 1) {
1763  SCLogDebug("Signature %"PRIu32" is considered \"Payload inspecting\"", s->id);
1764  cnt_payload++;
1765  } else if (s->type == SIG_TYPE_DEONLY) {
1766  SCLogDebug("Signature %"PRIu32" is considered \"Decoder Event only\"", s->id);
1767  cnt_deonly++;
1768  } else if (s->flags & SIG_FLAG_APPLAYER) {
1769  SCLogDebug("Signature %"PRIu32" is considered \"Applayer inspecting\"", s->id);
1770  cnt_applayer++;
1771  }
1772 
1773 #ifdef DEBUG
1774  if (SCLogDebugEnabled()) {
1775  uint16_t colen = 0;
1776  char copresent = 0;
1777  SigMatch *sm;
1778  DetectContentData *co;
1779  for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH]; sm != NULL; sm = sm->next) {
1780  if (sm->type != DETECT_CONTENT)
1781  continue;
1782 
1783  copresent = 1;
1784  co = (DetectContentData *)sm->ctx;
1785  if (co->content_len > colen)
1786  colen = co->content_len;
1787  }
1788 
1789  if (copresent && colen == 1) {
1790  SCLogDebug("signature %8u content maxlen 1", s->id);
1791  for (int proto = 0; proto < 256; proto++) {
1792  if (s->proto.proto[(proto/8)] & (1<<(proto%8)))
1793  SCLogDebug("=> proto %" PRId32 "", proto);
1794  }
1795  }
1796  }
1797 #endif /* DEBUG */
1798 
1799  if (RuleMpmIsNegated(s)) {
1800  s->flags |= SIG_FLAG_MPM_NEG;
1801  }
1802 
1803  SignatureCreateMask(s);
1806 
1807  RuleSetScore(s);
1808 
1809  /* run buffer type callbacks if any */
1810  for (int x = 0; x < DETECT_SM_LIST_MAX; x++) {
1811  if (s->init_data->smlists[x])
1813  }
1814  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
1816  }
1817 
1818  de_ctx->sig_cnt++;
1819  }
1820 
1821  if (!(de_ctx->flags & DE_QUIET)) {
1822  if (strlen(de_ctx->config_prefix) > 0)
1823  SCLogInfo("tenant id %d: %" PRIu32 " signatures processed. %" PRIu32 " are IP-only "
1824  "rules, %" PRIu32 " are inspecting packet payload, %" PRIu32
1825  " inspect application layer, %" PRIu32 " are decoder event only",
1826  de_ctx->tenant_id, de_ctx->sig_cnt, cnt_iponly, cnt_payload, cnt_applayer,
1827  cnt_deonly);
1828  else
1829  SCLogInfo("%" PRIu32 " signatures processed. %" PRIu32 " are IP-only "
1830  "rules, %" PRIu32 " are inspecting packet payload, %" PRIu32
1831  " inspect application layer, %" PRIu32 " are decoder event only",
1832  de_ctx->sig_cnt, cnt_iponly, cnt_payload, cnt_applayer, cnt_deonly);
1833 
1834  SCLogConfig("building signature grouping structure, stage 1: "
1835  "preprocessing rules... complete");
1836  }
1837 
1838  if (DetectFlowbitsAnalyze(de_ctx) != 0)
1839  goto error;
1840 
1841  return 0;
1842 
1843 error:
1844  return -1;
1845 }
1846 
1847 /**
1848  * \internal
1849  * \brief add a decoder event signature to the detection engine ctx
1850  */
1851 static void DetectEngineAddDecoderEventSig(DetectEngineCtx *de_ctx, Signature *s)
1852 {
1853  SCLogDebug("adding signature %"PRIu32" to the decoder event sgh", s->id);
1855 }
1856 
1857 static void DetectEngineAddSigToPreStreamHook(DetectEngineCtx *de_ctx, Signature *s)
1858 {
1859  SCLogDebug("adding signature %" PRIu32 " to the pre_stream hook sgh", s->id);
1860 
1861  if ((s->flags & (SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT)) ==
1865  } else if (s->flags & SIG_FLAG_TOSERVER) {
1867  } else if (s->flags & SIG_FLAG_TOCLIENT) {
1869  }
1870 }
1871 
1872 static void DetectEngineAddSigToPreFlowHook(DetectEngineCtx *de_ctx, Signature *s)
1873 {
1874  SCLogDebug("adding signature %" PRIu32 " to the pre_flow hook sgh", s->id);
1876 }
1877 
1878 /**
1879  * \brief Fill the global src group head, with the sigs included
1880  *
1881  * \param de_ctx Pointer to the Detection Engine Context whose Signatures have
1882  * to be processed
1883  *
1884  * \retval 0 On success
1885  * \retval -1 On failure
1886  */
1888 {
1889  SCLogDebug("building signature grouping structure, stage 2: "
1890  "building source address lists...");
1891 
1893 
1894  de_ctx->flow_gh[1].tcp = RulesGroupByPorts(de_ctx, IPPROTO_TCP, SIG_FLAG_TOSERVER);
1895  de_ctx->flow_gh[0].tcp = RulesGroupByPorts(de_ctx, IPPROTO_TCP, SIG_FLAG_TOCLIENT);
1896  de_ctx->flow_gh[1].udp = RulesGroupByPorts(de_ctx, IPPROTO_UDP, SIG_FLAG_TOSERVER);
1897  de_ctx->flow_gh[0].udp = RulesGroupByPorts(de_ctx, IPPROTO_UDP, SIG_FLAG_TOCLIENT);
1898 
1899  /* Setup the other IP Protocols (so not TCP/UDP) */
1900  RulesGroupByIPProto(de_ctx);
1901 
1902  /* now for every rule add the source group to our temp lists */
1903  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
1904  SCLogDebug("s->id %"PRIu32, s->id);
1905  if (s->type == SIG_TYPE_IPONLY) {
1907  } else if (s->type == SIG_TYPE_DEONLY) {
1908  DetectEngineAddDecoderEventSig(de_ctx, s);
1909  } else if (s->type == SIG_TYPE_PKT && s->init_data->hook.type == SIGNATURE_HOOK_TYPE_PKT &&
1911  DetectEngineAddSigToPreStreamHook(de_ctx, s);
1912  } else if (s->type == SIG_TYPE_PKT && s->init_data->hook.type == SIGNATURE_HOOK_TYPE_PKT &&
1914  DetectEngineAddSigToPreFlowHook(de_ctx, s);
1915  }
1916  }
1917 
1920  return 0;
1921 }
1922 
1923 static void DetectEngineBuildDecoderEventSgh(DetectEngineCtx *de_ctx)
1924 {
1925  if (de_ctx->decoder_event_sgh == NULL)
1926  return;
1927 
1928  uint32_t max_idx = DetectEngineGetMaxSigId(de_ctx);
1931 }
1932 
1933 static void DetectEngineBuildPreStreamHookSghs(DetectEngineCtx *de_ctx)
1934 {
1935  uint32_t max_idx = DetectEngineGetMaxSigId(de_ctx);
1936  if (de_ctx->pre_stream_sgh[0] != NULL) {
1940  }
1941  if (de_ctx->pre_stream_sgh[1] != NULL) {
1945  }
1946 
1947  if (de_ctx->pre_stream_sgh[0] != NULL || de_ctx->pre_stream_sgh[1] != NULL) {
1949  }
1950 }
1951 
1952 static void DetectEngineBuildPreFlowHookSghs(DetectEngineCtx *de_ctx)
1953 {
1954  if (de_ctx->pre_flow_sgh != NULL) {
1955  uint32_t max_idx = DetectEngineGetMaxSigId(de_ctx);
1960  }
1961 }
1962 
1964 {
1965  /* prepare the decoder event sgh */
1966  DetectEngineBuildDecoderEventSgh(de_ctx);
1967 
1968  /* pre_flow hook sgh */
1969  DetectEngineBuildPreFlowHookSghs(de_ctx);
1970 
1971  /* pre_stream hook sghs */
1972  DetectEngineBuildPreStreamHookSghs(de_ctx);
1973 
1974  return 0;
1975 }
1976 
1978 {
1979  BUG_ON(de_ctx == NULL);
1980 
1981  SCLogDebug("cleaning up signature grouping structure...");
1982 
1985  de_ctx->decoder_event_sgh = NULL;
1986  if (de_ctx->pre_flow_sgh)
1988  de_ctx->pre_flow_sgh = NULL;
1989  if (de_ctx->pre_stream_sgh[0])
1991  de_ctx->pre_stream_sgh[0] = NULL;
1992  if (de_ctx->pre_stream_sgh[1])
1994  de_ctx->pre_stream_sgh[1] = NULL;
1995 
1996  for (int f = 0; f < FLOW_STATES; f++) {
1997  for (int p = 0; p < 256; p++) {
1998  de_ctx->flow_gh[f].sgh[p] = NULL;
1999  }
2000 
2001  /* free lookup lists */
2003  de_ctx->flow_gh[f].tcp = NULL;
2005  de_ctx->flow_gh[f].udp = NULL;
2006  }
2007 
2008  for (uint32_t idx = 0; idx < de_ctx->sgh_array_cnt; idx++) {
2009  SigGroupHead *sgh = de_ctx->sgh_array[idx];
2010  if (sgh == NULL)
2011  continue;
2012 
2013  SCLogDebug("sgh %p", sgh);
2014  SigGroupHeadFree(de_ctx, sgh);
2015  }
2017  de_ctx->sgh_array = NULL;
2018  de_ctx->sgh_array_cnt = 0;
2019  de_ctx->sgh_array_size = 0;
2020 
2022 
2023  SCLogDebug("cleaning up signature grouping structure... complete");
2024  return 0;
2025 }
2026 
2027 #if 0
2028 static void DbgPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
2029 {
2030  if (sgh == NULL) {
2031  printf("\n");
2032  return;
2033  }
2034 
2035  uint32_t sig;
2036  for (sig = 0; sig < sgh->sig_cnt; sig++) {
2037  printf("%" PRIu32 " ", sgh->match_array[sig]->id);
2038  }
2039  printf("\n");
2040 }
2041 
2042 static void DbgPrintSigs2(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
2043 {
2044  if (sgh == NULL || sgh->init == NULL) {
2045  printf("\n");
2046  return;
2047  }
2048 
2049  uint32_t sig;
2050  for (sig = 0; sig < DetectEngineGetMaxSigId(de_ctx); sig++) {
2051  if (sgh->init->sig_array[(sig/8)] & (1<<(sig%8))) {
2052  printf("%" PRIu32 " ", de_ctx->sig_array[sig]->id);
2053  }
2054  }
2055  printf("\n");
2056 }
2057 #endif
2058 
2059 /** \brief finalize preparing sgh's */
2061 {
2062  SCEnter();
2063 
2064  //SCLogInfo("sgh's %"PRIu32, de_ctx->sgh_array_cnt);
2065 
2066  uint32_t cnt = 0;
2067  for (uint32_t idx = 0; idx < de_ctx->sgh_array_cnt; idx++) {
2068  SigGroupHead *sgh = de_ctx->sgh_array[idx];
2069  if (sgh == NULL)
2070  continue;
2071 
2072  SCLogDebug("sgh %p", sgh);
2073 
2075  SCLogDebug("filestore count %u", sgh->filestore_cnt);
2076 
2078 
2079  sgh->id = idx;
2080  cnt++;
2081  }
2082  SCLogPerf("Unique rule groups: %u", cnt);
2083 
2085 
2086  if (de_ctx->decoder_event_sgh != NULL) {
2087  /* no need to set filestore count here as that would make a
2088  * signature not decode event only. */
2090  }
2091 
2092  int dump_grouping = 0;
2093  (void)SCConfGetBool("detect.profiling.grouping.dump-to-disk", &dump_grouping);
2094 
2095  if (dump_grouping) {
2096  int add_rules = 0;
2097  (void)SCConfGetBool("detect.profiling.grouping.include-rules", &add_rules);
2098  int add_mpm_stats = 0;
2099  (void)SCConfGetBool("detect.profiling.grouping.include-mpm-stats", &add_mpm_stats);
2100 
2101  RulesDumpGrouping(de_ctx, add_rules, add_mpm_stats);
2102  }
2103 
2104  for (uint32_t idx = 0; idx < de_ctx->sgh_array_cnt; idx++) {
2105  SigGroupHead *sgh = de_ctx->sgh_array[idx];
2106  if (sgh == NULL)
2107  continue;
2109  sgh->init = NULL;
2110  }
2111  /* cleanup the hashes now since we won't need them
2112  * after the initialization phase. */
2114 
2115 #ifdef PROFILING
2117 #endif
2118  SCReturnInt(0);
2119 }
2120 
2121 extern bool rule_engine_analysis_set;
2122 /** \internal
2123  * \brief perform final per signature setup tasks
2124  *
2125  * - Create SigMatchData arrays from the init only SigMatch lists
2126  * - Setup per signature inspect engines
2127  * - remove signature init data.
2128  */
2129 static int SigMatchPrepare(DetectEngineCtx *de_ctx)
2130 {
2131  SCEnter();
2132 
2133  Signature *s = de_ctx->sig_list;
2134  for (; s != NULL; s = s->next) {
2135  /* set up inspect engines */
2137 
2138  /* built-ins */
2139  for (int type = 0; type < DETECT_SM_LIST_MAX; type++) {
2140  /* skip PMATCH if it is used in a stream 'app engine' instead */
2142  continue;
2143  SigMatch *sm = s->init_data->smlists[type];
2145  }
2146  /* set up the pkt inspection engines */
2148 
2152  }
2153  /* free lists. Ctx' are xferred to sm_arrays so won't get freed */
2154  for (uint32_t i = 0; i < DETECT_SM_LIST_MAX; i++) {
2155  SigMatch *sm = s->init_data->smlists[i];
2156  while (sm != NULL) {
2157  SigMatch *nsm = sm->next;
2158  SigMatchFree(de_ctx, sm);
2159  sm = nsm;
2160  }
2161  }
2162  for (uint32_t i = 0; i < (uint32_t)s->init_data->transforms.cnt; i++) {
2163  if (s->init_data->transforms.transforms[i].options) {
2164  int transform = s->init_data->transforms.transforms[i].transform;
2165  sigmatch_table[transform].Free(
2167  s->init_data->transforms.transforms[i].options = NULL;
2168  }
2169  }
2170  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
2171  SigMatch *sm = s->init_data->buffers[x].head;
2172  while (sm != NULL) {
2173  SigMatch *nsm = sm->next;
2174  SigMatchFree(de_ctx, sm);
2175  sm = nsm;
2176  }
2177  }
2178  if (s->init_data->cidr_dst != NULL)
2180 
2181  if (s->init_data->cidr_src != NULL)
2183 
2184  SCFree(s->init_data->buffers);
2187  SCFree(s->init_data);
2188  s->init_data = NULL;
2189  }
2190 
2192  SCReturnInt(0);
2193 }
2194 
2195 /**
2196  * \brief Convert the signature list into the runtime match structure.
2197  *
2198  * \param de_ctx Pointer to the Detection Engine Context whose Signatures have
2199  * to be processed
2200  *
2201  * \retval 0 On Success.
2202  * \retval -1 On failure.
2203  */
2205 {
2206  Signature *s = de_ctx->sig_list;
2207 
2208  /* Assign the unique order id of signatures after sorting,
2209  * so the IP Only engine process them in order too. Also
2210  * reset the old signums and assign new signums. We would
2211  * have experienced Sig reordering by now, hence the new
2212  * signums. */
2213  de_ctx->signum = 0;
2214  while (s != NULL) {
2215  s->iid = de_ctx->signum++;
2216 
2217  s = s->next;
2218  }
2219 
2221  return -1;
2222 
2223  SigInitStandardMpmFactoryContexts(de_ctx);
2224 
2225  if (SigPrepareStage1(de_ctx) != 0) {
2226  FatalError("initializing the detection engine failed");
2227  }
2228 
2229  if (SigPrepareStage2(de_ctx) != 0) {
2230  FatalError("initializing the detection engine failed");
2231  }
2232 
2233  if (SigPrepareStage3(de_ctx) != 0) {
2234  FatalError("initializing the detection engine failed");
2235  }
2236  if (SigPrepareStage4(de_ctx) != 0) {
2237  FatalError("initializing the detection engine failed");
2238  }
2239 
2244  if (r != 0) {
2245  FatalError("initializing the detection engine failed");
2246  }
2247 
2248  if (SigMatchPrepare(de_ctx) != 0) {
2249  FatalError("initializing the detection engine failed");
2250  }
2251 
2252 #ifdef PROFILING
2255  de_ctx->profile_match_logging_threshold = UINT_MAX; // disabled
2256 
2257  intmax_t v = 0;
2258  if (SCConfGetInt("detect.profiling.inspect-logging-threshold", &v) == 1)
2259  de_ctx->profile_match_logging_threshold = (uint32_t)v;
2260 #endif
2261 #ifdef PROFILE_RULES
2262  SCProfilingRuleInitCounters(de_ctx);
2263 #endif
2264 
2267  }
2268 
2269  if (EngineModeIsFirewall()) {
2271  }
2272  return 0;
2273 }
2274 
2276 {
2278 
2279  return 0;
2280 }
detect-tcp-flags.h
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:56
SIG_TYPE_STREAM
@ SIG_TYPE_STREAM
Definition: detect.h:74
DETECT_FLOW_FLAG_TOCLIENT
#define DETECT_FLOW_FLAG_TOCLIENT
Definition: detect-flow.h:28
SignatureInitDataBuffer_::head
SigMatch * head
Definition: detect.h:534
detect-content.h
DETECT_APP_LAYER_EVENT
@ DETECT_APP_LAYER_EVENT
Definition: detect-engine-register.h:204
util-port-interval-tree.h
detect-engine.h
DetectEngineResetMaxSigId
void DetectEngineResetMaxSigId(DetectEngineCtx *de_ctx)
Definition: detect-engine.c:3055
DetectEngineBufferTypeSupportsPacketGetById
bool DetectEngineBufferTypeSupportsPacketGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1446
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:119
SIG_MASK_REQUIRE_REAL_PKT
#define SIG_MASK_REQUIRE_REAL_PKT
Definition: detect.h:316
MASK_TCP_UNUSUAL_FLAGS
#define MASK_TCP_UNUSUAL_FLAGS
Definition: detect-engine-build.c:415
DetectFlagsSignatureNeedsSynOnlyPackets
int DetectFlagsSignatureNeedsSynOnlyPackets(const Signature *s)
Definition: detect-tcp-flags.c:536
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:642
detect-engine-proto.h
detect-dsize.h
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1264
UniquePortPoint_
Definition: detect-engine-build.c:1328
SIG_TYPE_APP_TX
@ SIG_TYPE_APP_TX
Definition: detect.h:77
SigMatchFree
void SigMatchFree(DetectEngineCtx *de_ctx, SigMatch *sm)
free a SigMatch
Definition: detect-parse.c:288
SigTableElmt_::Free
void(* Free)(DetectEngineCtx *, void *)
Definition: detect.h:1446
DetectEngineCtx_::decoder_event_sgh
struct SigGroupHead_ * decoder_event_sgh
Definition: detect.h:1017
DetectPortHashInit
int DetectPortHashInit(DetectEngineCtx *de_ctx)
Initializes the hash table in the detection engine context to hold the DetectPort hash.
Definition: detect-engine-port.c:1370
DetectEngineCtx_::flow_gh
DetectEngineLookupFlow flow_gh[FLOW_STATES]
Definition: detect.h:959
FILE_SIG_NEED_SHA1
#define FILE_SIG_NEED_SHA1
Definition: detect.h:325
SigPrepareStage4
int SigPrepareStage4(DetectEngineCtx *de_ctx)
finalize preparing sgh's
Definition: detect-engine-build.c:2060
detect-engine-siggroup.h
DetectFlowData_
Definition: detect-flow.h:37
SigTableElmt_::name
const char * name
Definition: detect.h:1459
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1319
DetectEngineBufferRunSetupCallback
void DetectEngineBufferRunSetupCallback(const DetectEngineCtx *de_ctx, const int id, Signature *s)
Definition: detect-engine.c:1483
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1629
DetectListToHumanString
const char * DetectListToHumanString(int list)
Definition: detect-parse.c:112
SIG_FLAG_INIT_FLOW
#define SIG_FLAG_INIT_FLOW
Definition: detect.h:292
SigFree
void SigFree(DetectEngineCtx *, Signature *)
Definition: detect-parse.c:2057
DumpPatterns
void DumpPatterns(DetectEngineCtx *de_ctx)
Definition: detect-engine-analyzer.c:1418
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectFlagsData_::flags
uint8_t flags
Definition: detect-tcp-flags.h:38
SigGroupHeadInitData_::sig_array
uint8_t * sig_array
Definition: detect.h:1603
DetectPortFree
void DetectPortFree(const DetectEngineCtx *de_ctx, DetectPort *dp)
Free a DetectPort and its members.
Definition: detect-engine-port.c:80
DetectEngineCtx_::PreFlowHook
DetectPacketHookFunc PreFlowHook
Definition: detect.h:1158
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:69
DetectEngineCtx_::max_uniq_toclient_groups
uint16_t max_uniq_toclient_groups
Definition: detect.h:990
MpmStoreReportStats
void MpmStoreReportStats(const DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:1476
SignatureInitData_::prefilter_sm
SigMatch * prefilter_sm
Definition: detect.h:625
SignatureInitData_::src_contains_negation
bool src_contains_negation
Definition: detect.h:601
DETECT_FLOW
@ DETECT_FLOW
Definition: detect-engine-register.h:54
Signature_::alproto
AppProto alproto
Definition: detect.h:673
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:275
DETECT_UINT_NE
#define DETECT_UINT_NE
Definition: detect-engine-uint.h:36
IPOnlyDeinit
void IPOnlyDeinit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
Deinitialize the IP Only detection engine context.
Definition: detect-engine-iponly.c:952
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DetectPort_::port
uint16_t port
Definition: detect.h:221
SCPortIntervalFindOverlappingRanges
void SCPortIntervalFindOverlappingRanges(DetectEngineCtx *de_ctx, const uint16_t port, const uint16_t port2, const struct PI *head, DetectPort **list)
Callee function to find all overlapping port ranges as asked by the detection engine during Stage 2 o...
Definition: util-port-interval-tree.c:315
PORT_SIGGROUPHEAD_COPY
#define PORT_SIGGROUPHEAD_COPY
Definition: detect.h:217
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:86
DETECT_DECODE_EVENT
@ DETECT_DECODE_EVENT
Definition: detect-engine-register.h:122
DETECT_SM_LIST_DYNAMIC_START
@ DETECT_SM_LIST_DYNAMIC_START
Definition: detect.h:138
Packet_::flags
uint32_t flags
Definition: decode.h:544
DetectEngineCtx_::PreStreamHook
DetectPacketHookFunc PreStreamHook
Definition: detect.h:1153
UNDEFINED_PORT
#define UNDEFINED_PORT
Definition: detect-engine-build.c:1324
PatternStrength
uint32_t PatternStrength(uint8_t *pat, uint16_t patlen)
Predict a strength value for patterns.
Definition: detect-engine-mpm.c:941
DetectFlowbitsAnalyze
int DetectFlowbitsAnalyze(DetectEngineCtx *de_ctx)
Definition: detect-flowbits.c:569
DetectSetFastPatternAndItsId
int DetectSetFastPatternAndItsId(DetectEngineCtx *de_ctx)
Figure out the FP and their respective content ids for all the sigs in the engine.
Definition: detect-engine-mpm.c:2464
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:40
SigTableElmt_::flags
uint16_t flags
Definition: detect.h:1450
SCProfilingSghInitCounters
void SCProfilingSghInitCounters(DetectEngineCtx *de_ctx)
Register the keyword profiling counters.
Definition: util-profiling-rulegroups.c:348
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:932
DETECT_PROTO_ANY
#define DETECT_PROTO_ANY
Definition: detect-engine-proto.h:28
SIG_TYPE_PKT_STREAM
@ SIG_TYPE_PKT_STREAM
Definition: detect.h:73
DetectEngineCtx_::pre_stream_sgh
struct SigGroupHead_ * pre_stream_sgh[2]
Definition: detect.h:1155
DetectFlagsSignatureNeedsSynPackets
int DetectFlagsSignatureNeedsSynPackets(const Signature *s)
Definition: detect-tcp-flags.c:517
TransformData_::options
void * options
Definition: detect.h:388
DetectFlowbitsData_::cmd
uint8_t cmd
Definition: detect-flowbits.h:37
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:287
SigGroupHeadSetProtoAndDirection
void SigGroupHeadSetProtoAndDirection(SigGroupHead *sgh, uint8_t ipproto, int dir)
Definition: detect-engine-siggroup.c:486
SIGMATCH_DEONLY_COMPAT
#define SIGMATCH_DEONLY_COMPAT
Definition: detect.h:1655
DETECT_UINT_EQ
#define DETECT_UINT_EQ
Definition: detect-engine-uint.h:35
DetectEngineBufferTypeGetNameById
const char * DetectEngineBufferTypeGetNameById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1309
DetectMpmInitializeBuiltinMpms
void DetectMpmInitializeBuiltinMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:737
SIG_FLAG_DST_ANY
#define SIG_FLAG_DST_ANY
Definition: detect.h:242
util-var-name.h
SIG_FLAG_REQUIRE_STREAM
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:255
rule_engine_analysis_set
bool rule_engine_analysis_set
Definition: detect-engine-loader.c:56
SCConfGetBool
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:497
DE_QUIET
#define DE_QUIET
Definition: detect.h:330
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:234
DetectEngineCtx_::tcp_priorityports
DetectPort * tcp_priorityports
Definition: detect.h:1068
DetectEngineCtx_::dport_hash_table
HashListTable * dport_hash_table
Definition: detect.h:1066
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:731
SignatureInitData_::init_flags
uint32_t init_flags
Definition: detect.h:608
proto
uint8_t proto
Definition: decode-template.h:0
DetectPort_::sh
struct SigGroupHead_ * sh
Definition: detect.h:231
DetectEngineCtx_::udp_priorityports
DetectPort * udp_priorityports
Definition: detect.h:1069
DetectContentData_
Definition: detect-content.h:93
DETECT_FLOWBITS_CMD_ISSET
#define DETECT_FLOWBITS_CMD_ISSET
Definition: detect-flowbits.h:32
PKT_NOPAYLOAD_INSPECTION
#define PKT_NOPAYLOAD_INSPECTION
Definition: decode.h:1250
SigCleanSignatures
void SigCleanSignatures(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:56
DetectPortPrintList
void DetectPortPrintList(DetectPort *head)
Helper function used to print the list of ports present in this DetectPort list.
Definition: detect-engine-port.c:100
DETECT_UINT_GT
#define DETECT_UINT_GT
Definition: detect-engine-uint.h:32
SigPrepareStage1
int SigPrepareStage1(DetectEngineCtx *de_ctx)
Preprocess signature, classify ip-only, etc, build sig array.
Definition: detect-engine-build.c:1733
DETECT_PGSCORE_RULE_SYN_ONLY
#define DETECT_PGSCORE_RULE_SYN_ONLY
Definition: detect-engine-build.c:54
EngineModeIsFirewall
bool EngineModeIsFirewall(void)
Definition: suricata.c:235
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:272
MAX
#define MAX(x, y)
Definition: suricata-common.h:412
SIG_FLAG_SRC_ANY
#define SIG_FLAG_SRC_ANY
Definition: detect.h:241
SigGroupHeadSetupFiles
void SigGroupHeadSetupFiles(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Set the need hash flag in the sgh.
Definition: detect-engine-siggroup.c:573
SIG_TYPE_APPLAYER
@ SIG_TYPE_APPLAYER
Definition: detect.h:76
SignatureIsFilesizeInspecting
int SignatureIsFilesizeInspecting(const Signature *s)
Check if a signature contains the filesize keyword.
Definition: detect-engine-build.c:187
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:606
DetectPort_::port2
uint16_t port2
Definition: detect.h:222
detect-engine-prefilter.h
Packet_::app_layer_events
AppLayerDecoderEvents * app_layer_events
Definition: decode.h:632
Packet_::events
PacketEngineEvents events
Definition: decode.h:630
FLOW_STATES
#define FLOW_STATES
Definition: detect.h:912
EngineAnalysisAddAllRulePatterns
void EngineAnalysisAddAllRulePatterns(DetectEngineCtx *de_ctx, const Signature *s)
add all patterns on our stats hash Used to fill the hash later used by DumpPatterns()
Definition: detect-engine-mpm.c:2521
DetectPort_::flags
uint8_t flags
Definition: detect.h:224
DetectPortPrint
void DetectPortPrint(DetectPort *dp)
Helper function that print the DetectPort info.
Definition: detect-engine-port.c:590
FirewallAnalyzer
int FirewallAnalyzer(const DetectEngineCtx *de_ctx)
Definition: detect-engine-analyzer.c:2001
PacketCreateMask
void PacketCreateMask(Packet *p, SignatureMask *mask, AppProto alproto, bool app_decoder_events)
Definition: detect-engine-build.c:420
SIG_FLAG_APPLAYER
#define SIG_FLAG_APPLAYER
Definition: detect.h:249
SigGroupHeadHashInit
int SigGroupHeadHashInit(DetectEngineCtx *de_ctx)
Initializes the hash table in the detection engine context to hold the SigGroupHeads.
Definition: detect-engine-siggroup.c:244
FILE_SIG_NEED_MD5
#define FILE_SIG_NEED_MD5
Definition: detect.h:324
DetectEngineCtx_::sgh_array_size
uint32_t sgh_array_size
Definition: detect.h:1002
SIGNATURE_HOOK_TYPE_APP
@ SIGNATURE_HOOK_TYPE_APP
Definition: detect.h:549
SignatureIsFileSha256Inspecting
int SignatureIsFileSha256Inspecting(const Signature *s)
Check if a signature contains the filesha256 keyword.
Definition: detect-engine-build.c:171
Signature_::next
struct Signature_ * next
Definition: detect.h:750
DetectFlowbitsData_
Definition: detect-flowbits.h:35
DetectEngineMultiTenantEnabled
int DetectEngineMultiTenantEnabled(void)
Definition: detect-engine.c:3874
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:55
DETECT_APP_LAYER_PROTOCOL
@ DETECT_APP_LAYER_PROTOCOL
Definition: detect-engine-register.h:35
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:127
SigGroupHeadInitData_::score
int score
Definition: detect.h:1608
DetectPortCopySingle
DetectPort * DetectPortCopySingle(DetectEngineCtx *de_ctx, DetectPort *src)
Function that return a copy of DetectPort src sigs.
Definition: detect-engine-port.c:550
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:271
DetectPortParse
int DetectPortParse(const DetectEngineCtx *de_ctx, DetectPort **head, const char *str)
Function for parsing port strings.
Definition: detect-engine-port.c:1182
SigAddressCleanupStage1
int SigAddressCleanupStage1(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:1977
SCPortIntervalInsert
int SCPortIntervalInsert(DetectEngineCtx *de_ctx, SCPortIntervalTree *it, const DetectPort *p)
Function to insert a node in the interval tree.
Definition: util-port-interval-tree.c:109
DetectEngineCtx_::pre_flow_sgh
struct SigGroupHead_ * pre_flow_sgh
Definition: detect.h:1160
SIG_TYPE_PKT
@ SIG_TYPE_PKT
Definition: detect.h:72
TCPHdr_::th_flags
uint8_t th_flags
Definition: decode-tcp.h:155
SigGroupHeadBuildMatchArray
int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t max_idx)
Create an array with all the internal ids of the sigs that this sig group head will check for.
Definition: detect-engine-siggroup.c:535
SigGroupHeadInitData_::sig_cnt
SigIntId sig_cnt
Definition: detect.h:1622
DETECT_CONTENT_ENDS_WITH
#define DETECT_CONTENT_ENDS_WITH
Definition: detect-content.h:42
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
g_alproto_max
AppProto g_alproto_max
Definition: app-layer-protos.c:29
DETECT_FLOWINT
@ DETECT_FLOWINT
Definition: detect-engine-register.h:62
IPOnlyInit
void IPOnlyInit(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
Setup the IP Only detection engine context.
Definition: detect-engine-iponly.c:913
SIG_MASK_REQUIRE_ENGINE_EVENT
#define SIG_MASK_REQUIRE_ENGINE_EVENT
Definition: detect.h:318
SIG_TYPE_IPONLY
@ SIG_TYPE_IPONLY
Definition: detect.h:66
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:623
SigFindSignatureBySidGid
Signature * SigFindSignatureBySidGid(DetectEngineCtx *de_ctx, uint32_t sid, uint32_t gid)
Find a specific signature by sid and gid.
Definition: detect-engine-build.c:80
DetectConfigData_::scope
enum ConfigScope scope
Definition: detect-config.h:32
DetectEngineGetMaxSigId
#define DetectEngineGetMaxSigId(de_ctx)
Definition: detect-engine.h:93
DETECT_FLOW_FLAG_TOSERVER
#define DETECT_FLOW_FLAG_TOSERVER
Definition: detect-flow.h:27
FILE_SIG_NEED_MAGIC
#define FILE_SIG_NEED_MAGIC
Definition: detect.h:322
SignatureInitData_::mpm_sm_list
int mpm_sm_list
Definition: detect.h:621
SIG_MASK_REQUIRE_FLOW
#define SIG_MASK_REQUIRE_FLOW
Definition: detect.h:312
SCConfGetInt
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:414
SignatureInitData_::cidr_dst
IPOnlyCIDRItem * cidr_dst
Definition: detect.h:618
DETECT_CONTENT_DEPTH
#define DETECT_CONTENT_DEPTH
Definition: detect-content.h:33
SCEnter
#define SCEnter(...)
Definition: util-debug.h:277
detect-engine-mpm.h
DetectEngineLookupFlow_::sgh
struct SigGroupHead_ * sgh[256]
Definition: detect.h:864
detect.h
SIG_MASK_REQUIRE_FLAGS_INITDEINIT
#define SIG_MASK_REQUIRE_FLAGS_INITDEINIT
Definition: detect.h:313
SCProfilingPrefilterInitCounters
void SCProfilingPrefilterInitCounters(DetectEngineCtx *de_ctx)
Register the prefilter profiling counters.
Definition: util-profiling-prefilter.c:300
SigMatchList2DataArray
SigMatchData * SigMatchList2DataArray(SigMatch *head)
convert SigMatch list to SigMatchData array
Definition: detect-parse.c:2365
PKT_DETECT_HAS_STREAMDATA
#define PKT_DETECT_HAS_STREAMDATA
Definition: decode.h:1303
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:360
DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_NEGATED
Definition: detect-content.h:40
detect-engine-port.h
DETECT_ENGINE_EVENT
@ DETECT_ENGINE_EVENT
Definition: detect-engine-register.h:226
DETECT_SM_LIST_MATCH
@ DETECT_SM_LIST_MATCH
Definition: detect.h:117
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:255
DetectContentPropagateLimits
void DetectContentPropagateLimits(Signature *s)
Definition: detect-content.c:718
SignatureHook_::pkt
struct SignatureHook_::@95::@97 pkt
DetectPort_
Port structure for detection engine.
Definition: detect.h:220
SigGroupHead_::init
SigGroupHeadInitData * init
Definition: detect.h:1646
DetectEngineCtx_::sig_cnt
uint32_t sig_cnt
Definition: detect.h:942
DETECT_PGSCORE_RULE_NO_MPM
#define DETECT_PGSCORE_RULE_NO_MPM
Definition: detect-engine-build.c:53
UniquePortPoint_::single
bool single
Definition: detect-engine-build.c:1330
SignatureInitData_::cidr_src
IPOnlyCIDRItem * cidr_src
Definition: detect.h:618
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:359
SignatureInitData_::hook
SignatureHook hook
Definition: detect.h:590
SIGNATURE_HOOK_TYPE_NOT_SET
@ SIGNATURE_HOOK_TYPE_NOT_SET
Definition: detect.h:547
SignatureHook_::t
union SignatureHook_::@95 t
DetectProto_::proto
uint8_t proto[256/8]
Definition: detect-engine-proto.h:36
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
AppLayerDecoderEvents_::cnt
uint8_t cnt
Definition: app-layer-events.h:40
IPOnlyPrepare
void IPOnlyPrepare(DetectEngineCtx *de_ctx)
Build the radix trees from the lists of parsed addresses in CIDR format the result should be 4 radix ...
Definition: detect-engine-iponly.c:1138
SigGroupCleanup
int SigGroupCleanup(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:2275
DETECT_PGSCORE_RULE_MPM_FAST_PATTERN
#define DETECT_PGSCORE_RULE_MPM_FAST_PATTERN
Definition: detect-engine-build.c:51
SIG_FLAG_REQUIRE_FLOWVAR
#define SIG_FLAG_REQUIRE_FLOWVAR
Definition: detect.h:267
util-profiling.h
FILE_SIG_NEED_SHA256
#define FILE_SIG_NEED_SHA256
Definition: detect.h:326
DetectEngineLookupFlow_::udp
DetectPort * udp
Definition: detect.h:863
SCReturn
#define SCReturn
Definition: util-debug.h:279
Signature_::flags
uint32_t flags
Definition: detect.h:669
Packet_
Definition: decode.h:501
detect-engine-build.h
type
uint16_t type
Definition: decode-vlan.c:106
DETECT_UINT_GTE
#define DETECT_UINT_GTE
Definition: detect-engine-uint.h:33
SCConfigGetLogDirectory
const char * SCConfigGetLogDirectory(void)
Definition: util-conf.c:38
IPOnlyPrint
void IPOnlyPrint(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx)
Print stats of the IP Only engine.
Definition: detect-engine-iponly.c:941
DetectConfigData_
Definition: detect-config.h:29
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:104
DetectEngineCtx_::max_uniq_toserver_groups
uint16_t max_uniq_toserver_groups
Definition: detect.h:991
IPOnlyAddSignature
void IPOnlyAddSignature(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx, Signature *s)
Add a signature to the lists of Addresses in CIDR format (sorted) this step is necessary to build the...
Definition: detect-engine-iponly.c:1410
SC_OK
@ SC_OK
Definition: util-error.h:27
DETECT_CONFIG
@ DETECT_CONFIG
Definition: detect-engine-register.h:229
name
const char * name
Definition: tm-threads.c:2163
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:747
DetectPreFlow
uint8_t DetectPreFlow(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, Packet *p)
Definition: detect.c:2312
SignatureInitData_::rule_state_dependant_sids_array
uint32_t * rule_state_dependant_sids_array
Definition: detect.h:657
DetectEngineCtx_::sgh_array_cnt
uint32_t sgh_array_cnt
Definition: detect.h:1001
SigGroupHeadAppendSig
int SigGroupHeadAppendSig(const DetectEngineCtx *de_ctx, SigGroupHead **sgh, const Signature *s)
Add a Signature to a SigGroupHead.
Definition: detect-engine-siggroup.c:319
DetectEngineCtx_::sgh_array
struct SigGroupHead_ ** sgh_array
Definition: detect.h:1000
UniquePortPoint_::port
uint16_t port
Definition: detect-engine-build.c:1329
SignatureInitData_::dst_contains_negation
bool dst_contains_negation
Definition: detect.h:602
SigGroupHeadFree
void SigGroupHeadFree(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Free a SigGroupHead and its members.
Definition: detect-engine-siggroup.c:163
DetectEngineTransforms::transforms
TransformData transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:392
SIG_TYPE_DEONLY
@ SIG_TYPE_DEONLY
Definition: detect.h:71
SIGNATURE_HOOK_PKT_PRE_STREAM
@ SIGNATURE_HOOK_PKT_PRE_STREAM
Definition: detect.h:542
detect-flowbits.h
SIG_MASK_REQUIRE_PAYLOAD
#define SIG_MASK_REQUIRE_PAYLOAD
Definition: detect.h:311
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:225
DETECT_DSIZE
@ DETECT_DSIZE
Definition: detect-engine-register.h:52
Signature_::sp
DetectPort * sp
Definition: detect.h:719
SIG_TYPE_NOT_SET
@ SIG_TYPE_NOT_SET
Definition: detect.h:65
SignatureIsFileSha1Inspecting
int SignatureIsFileSha1Inspecting(const Signature *s)
Check if a signature contains the filesha1 keyword.
Definition: detect-engine-build.c:155
SCPortIntervalTreeInit
SCPortIntervalTree * SCPortIntervalTreeInit(void)
Function to initialize the interval tree.
Definition: util-port-interval-tree.c:58
IPOnlyCIDRListFree
void IPOnlyCIDRListFree(IPOnlyCIDRItem *tmphead)
This function free a IPOnlyCIDRItem list.
Definition: detect-engine-iponly.c:482
SigGroupBuild
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
Definition: detect-engine-build.c:2204
DetectEngineCtx_::config_prefix
char config_prefix[64]
Definition: detect.h:1051
SIG_FLAG_MPM_NEG
#define SIG_FLAG_MPM_NEG
Definition: detect.h:257
SCPortIntervalTree_::tree
struct PI tree
Definition: util-port-interval-tree.h:30
detect-engine-analyzer.h
SIG_FLAG_INIT_STATE_MATCH
#define SIG_FLAG_INIT_STATE_MATCH
Definition: detect.h:296
DetectEngineBufferTypeSupportsFramesGetById
bool DetectEngineBufferTypeSupportsFramesGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1464
EngineAnalysisRules2
void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
Definition: detect-engine-analyzer.c:971
SigGroupHeadSetSigCnt
void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx)
Updates the SigGroupHead->sig_cnt with the total count of all the Signatures present in this SigGroup...
Definition: detect-engine-siggroup.c:446
DetectProto_::flags
uint8_t flags
Definition: detect-engine-proto.h:37
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
util-conf.h
DetectMpmPrepareFrameMpms
int DetectMpmPrepareFrameMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for applayer buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:524
SINGLE_PORT
#define SINGLE_PORT
Definition: detect-engine-build.c:1326
DetectEnginePktInspectionSetup
int DetectEnginePktInspectionSetup(Signature *s)
Definition: detect-engine.c:1862
tail
Host * tail
Definition: host.h:2
Signature_::proto
DetectProto proto
Definition: detect.h:687
suricata-common.h
SIG_MASK_REQUIRE_NO_PAYLOAD
#define SIG_MASK_REQUIRE_NO_PAYLOAD
Definition: detect.h:315
SIG_FLAG_SP_ANY
#define SIG_FLAG_SP_ANY
Definition: detect.h:243
SigGroupHeadStore
void SigGroupHeadStore(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Definition: detect-engine-siggroup.c:109
SigMatch_::type
uint16_t type
Definition: detect.h:357
SigGroupHeadInitData_::match_array
Signature ** match_array
Definition: detect.h:1625
Signature_::file_flags
uint8_t file_flags
Definition: detect.h:684
SigPrepareStage3
int SigPrepareStage3(DetectEngineCtx *de_ctx)
Definition: detect-engine-build.c:1963
SignatureHook_::type
enum SignatureHookType type
Definition: detect.h:572
DetectPort_::prev
struct DetectPort_ * prev
Definition: detect.h:233
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:234
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:94
MASK_TCP_INITDEINIT_FLAGS
#define MASK_TCP_INITDEINIT_FLAGS
Definition: detect-engine-build.c:414
DetectListToString
const char * DetectListToString(int list)
Definition: detect-parse.c:130
SIGNATURE_HOOK_PKT_PRE_FLOW
@ SIGNATURE_HOOK_PKT_PRE_FLOW
Definition: detect.h:541
DetectEngineCtx_::profile_match_logging_threshold
uint32_t profile_match_logging_threshold
Definition: detect.h:1049
FatalError
#define FatalError(...)
Definition: util-debug.h:510
SIGNATURE_HOOK_TYPE_PKT
@ SIGNATURE_HOOK_TYPE_PKT
Definition: detect.h:548
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:941
DetectMpmPreparePktMpms
int DetectMpmPreparePktMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for applayer buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:691
SigGroupHeadHashFree
void SigGroupHeadHashFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by SigGroupHeadHashInit() function.
Definition: detect-engine-siggroup.c:299
SIG_MASK_REQUIRE_FLAGS_UNUSUAL
#define SIG_MASK_REQUIRE_FLAGS_UNUSUAL
Definition: detect.h:314
TransformData_::transform
int transform
Definition: detect.h:387
DETECT_FLOWBITS
@ DETECT_FLOWBITS
Definition: detect-engine-register.h:59
app-layer-events.h
SigGroupHeadHashAdd
int SigGroupHeadHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Adds a SigGroupHead to the detection engine context SigGroupHead hash table.
Definition: detect-engine-siggroup.c:266
util-validate.h
detect-flow.h
SCPortIntervalTree_
Definition: util-port-interval-tree.h:29
SigPrepareStage2
int SigPrepareStage2(DetectEngineCtx *de_ctx)
Fill the global src group head, with the sigs included.
Definition: detect-engine-build.c:1887
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
SignatureInitData_::buffers
SignatureInitDataBuffer * buffers
Definition: detect.h:647
HtpBodyChunk_::next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:123
SigGroupHeadHashLookup
SigGroupHead * SigGroupHeadHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Used to lookup a SigGroupHead hash from the detection engine context SigGroupHead hash table.
Definition: detect-engine-siggroup.c:283
Signature_::dp
DetectPort * dp
Definition: detect.h:719
DETECT_STREAM_EVENT
@ DETECT_STREAM_EVENT
Definition: detect-engine-register.h:227
Signature_::iid
SigIntId iid
Definition: detect.h:680
DETECT_PGSCORE_RULE_PORT_PRIORITIZED
#define DETECT_PGSCORE_RULE_PORT_PRIORITIZED
Definition: detect-engine-build.c:50
SignatureIsFilestoring
int SignatureIsFilestoring(const Signature *s)
Check if a signature contains the filestore keyword.
Definition: detect-engine-build.c:101
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SignatureIsIPOnly
int SignatureIsIPOnly(DetectEngineCtx *de_ctx, const Signature *s)
Test is a initialized signature is IP only.
Definition: detect-engine-build.c:210
DetectMpmPrepareBuiltinMpms
int DetectMpmPrepareBuiltinMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for builtin buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:750
Signature_::id
uint32_t id
Definition: detect.h:713
HashListTableBucket_
Definition: util-hashlist.h:28
detect-engine-iponly.h
SignatureInitData_::score
int score
Definition: detect.h:636
detect-parse.h
SignatureInitDataBuffer_::id
uint32_t id
Definition: detect.h:525
Signature_
Signature container.
Definition: detect.h:668
SigMatch_
a single match condition for a signature
Definition: detect.h:356
DETECT_SM_LIST_MAX
@ DETECT_SM_LIST_MAX
Definition: detect.h:135
SigGroupHeadInitDataFree
void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid)
Definition: detect-engine-siggroup.c:60
SignatureIsFileMd5Inspecting
int SignatureIsFileMd5Inspecting(const Signature *s)
Check if a signature contains the filemd5 keyword.
Definition: detect-engine-build.c:139
DETECT_PGSCORE_RULE_MPM_NEGATED
#define DETECT_PGSCORE_RULE_MPM_NEGATED
Definition: detect-engine-build.c:52
DetectFlagsData_
Definition: detect-tcp-flags.h:37
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
SignatureSetType
void SignatureSetType(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine-build.c:1655
RANGE_PORT
#define RANGE_PORT
Definition: detect-engine-build.c:1325
PrefilterSetupRuleGroup
int PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Definition: detect-engine-prefilter.c:1176
SCProfilingKeywordInitCounters
void SCProfilingKeywordInitCounters(DetectEngineCtx *de_ctx)
Register the keyword profiling counters.
Definition: util-profiling-keywords.c:365
DetectEngineTransforms::cnt
int cnt
Definition: detect.h:393
DetectPortHashAdd
int DetectPortHashAdd(DetectEngineCtx *de_ctx, DetectPort *dp)
Adds a DetectPort to the detection engine context DetectPort hash table.
Definition: detect-engine-port.c:1390
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:950
CONFIG_SCOPE_FLOW
@ CONFIG_SCOPE_FLOW
Definition: util-config.h:51
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:95
DetectEngineCtx_::buffer_type_id
uint32_t buffer_type_id
Definition: detect.h:1081
DetectPreStream
uint8_t DetectPreStream(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, Packet *p)
Definition: detect.c:2322
SigParseApplyDsizeToContent
void SigParseApplyDsizeToContent(Signature *s)
Apply dsize as depth to content matches in the rule.
Definition: detect-dsize.c:327
SignatureInitData_::rule_state_flowbits_ids_array
uint32_t * rule_state_flowbits_ids_array
Definition: detect.h:660
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:934
UniquePortPoint
struct UniquePortPoint_ UniquePortPoint
SignatureInitData_::transforms
DetectEngineTransforms transforms
Definition: detect.h:631
DetectEngineCtx_::io_ctx
DetectEngineIPOnlyCtx io_ctx
Definition: detect.h:970
DetectU16Data
DetectUintData_u16 DetectU16Data
Definition: detect-engine-uint.h:42
DetectPortHashFree
void DetectPortHashFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by DetectPortInit() function.
Definition: detect-engine-port.c:1421
DetectPortHashLookup
DetectPort * DetectPortHashLookup(DetectEngineCtx *de_ctx, DetectPort *dp)
Used to lookup a DetectPort hash from the detection engine context DetectPort hash table.
Definition: detect-engine-port.c:1406
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DetectEngineCtx_::sig_array_len
uint32_t sig_array_len
Definition: detect.h:951
detect-config.h
DETECT_FLAGS
@ DETECT_FLAGS
Definition: detect-engine-register.h:42
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:281
Signature_::type
enum SignatureType type
Definition: detect.h:671
SignatureIsFilemagicInspecting
int SignatureIsFilemagicInspecting(const Signature *s)
Check if a signature contains the filemagic keyword.
Definition: detect-engine-build.c:120
DetectEngineCtx_::signum
uint32_t signum
Definition: detect.h:953
DetectEngineCtx_::tenant_id
uint32_t tenant_id
Definition: detect.h:939
SigGroupHead_::filestore_cnt
uint16_t filestore_cnt
Definition: detect.h:1635
SignatureInitData_::buffer_index
uint32_t buffer_index
Definition: detect.h:648
DetectMpmPrepareAppMpms
int DetectMpmPrepareAppMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for applayer buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:297
SIGMATCH_IPONLY_COMPAT
#define SIGMATCH_IPONLY_COMPAT
Definition: detect.h:1653
DetectEngineLookupFlow_::tcp
DetectPort * tcp
Definition: detect.h:862
DetectPortCleanupList
void DetectPortCleanupList(const DetectEngineCtx *de_ctx, DetectPort *head)
Free a DetectPort list and each of its members.
Definition: detect-engine-port.c:124
SIG_TYPE_PDONLY
@ SIG_TYPE_PDONLY
Definition: detect.h:70
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:767
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
DetectEngineAppInspectionEngine2Signature
int DetectEngineAppInspectionEngine2Signature(DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine.c:800
SCPortIntervalTreeFree
void SCPortIntervalTreeFree(DetectEngineCtx *de_ctx, SCPortIntervalTree *it)
Function to free an entire interval tree.
Definition: util-port-interval-tree.c:92
TCPHdr_
Definition: decode-tcp.h:149
detect-engine-address.h
SigGroupHead_::id
uint32_t id
Definition: detect.h:1637
VarNameStoreActivate
int VarNameStoreActivate(void)
Definition: util-var-name.c:214
SIG_FLAG_FILESTORE
#define SIG_FLAG_FILESTORE
Definition: detect.h:269
DETECT_UINT_RA
#define DETECT_UINT_RA
Definition: detect-engine-uint.h:34
FILE_SIG_NEED_SIZE
#define FILE_SIG_NEED_SIZE
Definition: detect.h:327
SIG_FLAG_DP_ANY
#define SIG_FLAG_DP_ANY
Definition: detect.h:244
DETECT_FLOWBITS_CMD_SET
#define DETECT_FLOWBITS_CMD_SET
Definition: detect-flowbits.h:28
detect-engine-threshold.h
SignatureMask
#define SignatureMask
Definition: decode.h:99
SigGroupHeadCopySigs
int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst)
Copies the bitarray holding the sids from the source SigGroupHead to the destination SigGroupHead.
Definition: detect-engine-siggroup.c:390
Signature_::mask
SignatureMask mask
Definition: detect.h:679
SIG_TYPE_LIKE_IPONLY
@ SIG_TYPE_LIKE_IPONLY
Definition: detect.h:67
PacketEngineEvents_::cnt
uint8_t cnt
Definition: decode.h:307
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:254