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