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