suricata
detect-engine-mpm.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2014 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  * \author Anoop Saldanha <anoopsaldanha@gmail.com>
23  *
24  * Multi pattern matcher
25  */
26 
27 #include "suricata.h"
28 #include "suricata-common.h"
29 
30 #include "app-layer-protos.h"
31 
32 #include "decode.h"
33 #include "detect.h"
34 #include "detect-engine.h"
35 #include "detect-engine-siggroup.h"
36 #include "detect-engine-mpm.h"
37 #include "detect-engine-iponly.h"
38 #include "detect-parse.h"
40 #include "util-mpm.h"
41 #include "util-memcmp.h"
42 #include "util-memcpy.h"
43 #include "conf.h"
44 #include "detect-fast-pattern.h"
45 
46 #include "detect-tcphdr.h"
47 #include "detect-udphdr.h"
48 
49 #include "flow.h"
50 #include "flow-var.h"
51 #include "detect-flow.h"
52 
53 #include "detect-content.h"
54 
55 #include "detect-engine-payload.h"
56 #include "detect-engine-dns.h"
57 
58 #include "stream.h"
59 
60 #include "util-misc.h"
61 #include "util-enum.h"
62 #include "util-debug.h"
63 #include "util-print.h"
64 #include "util-validate.h"
65 
66 const char *builtin_mpms[] = {
67  "toserver TCP packet",
68  "toclient TCP packet",
69  "toserver TCP stream",
70  "toclient TCP stream",
71  "toserver UDP packet",
72  "toclient UDP packet",
73  "other IP packet",
74 
75  NULL };
76 
77 /* Registry for mpm keywords
78  *
79  * Keywords are registered at engine start up
80  */
81 
82 static DetectBufferMpmRegistery *g_mpm_list[DETECT_BUFFER_MPM_TYPE_SIZE] = { NULL, NULL };
83 static int g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_SIZE] = { 0, 0 };
84 
85 /** \brief register a MPM engine
86  *
87  * \note to be used at start up / registration only. Errors are fatal.
88  */
89 void DetectAppLayerMpmRegister2(const char *name,
90  int direction, int priority,
91  int (*PrefilterRegister)(DetectEngineCtx *de_ctx,
92  SigGroupHead *sgh, MpmCtx *mpm_ctx,
93  const DetectBufferMpmRegistery *mpm_reg, int list_id),
95  AppProto alproto, int tx_min_progress)
96 {
97  SCLogDebug("registering %s/%d/%d/%p/%p/%u/%d", name, direction, priority,
98  PrefilterRegister, GetData, alproto, tx_min_progress);
99 
100  if (PrefilterRegister == PrefilterGenericMpmRegister && GetData == NULL) {
101  // must register GetData with PrefilterGenericMpmRegister
102  abort();
103  }
104 
107  int sm_list = DetectBufferTypeGetByName(name);
108  if (sm_list == -1) {
110  "MPM engine registration for %s failed", name);
111  }
112 
113  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
114  BUG_ON(am == NULL);
115  am->name = name;
116  snprintf(am->pname, sizeof(am->pname), "%s", am->name);
117  am->direction = direction;
118  am->sm_list = sm_list;
119  am->priority = priority;
121 
122  am->PrefilterRegisterWithListId = PrefilterRegister;
123  am->app_v2.GetData = GetData;
124  am->app_v2.alproto = alproto;
125  am->app_v2.tx_min_progress = tx_min_progress;
126 
127  if (g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP] == NULL) {
128  g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP] = am;
129  } else {
131  while (t->next != NULL) {
132  t = t->next;
133  }
134 
135  t->next = am;
136  am->id = t->id + 1;
137  }
138  g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_APP]++;
139 
140  SupportFastPatternForSigMatchList(sm_list, priority);
141 }
142 
143 /** \brief copy a mpm engine from parent_id, add in transforms */
145  const int id, const int parent_id,
146  DetectEngineTransforms *transforms)
147 {
148  SCLogDebug("registering %d/%d", id, parent_id);
149 
151  while (t) {
152  if (t->sm_list == parent_id) {
153  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
154  BUG_ON(am == NULL);
155  am->name = t->name;
156  am->direction = t->direction;
157  am->sm_list = id; // use new id
160  am->app_v2.GetData = t->app_v2.GetData;
161  am->app_v2.alproto = t->app_v2.alproto;
162  am->app_v2.tx_min_progress = t->app_v2.tx_min_progress;
163  am->priority = t->priority;
165  am->next = t->next;
166  if (transforms) {
167  memcpy(&am->transforms, transforms, sizeof(*transforms));
168 
169  /* create comma separated string of the names of the
170  * transforms and then shorten it if necessary. Finally
171  * use it to construct the 'profile' name for the engine */
172  char xforms[1024] = "";
173  for (int i = 0; i < transforms->cnt; i++) {
174  char ttstr[64];
175  (void)snprintf(ttstr,sizeof(ttstr), "%s,",
176  sigmatch_table[transforms->transforms[i].transform].name);
177  strlcat(xforms, ttstr, sizeof(xforms));
178  }
179  xforms[strlen(xforms)-1] = '\0';
180 
181  size_t space = sizeof(am->pname) - strlen(am->name) - 3;
182  char toprint[space + 1];
183  memset(toprint, 0x00, space + 1);
184  if (space < strlen(xforms)) {
185  ShortenString(xforms, toprint, space, '~');
186  } else {
187  strlcpy(toprint, xforms,sizeof(toprint));
188  }
189  (void)snprintf(am->pname, sizeof(am->pname), "%s#%d (%s)",
190  am->name, id, toprint);
191  } else {
192  (void)snprintf(am->pname, sizeof(am->pname), "%s#%d",
193  am->name, id);
194  }
195  am->id = de_ctx->app_mpms_list_cnt++;
196 
198  t->next = am;
199  SCLogDebug("copied mpm registration for %s id %u "
200  "with parent %u and GetData %p",
201  t->name, id, parent_id, am->app_v2.GetData);
202  t = am;
203  }
204  t = t->next;
205  }
206 }
207 
209 {
210  const DetectBufferMpmRegistery *list = g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP];
211  while (list != NULL) {
212  DetectBufferMpmRegistery *n = SCCalloc(1, sizeof(*n));
213  BUG_ON(n == NULL);
214 
215  *n = *list;
216  n->next = NULL;
217 
218  if (de_ctx->app_mpms_list == NULL) {
219  de_ctx->app_mpms_list = n;
220  } else {
222  while (t->next != NULL) {
223  t = t->next;
224  }
225  t->next = n;
226  }
227 
228  /* default to whatever the global setting is */
230 
231  /* see if we use a unique or shared mpm ctx for this type */
232  int confshared = 0;
233  char confstring[256] = "detect.mpm.";
234  strlcat(confstring, n->name, sizeof(confstring));
235  strlcat(confstring, ".shared", sizeof(confstring));
236  if (ConfGetBool(confstring, &confshared) == 1)
237  shared = confshared;
238 
239  if (shared == 0) {
240  if (!(de_ctx->flags & DE_QUIET)) {
241  SCLogPerf("using unique mpm ctx' for %s", n->name);
242  }
244  } else {
245  if (!(de_ctx->flags & DE_QUIET)) {
246  SCLogPerf("using shared mpm ctx' for %s", n->name);
247  }
249  }
250 
251  list = list->next;
252  }
254  SCLogDebug("mpm: de_ctx app_mpms_list %p %u",
256 }
257 
258 /**
259  * \brief initialize mpm contexts for applayer buffers that are in
260  * "single or "shared" mode.
261  */
263 {
264  int r = 0;
266  while (am != NULL) {
267  int dir = (am->direction == SIG_FLAG_TOSERVER) ? 1 : 0;
268 
270  {
272  if (mpm_ctx != NULL) {
273  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
274  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
275  }
276  }
277  }
278  am = am->next;
279  }
280  return r;
281 }
282 
283 /** \brief register a MPM engine
284  *
285  * \note to be used at start up / registration only. Errors are fatal.
286  */
287 void DetectPktMpmRegister(const char *name,
288  int priority,
289  int (*PrefilterRegister)(DetectEngineCtx *de_ctx,
290  SigGroupHead *sgh, MpmCtx *mpm_ctx,
291  const DetectBufferMpmRegistery *mpm_reg, int list_id),
293 {
294  SCLogDebug("registering %s/%d/%p/%p", name, priority,
295  PrefilterRegister, GetData);
296 
297  if (PrefilterRegister == PrefilterGenericMpmPktRegister && GetData == NULL) {
298  // must register GetData with PrefilterGenericMpmRegister
299  abort();
300  }
301 
304  int sm_list = DetectBufferTypeGetByName(name);
305  if (sm_list == -1) {
307  "MPM engine registration for %s failed", name);
308  }
309 
310  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
311  BUG_ON(am == NULL);
312  am->name = name;
313  snprintf(am->pname, sizeof(am->pname), "%s", am->name);
314  am->sm_list = sm_list;
315  am->priority = priority;
317 
318  am->PrefilterRegisterWithListId = PrefilterRegister;
319  am->pkt_v1.GetData = GetData;
320 
321  if (g_mpm_list[DETECT_BUFFER_MPM_TYPE_PKT] == NULL) {
322  g_mpm_list[DETECT_BUFFER_MPM_TYPE_PKT] = am;
323  } else {
325  while (t->next != NULL) {
326  t = t->next;
327  }
328  t->next = am;
329  am->id = t->id + 1;
330  }
331  g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_PKT]++;
332 
333  SupportFastPatternForSigMatchList(sm_list, priority);
334  SCLogDebug("%s/%d done", name, sm_list);
335 }
336 
337 /** \brief copy a mpm engine from parent_id, add in transforms */
339  const int id, const int parent_id,
340  DetectEngineTransforms *transforms)
341 {
342  SCLogDebug("registering %d/%d", id, parent_id);
343 
345  while (t) {
346  if (t->sm_list == parent_id) {
347  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
348  BUG_ON(am == NULL);
349  am->name = t->name;
350  snprintf(am->pname, sizeof(am->pname), "%s#%d", am->name, id);
351  am->sm_list = id; // use new id
354  am->pkt_v1.GetData = t->pkt_v1.GetData;
355  am->priority = t->priority;
357  am->next = t->next;
358  if (transforms) {
359  memcpy(&am->transforms, transforms, sizeof(*transforms));
360  }
361  am->id = de_ctx->pkt_mpms_list_cnt++;
362 
364  t->next = am;
365  SCLogDebug("copied mpm registration for %s id %u "
366  "with parent %u and GetData %p",
367  t->name, id, parent_id, am->pkt_v1.GetData);
368  t = am;
369  }
370  t = t->next;
371  }
372 }
373 
375 {
376  const DetectBufferMpmRegistery *list = g_mpm_list[DETECT_BUFFER_MPM_TYPE_PKT];
377  while (list != NULL) {
378  DetectBufferMpmRegistery *n = SCCalloc(1, sizeof(*n));
379  BUG_ON(n == NULL);
380 
381  *n = *list;
382  n->next = NULL;
383 
384  if (de_ctx->pkt_mpms_list == NULL) {
385  de_ctx->pkt_mpms_list = n;
386  } else {
388  while (t->next != NULL) {
389  t = t->next;
390  }
391 
392  t->next = n;
393  }
394 
395  /* default to whatever the global setting is */
397 
398  /* see if we use a unique or shared mpm ctx for this type */
399  int confshared = 0;
400  char confstring[256] = "detect.mpm.";
401  strlcat(confstring, n->name, sizeof(confstring));
402  strlcat(confstring, ".shared", sizeof(confstring));
403  if (ConfGetBool(confstring, &confshared) == 1)
404  shared = confshared;
405 
406  if (shared == 0) {
407  if (!(de_ctx->flags & DE_QUIET)) {
408  SCLogPerf("using unique mpm ctx' for %s", n->name);
409  }
411  } else {
412  if (!(de_ctx->flags & DE_QUIET)) {
413  SCLogPerf("using shared mpm ctx' for %s", n->name);
414  }
416  }
417 
418  list = list->next;
419  }
421  SCLogDebug("mpm: de_ctx pkt_mpms_list %p %u",
423 }
424 
425 /**
426  * \brief initialize mpm contexts for applayer buffers that are in
427  * "single or "shared" mode.
428  */
430 {
431  SCLogDebug("preparing pkt mpm");
432  int r = 0;
434  while (am != NULL) {
435  SCLogDebug("%s", am->name);
437  {
439  if (mpm_ctx != NULL) {
440  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
441  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
442  SCLogDebug("%s: %d", am->name, r);
443  }
444  }
445  }
446  am = am->next;
447  }
448  return r;
449 }
450 
451 static int32_t SetupBuiltinMpm(DetectEngineCtx *de_ctx, const char *name)
452 {
453  /* default to whatever the global setting is */
455 
456  /* see if we use a unique or shared mpm ctx for this type */
457  int confshared = 0;
458  char confstring[256] = "detect.mpm.";
459  strlcat(confstring, name, sizeof(confstring));
460  strlcat(confstring, ".shared", sizeof(confstring));
461  if (ConfGetBool(confstring, &confshared) == 1)
462  shared = confshared;
463 
464  int32_t ctx;
465  if (shared == 0) {
467  SCLogPerf("using unique mpm ctx' for %s", name);
468  } else {
470  SCLogPerf("using shared mpm ctx' for %s", name);
471  }
472  return ctx;
473 }
474 
476 {
477  de_ctx->sgh_mpm_context_proto_tcp_packet = SetupBuiltinMpm(de_ctx, "tcp-packet");
478  de_ctx->sgh_mpm_context_stream = SetupBuiltinMpm(de_ctx, "tcp-stream");
479 
480  de_ctx->sgh_mpm_context_proto_udp_packet = SetupBuiltinMpm(de_ctx, "udp-packet");
481  de_ctx->sgh_mpm_context_proto_other_packet = SetupBuiltinMpm(de_ctx, "other-ip");
482 }
483 
484 /**
485  * \brief initialize mpm contexts for builtin buffers that are in
486  * "single or "shared" mode.
487  */
489 {
490  int r = 0;
491  MpmCtx *mpm_ctx = NULL;
492 
495  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
496  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
497  }
499  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
500  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
501  }
502  }
503 
506  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
507  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
508  }
510  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
511  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
512  }
513  }
514 
517  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
518  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
519  }
520  }
521 
524  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
525  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
526  }
528  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
529  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
530  }
531  }
532 
533  return r;
534 }
535 
536 /**
537  * \brief check if a signature has patterns that are to be inspected
538  * against a packets payload (as opposed to the stream payload)
539  *
540  * \param s signature
541  *
542  * \retval 1 true
543  * \retval 0 false
544  */
546 {
547  SCEnter();
548 
549  if (s == NULL) {
550  SCReturnInt(0);
551  }
552 
553  if (!(s->proto.proto[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8))) {
554  SCReturnInt(1);
555  }
556 
557  if ((s->init_data != NULL && s->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) ||
558  (s->init_data == NULL && s->sm_arrays[DETECT_SM_LIST_PMATCH] == NULL))
559  {
560  SCLogDebug("no mpm");
561  SCReturnInt(0);
562  }
563 
564  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
565  SCReturnInt(0);
566  }
567 
568  SCReturnInt(1);
569 }
570 
571 /**
572  * \brief check if a signature has patterns that are to be inspected
573  * against the stream payload (as opposed to the individual packets
574  * payload(s))
575  *
576  * \param s signature
577  *
578  * \retval 1 true
579  * \retval 0 false
580  */
582 {
583  SCEnter();
584 
585  if (s == NULL) {
586  SCReturnInt(0);
587  }
588 
589  if (!(s->proto.proto[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8))) {
590  SCReturnInt(0);
591  }
592 
593  if ((s->init_data != NULL && s->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) ||
594  (s->init_data == NULL && s->sm_arrays[DETECT_SM_LIST_PMATCH] == NULL))
595  {
596  SCLogDebug("no mpm");
597  SCReturnInt(0);
598  }
599 
600  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
601  SCReturnInt(0);
602  }
603 
604  SCReturnInt(1);
605 }
606 
607 
608 /**
609  * \brief Function to return the multi pattern matcher algorithm to be
610  * used by the engine, based on the mpm-algo setting in yaml
611  * Use the default mpm if none is specified in the yaml file.
612  *
613  * \retval mpm algo value
614  */
616 {
617  const char *mpm_algo;
618  uint16_t mpm_algo_val = mpm_default_matcher;
619 
620  /* Get the mpm algo defined in config file by the user */
621  if ((ConfGet("mpm-algo", &mpm_algo)) == 1) {
622  if (mpm_algo != NULL) {
623 #if __BYTE_ORDER == __BIG_ENDIAN
624  if (strcmp(mpm_algo, "ac-ks") == 0) {
625  FatalError(SC_ERR_FATAL, "ac-ks does "
626  "not work on big endian systems at this time.");
627  }
628 #endif
629  if (strcmp("auto", mpm_algo) == 0) {
630  goto done;
631  }
632  for (uint16_t u = 0; u < MPM_TABLE_SIZE; u++) {
633  if (mpm_table[u].name == NULL)
634  continue;
635 
636  if (strcmp(mpm_table[u].name, mpm_algo) == 0) {
637  mpm_algo_val = u;
638  goto done;
639  }
640  }
641 
642 #ifndef BUILD_HYPERSCAN
643  if ((strcmp(mpm_algo, "hs") == 0)) {
644  FatalError(SC_ERR_INVALID_VALUE, "Hyperscan (hs) support for mpm-algo is "
645  "not compiled into Suricata.");
646  }
647 #endif
648  }
649  FatalError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Invalid mpm algo supplied "
650  "in the yaml conf file: \"%s\"", mpm_algo);
651  }
652 
653  done:
654  return mpm_algo_val;
655 }
656 
657 /** \brief cleans up the mpm instance after a match */
659 {
660  PmqReset(&det_ctx->pmq);
661 }
662 
663 void PatternMatchDestroy(MpmCtx *mpm_ctx, uint16_t mpm_matcher)
664 {
665  SCLogDebug("mpm_ctx %p, mpm_matcher %"PRIu16"", mpm_ctx, mpm_matcher);
666  mpm_table[mpm_matcher].DestroyCtx(mpm_ctx);
667 }
668 
669 void PatternMatchThreadPrint(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
670 {
671  SCLogDebug("mpm_thread_ctx %p, mpm_matcher %"PRIu16" defunct", mpm_thread_ctx, mpm_matcher);
672  //mpm_table[mpm_matcher].PrintThreadCtx(mpm_thread_ctx);
673 }
674 void PatternMatchThreadDestroy(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
675 {
676  SCLogDebug("mpm_thread_ctx %p, mpm_matcher %"PRIu16"", mpm_thread_ctx, mpm_matcher);
677  if (mpm_table[mpm_matcher].DestroyThreadCtx != NULL)
678  mpm_table[mpm_matcher].DestroyThreadCtx(NULL, mpm_thread_ctx);
679 }
680 void PatternMatchThreadPrepare(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
681 {
682  SCLogDebug("mpm_thread_ctx %p, type %"PRIu16, mpm_thread_ctx, mpm_matcher);
683  MpmInitThreadCtx(mpm_thread_ctx, mpm_matcher);
684 }
685 
686 /** \brief Predict a strength value for patterns
687  *
688  * Patterns with high character diversity score higher.
689  * Alpha chars score not so high
690  * Other printable + a few common codes a little higher
691  * Everything else highest.
692  * Longer patterns score better than short patters.
693  *
694  * \param pat pattern
695  * \param patlen length of the pattern
696  *
697  * \retval s pattern score
698  */
699 uint32_t PatternStrength(uint8_t *pat, uint16_t patlen)
700 {
701  uint8_t a[256];
702  memset(&a, 0 ,sizeof(a));
703 
704  uint32_t s = 0;
705  uint16_t u = 0;
706  for (u = 0; u < patlen; u++) {
707  if (a[pat[u]] == 0) {
708  if (isalpha(pat[u]))
709  s += 3;
710  else if (isprint(pat[u]) || pat[u] == 0x00 || pat[u] == 0x01 || pat[u] == 0xFF)
711  s += 4;
712  else
713  s += 6;
714 
715  a[pat[u]] = 1;
716  } else {
717  s++;
718  }
719  }
720 
721  return s;
722 }
723 
724 static void PopulateMpmHelperAddPattern(MpmCtx *mpm_ctx,
725  const DetectContentData *cd,
726  const Signature *s, uint8_t flags,
727  int chop)
728 {
729  uint16_t pat_offset = cd->offset;
730  uint16_t pat_depth = cd->depth;
731 
732  /* recompute offset/depth to cope with chop */
733  if (chop && (pat_depth || pat_offset)) {
734  pat_offset += cd->fp_chop_offset;
735  if (pat_depth) {
736  pat_depth -= cd->content_len;
737  pat_depth += cd->fp_chop_offset + cd->fp_chop_len;
738  }
739  }
740 
741  /* We have to effectively "wild card" values that will be coming from
742  * byte_extract variables
743  */
745  pat_depth = pat_offset = 0;
746  }
747 
748  if (cd->flags & DETECT_CONTENT_NOCASE) {
749  if (chop) {
750  MpmAddPatternCI(mpm_ctx,
751  cd->content + cd->fp_chop_offset, cd->fp_chop_len,
752  pat_offset, pat_depth,
754  } else {
755  MpmAddPatternCI(mpm_ctx,
756  cd->content, cd->content_len,
757  pat_offset, pat_depth,
759  }
760  } else {
761  if (chop) {
762  MpmAddPatternCS(mpm_ctx,
763  cd->content + cd->fp_chop_offset, cd->fp_chop_len,
764  pat_offset, pat_depth,
766  } else {
767  MpmAddPatternCS(mpm_ctx,
768  cd->content, cd->content_len,
769  pat_offset, pat_depth,
771  }
772  }
773 
774  return;
775 }
776 
777 #define SGH_PROTO(sgh, p) ((sgh)->init->protos[(p)] == 1)
778 #define SGH_DIRECTION_TS(sgh) ((sgh)->init->direction & SIG_FLAG_TOSERVER)
779 #define SGH_DIRECTION_TC(sgh) ((sgh)->init->direction & SIG_FLAG_TOCLIENT)
780 
781 static void SetMpm(Signature *s, SigMatch *mpm_sm)
782 {
783  if (s == NULL || mpm_sm == NULL)
784  return;
785 
786  DetectContentData *cd = (DetectContentData *)mpm_sm->ctx;
788  if (DETECT_CONTENT_IS_SINGLE(cd) &&
789  !(cd->flags & DETECT_CONTENT_NEGATED) &&
790  !(cd->flags & DETECT_CONTENT_REPLACE) &&
791  cd->content_len == cd->fp_chop_len)
792  {
794  }
795  } else {
796  if (DETECT_CONTENT_IS_SINGLE(cd) &&
797  !(cd->flags & DETECT_CONTENT_NEGATED) &&
798  !(cd->flags & DETECT_CONTENT_REPLACE))
799  {
801  }
802  }
803  cd->flags |= DETECT_CONTENT_MPM;
804  s->init_data->mpm_sm = mpm_sm;
805  return;
806 }
807 
808 static SigMatch *GetMpmForList(const Signature *s, const int list, SigMatch *mpm_sm,
809  uint16_t max_len, bool skip_negated_content)
810 {
811  for (SigMatch *sm = s->init_data->smlists[list]; sm != NULL; sm = sm->next) {
812  if (sm->type != DETECT_CONTENT)
813  continue;
814 
815  const DetectContentData *cd = (DetectContentData *)sm->ctx;
816  /* skip_negated_content is only set if there's absolutely no
817  * non-negated content present in the sig */
818  if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
819  continue;
820  if (cd->content_len != max_len)
821  continue;
822 
823  if (mpm_sm == NULL) {
824  mpm_sm = sm;
825  } else {
826  DetectContentData *data1 = (DetectContentData *)sm->ctx;
827  DetectContentData *data2 = (DetectContentData *)mpm_sm->ctx;
828  uint32_t ls = PatternStrength(data1->content, data1->content_len);
829  uint32_t ss = PatternStrength(data2->content, data2->content_len);
830  if (ls > ss) {
831  mpm_sm = sm;
832  } else if (ls == ss) {
833  /* if 2 patterns are of equal strength, we pick the longest */
834  if (data1->content_len > data2->content_len)
835  mpm_sm = sm;
836  } else {
837  SCLogDebug("sticking with mpm_sm");
838  }
839  }
840  }
841  return mpm_sm;
842 }
843 
845 {
846  if (s->init_data->mpm_sm != NULL)
847  return;
848 
849  SigMatch *mpm_sm = NULL, *sm = NULL;
850  const int nlists = s->init_data->smlists_array_size;
851  int nn_sm_list[nlists];
852  int n_sm_list[nlists];
853  memset(nn_sm_list, 0, nlists * sizeof(int));
854  memset(n_sm_list, 0, nlists * sizeof(int));
855  int count_nn_sm_list = 0;
856  int count_n_sm_list = 0;
857 
858  /* inspect rule to see if we have the fast_pattern reg to
859  * force using a sig, otherwise keep stats about the patterns */
860  for (int list_id = 0; list_id < nlists; list_id++) {
861  if (s->init_data->smlists[list_id] == NULL)
862  continue;
863 
865  continue;
866 
867  for (sm = s->init_data->smlists[list_id]; sm != NULL; sm = sm->next) {
868  if (sm->type != DETECT_CONTENT)
869  continue;
870 
871  const DetectContentData *cd = (DetectContentData *)sm->ctx;
872  /* fast_pattern set in rule, so using this pattern */
873  if ((cd->flags & DETECT_CONTENT_FAST_PATTERN)) {
874  SetMpm(s, sm);
875  return;
876  }
877 
878  if (cd->flags & DETECT_CONTENT_NEGATED) {
879  n_sm_list[list_id] = 1;
880  count_n_sm_list++;
881  } else {
882  nn_sm_list[list_id] = 1;
883  count_nn_sm_list++;
884  }
885  }
886  }
887 
888  /* prefer normal not-negated over negated */
889  int *curr_sm_list = NULL;
890  int skip_negated_content = 1;
891  if (count_nn_sm_list > 0) {
892  curr_sm_list = nn_sm_list;
893  } else if (count_n_sm_list > 0) {
894  curr_sm_list = n_sm_list;
895  skip_negated_content = 0;
896  } else {
897  return;
898  }
899 
900  int final_sm_list[nlists];
901  memset(&final_sm_list, 0, (nlists * sizeof(int)));
902 
903  int count_final_sm_list = 0;
904  int priority;
905 
907  while (tmp != NULL) {
908  for (priority = tmp->priority;
909  tmp != NULL && priority == tmp->priority;
910  tmp = tmp->next)
911  {
912  if (tmp->list_id >= nlists)
913  continue;
914  if (curr_sm_list[tmp->list_id] == 0)
915  continue;
916  final_sm_list[count_final_sm_list++] = tmp->list_id;
917  }
918  if (count_final_sm_list != 0)
919  break;
920  }
921 
922  BUG_ON(count_final_sm_list == 0);
923 
924  uint16_t max_len = 0;
925  for (int i = 0; i < count_final_sm_list; i++) {
926  if (final_sm_list[i] >= (int)s->init_data->smlists_array_size)
927  continue;
928 
929  for (sm = s->init_data->smlists[final_sm_list[i]]; sm != NULL; sm = sm->next) {
930  if (sm->type != DETECT_CONTENT)
931  continue;
932 
933  const DetectContentData *cd = (DetectContentData *)sm->ctx;
934  /* skip_negated_content is only set if there's absolutely no
935  * non-negated content present in the sig */
936  if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
937  continue;
938  if (max_len < cd->content_len)
939  max_len = cd->content_len;
940  }
941  }
942 
943  for (int i = 0; i < count_final_sm_list; i++) {
944  if (final_sm_list[i] >= (int)s->init_data->smlists_array_size)
945  continue;
946 
947  mpm_sm = GetMpmForList(s, final_sm_list[i], mpm_sm, max_len, skip_negated_content);
948  }
949 
950  /* assign to signature */
951  SetMpm(s, mpm_sm);
952  return;
953 }
954 
955 /** \internal
956  * \brief The hash function for MpmStore
957  *
958  * \param ht Pointer to the hash table.
959  * \param data Pointer to the MpmStore.
960  * \param datalen Not used in our case.
961  *
962  * \retval hash The generated hash value.
963  */
964 static uint32_t MpmStoreHashFunc(HashListTable *ht, void *data, uint16_t datalen)
965 {
966  const MpmStore *ms = (MpmStore *)data;
967  uint32_t hash = 0;
968  uint32_t b = 0;
969 
970  for (b = 0; b < ms->sid_array_size; b++)
971  hash += ms->sid_array[b];
972 
973  return hash % ht->array_size;
974 }
975 
976 /**
977  * \brief The Compare function for MpmStore
978  *
979  * \param data1 Pointer to the first MpmStore.
980  * \param len1 Not used.
981  * \param data2 Pointer to the second MpmStore.
982  * \param len2 Not used.
983  *
984  * \retval 1 If the 2 MpmStores sent as args match.
985  * \retval 0 If the 2 MpmStores sent as args do not match.
986  */
987 static char MpmStoreCompareFunc(void *data1, uint16_t len1, void *data2,
988  uint16_t len2)
989 {
990  const MpmStore *ms1 = (MpmStore *)data1;
991  const MpmStore *ms2 = (MpmStore *)data2;
992 
993  if (ms1->sid_array_size != ms2->sid_array_size)
994  return 0;
995 
996  if (ms1->buffer != ms2->buffer)
997  return 0;
998 
999  if (ms1->direction != ms2->direction)
1000  return 0;
1001 
1002  if (ms1->sm_list != ms2->sm_list)
1003  return 0;
1004 
1005  if (SCMemcmp(ms1->sid_array, ms2->sid_array,
1006  ms1->sid_array_size) != 0)
1007  {
1008  return 0;
1009  }
1010 
1011  return 1;
1012 }
1013 
1014 static void MpmStoreFreeFunc(void *ptr)
1015 {
1016  MpmStore *ms = ptr;
1017  if (ms != NULL) {
1018  if (ms->mpm_ctx != NULL && !(ms->mpm_ctx->flags & MPMCTX_FLAGS_GLOBAL))
1019  {
1020  SCLogDebug("destroying mpm_ctx %p", ms->mpm_ctx);
1022  SCFree(ms->mpm_ctx);
1023  }
1024  ms->mpm_ctx = NULL;
1025 
1026  SCFree(ms->sid_array);
1027  SCFree(ms);
1028  }
1029 }
1030 
1031 /**
1032  * \brief Initializes the MpmStore mpm hash table to be used by the detection
1033  * engine context.
1034  *
1035  * \param de_ctx Pointer to the detection engine context.
1036  *
1037  * \retval 0 On success.
1038  * \retval -1 On failure.
1039  */
1041 {
1043  MpmStoreHashFunc,
1044  MpmStoreCompareFunc,
1045  MpmStoreFreeFunc);
1046  if (de_ctx->mpm_hash_table == NULL)
1047  goto error;
1048 
1049  return 0;
1050 
1051 error:
1052  return -1;
1053 }
1054 
1055 /**
1056  * \brief Adds a MpmStore to the detection engine context MpmStore
1057  *
1058  * \param de_ctx Pointer to the detection engine context.
1059  * \param sgh Pointer to the MpmStore.
1060  *
1061  * \retval ret 0 on Successfully adding the argument sgh; -1 on failure.
1062  */
1063 static int MpmStoreAdd(DetectEngineCtx *de_ctx, MpmStore *s)
1064 {
1065  int ret = HashListTableAdd(de_ctx->mpm_hash_table, (void *)s, 0);
1066  return ret;
1067 }
1068 
1069 /**
1070  * \brief Used to lookup a MpmStore from the MpmStore
1071  *
1072  * \param de_ctx Pointer to the detection engine context.
1073  * \param sgh Pointer to the MpmStore.
1074  *
1075  * \retval rsgh On success a pointer to the MpmStore if the MpmStore is
1076  * found in the hash table; NULL on failure.
1077  */
1078 static MpmStore *MpmStoreLookup(DetectEngineCtx *de_ctx, MpmStore *s)
1079 {
1081  (void *)s, 0);
1082  return rs;
1083 }
1084 
1085 static const DetectBufferMpmRegistery *GetByMpmStore(const DetectEngineCtx *de_ctx,
1086  const MpmStore *ms)
1087 {
1089  while (am != NULL) {
1090  if (ms->sm_list == am->sm_list &&
1091  ms->direction == am->direction) {
1092  return am;
1093  }
1094  am = am->next;
1095  }
1096  am = de_ctx->pkt_mpms_list;
1097  while (am != NULL) {
1098  if (ms->sm_list == am->sm_list) {
1099  return am;
1100  }
1101  am = am->next;
1102  }
1103  return NULL;
1104 }
1105 
1107 {
1108  HashListTableBucket *htb = NULL;
1109 
1110  uint32_t stats[MPMB_MAX] = {0};
1111  int app_mpms_cnt = de_ctx->buffer_type_map_elements;
1112  uint32_t appstats[app_mpms_cnt + 1]; // +1 to silence scan-build
1113  memset(&appstats, 0x00, sizeof(appstats));
1114  int pkt_mpms_cnt = de_ctx->buffer_type_map_elements;
1115  uint32_t pktstats[pkt_mpms_cnt + 1]; // +1 to silence scan-build
1116  memset(&pktstats, 0x00, sizeof(pktstats));
1117 
1119  htb != NULL;
1120  htb = HashListTableGetListNext(htb))
1121  {
1122  const MpmStore *ms = (MpmStore *)HashListTableGetListData(htb);
1123  if (ms == NULL || ms->mpm_ctx == NULL) {
1124  continue;
1125  }
1126  if (ms->buffer < MPMB_MAX)
1127  stats[ms->buffer]++;
1128  else if (ms->sm_list != DETECT_SM_LIST_PMATCH) {
1129  const DetectBufferMpmRegistery *am = GetByMpmStore(de_ctx, ms);
1130  if (am != NULL) {
1131  switch (am->type) {
1133  SCLogDebug("%s: %u patterns. Min %u, Max %u. Ctx %p",
1134  am->name,
1135  ms->mpm_ctx->pattern_cnt,
1136  ms->mpm_ctx->minlen, ms->mpm_ctx->maxlen,
1137  ms->mpm_ctx);
1138  pktstats[am->sm_list]++;
1139  break;
1141  SCLogDebug("%s %s: %u patterns. Min %u, Max %u. Ctx %p",
1142  am->name,
1143  am->direction == SIG_FLAG_TOSERVER ? "toserver":"toclient",
1144  ms->mpm_ctx->pattern_cnt,
1145  ms->mpm_ctx->minlen, ms->mpm_ctx->maxlen,
1146  ms->mpm_ctx);
1147  appstats[am->sm_list]++;
1148  break;
1150  break;
1151  }
1152  }
1153  }
1154  }
1155 
1156  if (!(de_ctx->flags & DE_QUIET)) {
1157  for (int x = 0; x < MPMB_MAX; x++) {
1158  SCLogPerf("Builtin MPM \"%s\": %u", builtin_mpms[x], stats[x]);
1159  }
1161  while (am != NULL) {
1162  if (appstats[am->sm_list] > 0) {
1163  const char *name = am->name;
1164  const char *direction = am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient";
1165  SCLogPerf("AppLayer MPM \"%s %s (%s)\": %u", direction, name,
1166  AppProtoToString(am->app_v2.alproto), appstats[am->sm_list]);
1167  }
1168  am = am->next;
1169  }
1171  while (pm != NULL) {
1172  if (pktstats[pm->sm_list] > 0) {
1173  const char *name = pm->name;
1174  SCLogPerf("Pkt MPM \"%s\": %u", name, pktstats[pm->sm_list]);
1175  }
1176  pm = pm->next;
1177  }
1178  }
1179 }
1180 
1181 /**
1182  * \brief Frees the hash table - DetectEngineCtx->mpm_hash_table, allocated by
1183  * MpmStoreInit() function.
1184  *
1185  * \param de_ctx Pointer to the detection engine context.
1186  */
1188 {
1189  if (de_ctx->mpm_hash_table == NULL)
1190  return;
1191 
1193  de_ctx->mpm_hash_table = NULL;
1194  return;
1195 }
1196 
1197 static void MpmStoreSetup(const DetectEngineCtx *de_ctx, MpmStore *ms)
1198 {
1199  const Signature *s = NULL;
1200  uint32_t sig;
1201  int dir = 0;
1202 
1203  if (ms->buffer != MPMB_MAX) {
1205 
1206  switch (ms->buffer) {
1207  /* TS is 1 */
1208  case MPMB_TCP_PKT_TS:
1209  case MPMB_TCP_STREAM_TS:
1210  case MPMB_UDP_TS:
1211  dir = 1;
1212  break;
1213 
1214  /* TC is 0 */
1215  default:
1216  case MPMB_UDP_TC:
1217  case MPMB_TCP_STREAM_TC:
1218  case MPMB_TCP_PKT_TC:
1219  case MPMB_OTHERIP: /**< use 0 for other */
1220  dir = 0;
1221  break;
1222  }
1223  } else {
1225 
1226  if (ms->direction == SIG_FLAG_TOSERVER)
1227  dir = 1;
1228  else
1229  dir = 0;
1230  }
1231 
1233  if (ms->mpm_ctx == NULL)
1234  return;
1235 
1237 
1238  /* add the patterns */
1239  for (sig = 0; sig < (ms->sid_array_size * 8); sig++) {
1240  if (ms->sid_array[sig / 8] & (1 << (sig % 8))) {
1241  s = de_ctx->sig_array[sig];
1242  if (s == NULL)
1243  continue;
1244  if ((s->flags & ms->direction) == 0)
1245  continue;
1246  if (s->init_data->mpm_sm == NULL)
1247  continue;
1248  int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
1249  if (list < 0)
1250  continue;
1251  if (list != ms->sm_list)
1252  continue;
1253 
1254  SCLogDebug("adding %u", s->id);
1255 
1257 
1258  int skip = 0;
1259  /* negated logic: if mpm match can't be used to be sure about this
1260  * pattern, we have to inspect the rule fully regardless of mpm
1261  * match. So in this case there is no point of adding it at all.
1262  * The non-mpm list entry for the sig will make sure the sig is
1263  * inspected. */
1264  if ((cd->flags & DETECT_CONTENT_NEGATED) &&
1266  {
1267  skip = 1;
1268  SCLogDebug("not adding negated mpm as it's not 'single'");
1269  }
1270 
1271  if (!skip) {
1272  PopulateMpmHelperAddPattern(ms->mpm_ctx,
1273  cd, s, 0, (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP));
1274  }
1275  }
1276  }
1277 
1278  if (ms->mpm_ctx->pattern_cnt == 0) {
1280  ms->mpm_ctx = NULL;
1281  } else {
1283  if (mpm_table[ms->mpm_ctx->mpm_type].Prepare != NULL) {
1285  }
1286  }
1287  }
1288 }
1289 
1290 
1291 /** \brief Get MpmStore for a built-in buffer type
1292  *
1293  */
1295  enum MpmBuiltinBuffers buf)
1296 {
1297  const Signature *s = NULL;
1298  uint32_t sig;
1299  uint32_t cnt = 0;
1300  int direction = 0;
1301  uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
1302  uint8_t sids_array[max_sid];
1303  memset(sids_array, 0x00, max_sid);
1304  int sgh_mpm_context = 0;
1305  int sm_list = DETECT_SM_LIST_PMATCH;
1306 
1307  switch (buf) {
1308  case MPMB_TCP_PKT_TS:
1309  case MPMB_TCP_PKT_TC:
1310  sgh_mpm_context = de_ctx->sgh_mpm_context_proto_tcp_packet;
1311  break;
1312  case MPMB_TCP_STREAM_TS:
1313  case MPMB_TCP_STREAM_TC:
1314  sgh_mpm_context = de_ctx->sgh_mpm_context_stream;
1315  break;
1316  case MPMB_UDP_TS:
1317  case MPMB_UDP_TC:
1318  sgh_mpm_context = de_ctx->sgh_mpm_context_proto_udp_packet;
1319  break;
1320  case MPMB_OTHERIP:
1321  sgh_mpm_context = de_ctx->sgh_mpm_context_proto_other_packet;
1322  break;
1323  default:
1324  break;
1325  }
1326 
1327  switch(buf) {
1328  case MPMB_TCP_PKT_TS:
1329  case MPMB_TCP_STREAM_TS:
1330  case MPMB_UDP_TS:
1331  direction = SIG_FLAG_TOSERVER;
1332  break;
1333 
1334  case MPMB_TCP_PKT_TC:
1335  case MPMB_TCP_STREAM_TC:
1336  case MPMB_UDP_TC:
1337  direction = SIG_FLAG_TOCLIENT;
1338  break;
1339 
1340  case MPMB_OTHERIP:
1341  direction = (SIG_FLAG_TOCLIENT|SIG_FLAG_TOSERVER);
1342  break;
1343 
1344  case MPMB_MAX:
1345  BUG_ON(1);
1346  break;
1347  }
1348 
1349  for (sig = 0; sig < sgh->sig_cnt; sig++) {
1350  s = sgh->match_array[sig];
1351  if (s == NULL)
1352  continue;
1353 
1354  if (s->init_data->mpm_sm == NULL)
1355  continue;
1356 
1357  int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
1358  if (list < 0)
1359  continue;
1360 
1361  if (list != DETECT_SM_LIST_PMATCH)
1362  continue;
1363 
1364  switch (buf) {
1365  case MPMB_TCP_PKT_TS:
1366  case MPMB_TCP_PKT_TC:
1367  if (SignatureHasPacketContent(s) == 1)
1368  {
1369  sids_array[s->num / 8] |= 1 << (s->num % 8);
1370  cnt++;
1371  }
1372  break;
1373  case MPMB_TCP_STREAM_TS:
1374  case MPMB_TCP_STREAM_TC:
1375  if (SignatureHasStreamContent(s) == 1)
1376  {
1377  sids_array[s->num / 8] |= 1 << (s->num % 8);
1378  cnt++;
1379  }
1380  break;
1381  case MPMB_UDP_TS:
1382  case MPMB_UDP_TC:
1383  sids_array[s->num / 8] |= 1 << (s->num % 8);
1384  cnt++;
1385  break;
1386  case MPMB_OTHERIP:
1387  sids_array[s->num / 8] |= 1 << (s->num % 8);
1388  cnt++;
1389  break;
1390  default:
1391  break;
1392  }
1393  }
1394 
1395  if (cnt == 0)
1396  return NULL;
1397 
1398  MpmStore lookup = { sids_array, max_sid, direction, buf, sm_list, 0, NULL};
1399 
1400  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1401  if (result == NULL) {
1402  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1403  if (copy == NULL)
1404  return NULL;
1405  uint8_t *sids = SCCalloc(1, max_sid);
1406  if (sids == NULL) {
1407  SCFree(copy);
1408  return NULL;
1409  }
1410 
1411  memcpy(sids, sids_array, max_sid);
1412  copy->sid_array = sids;
1413  copy->sid_array_size = max_sid;
1414  copy->buffer = buf;
1415  copy->direction = direction;
1416  copy->sm_list = sm_list;
1417  copy->sgh_mpm_context = sgh_mpm_context;
1418 
1419  MpmStoreSetup(de_ctx, copy);
1420  MpmStoreAdd(de_ctx, copy);
1421  return copy;
1422  } else {
1423  return result;
1424  }
1425 }
1426 
1427 static MpmStore *MpmStorePrepareBufferAppLayer(DetectEngineCtx *de_ctx,
1428  SigGroupHead *sgh, const DetectBufferMpmRegistery *am)
1429 {
1430  const Signature *s = NULL;
1431  uint32_t sig;
1432  uint32_t cnt = 0;
1433  uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
1434  uint8_t sids_array[max_sid];
1435  memset(sids_array, 0x00, max_sid);
1436 
1437  SCLogDebug("handling %s direction %s for list %d", am->name,
1438  am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient",
1439  am->sm_list);
1440 
1441  for (sig = 0; sig < sgh->sig_cnt; sig++) {
1442  s = sgh->match_array[sig];
1443  if (s == NULL)
1444  continue;
1445 
1446  if (s->init_data->mpm_sm == NULL)
1447  continue;
1448 
1449  int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
1450  if (list < 0)
1451  continue;
1452 
1453  if ((s->flags & am->direction) == 0)
1454  continue;
1455 
1456  if (list != am->sm_list)
1457  continue;
1458 
1459  sids_array[s->num / 8] |= 1 << (s->num % 8);
1460  cnt++;
1461  }
1462 
1463  if (cnt == 0)
1464  return NULL;
1465 
1466  MpmStore lookup = { sids_array, max_sid, am->direction,
1467  MPMB_MAX, am->sm_list, 0, NULL};
1468  SCLogDebug("am->direction %d am->sm_list %d",
1469  am->direction, am->sm_list);
1470 
1471  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1472  if (result == NULL) {
1473  SCLogDebug("new unique mpm for %s %s: %u patterns",
1474  am->name,
1475  am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient",
1476  cnt);
1477 
1478  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1479  if (copy == NULL)
1480  return NULL;
1481  uint8_t *sids = SCCalloc(1, max_sid);
1482  if (sids == NULL) {
1483  SCFree(copy);
1484  return NULL;
1485  }
1486 
1487  memcpy(sids, sids_array, max_sid);
1488  copy->sid_array = sids;
1489  copy->sid_array_size = max_sid;
1490  copy->buffer = MPMB_MAX;
1491  copy->direction = am->direction;
1492  copy->sm_list = am->sm_list;
1493  copy->sgh_mpm_context = am->sgh_mpm_context;
1494 
1495  MpmStoreSetup(de_ctx, copy);
1496  MpmStoreAdd(de_ctx, copy);
1497  return copy;
1498  } else {
1499  SCLogDebug("using existing mpm %p", result);
1500  return result;
1501  }
1502  return NULL;
1503 }
1504 
1505 static MpmStore *MpmStorePrepareBufferPkt(DetectEngineCtx *de_ctx,
1506  SigGroupHead *sgh, const DetectBufferMpmRegistery *am)
1507 {
1508  const Signature *s = NULL;
1509  uint32_t sig;
1510  uint32_t cnt = 0;
1511  uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
1512  uint8_t sids_array[max_sid];
1513  memset(sids_array, 0x00, max_sid);
1514 
1515  SCLogDebug("handling %s for list %d", am->name,
1516  am->sm_list);
1517 
1518  for (sig = 0; sig < sgh->sig_cnt; sig++) {
1519  s = sgh->match_array[sig];
1520  if (s == NULL)
1521  continue;
1522 
1523  if (s->init_data->mpm_sm == NULL)
1524  continue;
1525 
1526  int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
1527  if (list < 0)
1528  continue;
1529 
1530  if (list != am->sm_list)
1531  continue;
1532 
1533  sids_array[s->num / 8] |= 1 << (s->num % 8);
1534  cnt++;
1535  }
1536 
1537  if (cnt == 0)
1538  return NULL;
1539 
1540  MpmStore lookup = { sids_array, max_sid, SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT,
1541  MPMB_MAX, am->sm_list, 0, NULL};
1542  SCLogDebug("am->sm_list %d", am->sm_list);
1543 
1544  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1545  if (result == NULL) {
1546  SCLogDebug("new unique mpm for %s: %u patterns",
1547  am->name, cnt);
1548 
1549  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1550  if (copy == NULL)
1551  return NULL;
1552  uint8_t *sids = SCCalloc(1, max_sid);
1553  if (sids == NULL) {
1554  SCFree(copy);
1555  return NULL;
1556  }
1557 
1558  memcpy(sids, sids_array, max_sid);
1559  copy->sid_array = sids;
1560  copy->sid_array_size = max_sid;
1561  copy->buffer = MPMB_MAX;
1563  copy->sm_list = am->sm_list;
1564  copy->sgh_mpm_context = am->sgh_mpm_context;
1565 
1566  MpmStoreSetup(de_ctx, copy);
1567  MpmStoreAdd(de_ctx, copy);
1568  return copy;
1569  } else {
1570  SCLogDebug("using existing mpm %p", result);
1571  return result;
1572  }
1573  return NULL;
1574 }
1575 
1576 static void SetRawReassemblyFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
1577 {
1578  const Signature *s = NULL;
1579  uint32_t sig;
1580 
1581  for (sig = 0; sig < sgh->sig_cnt; sig++) {
1582  s = sgh->match_array[sig];
1583  if (s == NULL)
1584  continue;
1585 
1586  if (SignatureHasStreamContent(s) == 1) {
1588  SCLogDebug("rule group %p has SIG_GROUP_HEAD_HAVERAWSTREAM set", sgh);
1589  return;
1590  }
1591  }
1592  SCLogDebug("rule group %p does NOT have SIG_GROUP_HEAD_HAVERAWSTREAM set", sgh);
1593 }
1594 
1595 static void PrepareAppMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
1596 {
1597  if (de_ctx->app_mpms_list_cnt == 0)
1598  return;
1599 
1600  sh->init->app_mpms = SCCalloc(de_ctx->app_mpms_list_cnt, sizeof(MpmCtx *));
1601  BUG_ON(sh->init->app_mpms == NULL);
1602 
1604  while (a != NULL) {
1605  if ((a->direction == SIG_FLAG_TOSERVER && SGH_DIRECTION_TS(sh)) ||
1607  {
1608  MpmStore *mpm_store = MpmStorePrepareBufferAppLayer(de_ctx, sh, a);
1609  if (mpm_store != NULL) {
1610  sh->init->app_mpms[a->id] = mpm_store->mpm_ctx;
1611 
1612  SCLogDebug("a %p a->name %s a->PrefilterRegisterWithListId %p "
1613  "mpm_store->mpm_ctx %p", a, a->name,
1614  a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
1615 
1616  /* if we have just certain types of negated patterns,
1617  * mpm_ctx can be NULL */
1618  if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
1620  sh, mpm_store->mpm_ctx,
1621  a, a->sm_list) != 0);
1622  SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
1623  }
1624  }
1625  }
1626  a = a->next;
1627  }
1628 }
1629 
1630 static void PreparePktMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
1631 {
1632  if (de_ctx->pkt_mpms_list_cnt == 0)
1633  return;
1634 
1635  sh->init->pkt_mpms = SCCalloc(de_ctx->pkt_mpms_list_cnt, sizeof(MpmCtx *));
1636  BUG_ON(sh->init->pkt_mpms == NULL);
1637 
1639  while (a != NULL) {
1640  MpmStore *mpm_store = MpmStorePrepareBufferPkt(de_ctx, sh, a);
1641  if (mpm_store != NULL) {
1642  sh->init->pkt_mpms[a->id] = mpm_store->mpm_ctx;
1643 
1644  SCLogDebug("a %p a->name %s a->reg->PrefilterRegisterWithListId %p "
1645  "mpm_store->mpm_ctx %p", a, a->name,
1646  a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
1647 
1648  /* if we have just certain types of negated patterns,
1649  * mpm_ctx can be NULL */
1650  if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
1652  sh, mpm_store->mpm_ctx,
1653  a, a->sm_list) != 0);
1654  SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
1655  }
1656  }
1657  a = a->next;
1658  }
1659 }
1660 
1661 /** \brief Prepare the pattern matcher ctx in a sig group head.
1662  *
1663  */
1665 {
1666  MpmStore *mpm_store = NULL;
1667  if (SGH_PROTO(sh, IPPROTO_TCP)) {
1668  if (SGH_DIRECTION_TS(sh)) {
1669  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_PKT_TS);
1670  if (mpm_store != NULL) {
1671  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
1672  }
1673 
1675  if (mpm_store != NULL) {
1676  PrefilterPktStreamRegister(de_ctx, sh, mpm_store->mpm_ctx);
1677  }
1678 
1679  SetRawReassemblyFlag(de_ctx, sh);
1680  }
1681  if (SGH_DIRECTION_TC(sh)) {
1682  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_PKT_TC);
1683  if (mpm_store != NULL) {
1684  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
1685  }
1686 
1688  if (mpm_store != NULL) {
1689  PrefilterPktStreamRegister(de_ctx, sh, mpm_store->mpm_ctx);
1690  }
1691 
1692  SetRawReassemblyFlag(de_ctx, sh);
1693  }
1694  } else if (SGH_PROTO(sh, IPPROTO_UDP)) {
1695  if (SGH_DIRECTION_TS(sh)) {
1696  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_UDP_TS);
1697  if (mpm_store != NULL) {
1698  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
1699  }
1700  }
1701  if (SGH_DIRECTION_TC(sh)) {
1702  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_UDP_TC);
1703  if (mpm_store != NULL) {
1704  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
1705  }
1706  }
1707  } else {
1708  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_OTHERIP);
1709  if (mpm_store != NULL) {
1710  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
1711  }
1712  }
1713 
1714  PrepareAppMpms(de_ctx, sh);
1715  PreparePktMpms(de_ctx, sh);
1716  return 0;
1717 }
1718 
1719 typedef struct DetectFPAndItsId_ {
1721  uint16_t content_len;
1722  uint32_t flags;
1723  int sm_list;
1724 
1725  uint8_t *content;
1727 
1728 /**
1729  * \brief Figured out the FP and their respective content ids for all the
1730  * sigs in the engine.
1731  *
1732  * \param de_ctx Detection engine context.
1733  *
1734  * \retval 0 On success.
1735  * \retval -1 On failure.
1736  */
1738 {
1739  uint32_t struct_total_size = 0;
1740  uint32_t content_total_size = 0;
1741  Signature *s = NULL;
1742 
1743  /* Count the amount of memory needed to store all the structures
1744  * and the content of those structures. This will over estimate the
1745  * true size, since duplicates are removed below, but counted here.
1746  */
1747  for (s = de_ctx->sig_list; s != NULL; s = s->next) {
1748  if (s->flags & SIG_FLAG_PREFILTER)
1749  continue;
1750 
1752  if (s->init_data->mpm_sm != NULL) {
1754  struct_total_size += sizeof(DetectFPAndItsId);
1755  content_total_size += cd->content_len;
1756 
1757  s->flags |= SIG_FLAG_PREFILTER;
1758  }
1759  }
1760  /* no rules */
1761  if (struct_total_size + content_total_size == 0)
1762  return 0;
1763 
1764  /* array hash buffer - I've run out of ideas to name it */
1765  uint8_t *ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
1766  if (unlikely(ahb == NULL))
1767  return -1;
1768 
1769  uint8_t *content = NULL;
1770  uint16_t content_len = 0;
1771  PatIntId max_id = 0;
1772  DetectFPAndItsId *struct_offset = (DetectFPAndItsId *)ahb;
1773  uint8_t *content_offset = ahb + struct_total_size;
1774 
1775  for (s = de_ctx->sig_list; s != NULL; s = s->next) {
1776  if (s->init_data->mpm_sm != NULL) {
1777  int sm_list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
1778  BUG_ON(sm_list == -1);
1779 
1781  DetectFPAndItsId *dup = (DetectFPAndItsId *)ahb;
1783  content = cd->content + cd->fp_chop_offset;
1784  content_len = cd->fp_chop_len;
1785  } else {
1786  content = cd->content;
1787  content_len = cd->content_len;
1788  }
1789  uint32_t flags = cd->flags & DETECT_CONTENT_NOCASE;
1790  /* Check for content already found on the same list */
1791  for (; dup != struct_offset; dup++) {
1792  if (dup->content_len != content_len)
1793  continue;
1794  if (dup->sm_list != sm_list)
1795  continue;
1796  if (dup->flags != flags)
1797  continue;
1798  /* Check for pattern matching a duplicate. Use case insensitive matching
1799  * for case insensitive patterns. */
1800  if (flags & DETECT_CONTENT_NOCASE) {
1801  if (SCMemcmpLowercase(dup->content, content, content_len) != 0)
1802  continue;
1803  } else {
1804  /* Case sensitive matching */
1805  if (SCMemcmp(dup->content, content, content_len) != 0)
1806  continue;
1807  }
1808  /* Found a match with a previous pattern. */
1809  break;
1810  }
1811  if (dup != struct_offset) {
1812  /* Exited for-loop before the end, so found an existing match.
1813  * Use its ID. */
1814  cd->id = dup->id;
1815  continue;
1816  }
1817 
1818  /* Not found, so new content. Give it a new ID and add it
1819  * to the array. Copy the content at the end of the
1820  * content array.
1821  */
1822  struct_offset->id = max_id++;
1823  cd->id = struct_offset->id;
1824  struct_offset->content_len = content_len;
1825  struct_offset->sm_list = sm_list;
1826  struct_offset->content = content_offset;
1827  struct_offset->flags = flags;
1828 
1829  content_offset += content_len;
1830 
1831  if (flags & DETECT_CONTENT_NOCASE) {
1832  /* Need to store case-insensitive patterns as lower case
1833  * because SCMemcmpLowercase() above assumes that all
1834  * patterns are stored lower case so that it doesn't
1835  * need to re-lower its first argument.
1836  */
1837  memcpy_tolower(struct_offset->content, content, content_len);
1838  } else {
1839  memcpy(struct_offset->content, content, content_len);
1840  }
1841 
1842  struct_offset++;
1843  } /* if (s->mpm_sm != NULL) */
1844  } /* for */
1845 
1846  de_ctx->max_fp_id = max_id;
1847 
1848  SCFree(ahb);
1849 
1850  return 0;
1851 }
MpmInitThreadCtx
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
Definition: util-mpm.c:249
DetectBufferMpmRegistery_::sm_list
int sm_list
Definition: detect.h:615
DETECT_CONTENT_NOCASE
#define DETECT_CONTENT_NOCASE
Definition: detect-content.h:29
SignatureHasPacketContent
int SignatureHasPacketContent(const Signature *s)
check if a signature has patterns that are to be inspected against a packets payload (as opposed to t...
Definition: detect-engine-mpm.c:545
DetectEngineCtx_::pkt_mpms_list_cnt
uint32_t pkt_mpms_list_cnt
Definition: detect.h:939
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:59
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:100
SCFPSupportSMList_
Definition: detect-fast-pattern.h:27
MPMB_UDP_TS
@ MPMB_UDP_TS
Definition: detect.h:1253
DetectBufferMpmRegistery_::direction
int direction
Definition: detect.h:614
DetectFPAndItsId_::flags
uint32_t flags
Definition: detect-engine-mpm.c:1722
detect-content.h
SGH_DIRECTION_TC
#define SGH_DIRECTION_TC(sgh)
Definition: detect-engine-mpm.c:779
MpmCtx_::mpm_type
uint8_t mpm_type
Definition: util-mpm.h:90
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:90
DETECT_CONTENT_FAST_PATTERN_CHOP
#define DETECT_CONTENT_FAST_PATTERN_CHOP
Definition: detect-content.h:36
PatternMatchDestroy
void PatternMatchDestroy(MpmCtx *mpm_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:663
MpmStore_::sid_array_size
uint32_t sid_array_size
Definition: detect.h:1261
DetectContentData_::fp_chop_len
uint16_t fp_chop_len
Definition: detect-content.h:91
MpmStore_::sid_array
uint8_t * sid_array
Definition: detect.h:1260
DetectFPAndItsId_
Definition: detect-engine-mpm.c:1719
DetectEngineCtx_::sgh_mpm_context_proto_tcp_packet
int32_t sgh_mpm_context_proto_tcp_packet
Definition: detect.h:852
SC_ERR_INVALID_VALUE
@ SC_ERR_INVALID_VALUE
Definition: util-error.h:160
PatternMatchPrepareGroup
int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
Prepare the pattern matcher ctx in a sig group head.
Definition: detect-engine-mpm.c:1664
SCFPSupportSMList_::next
struct SCFPSupportSMList_ * next
Definition: detect-fast-pattern.h:32
DetectPktMpmRegister
void DetectPktMpmRegister(const char *name, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id), InspectionBufferGetPktDataPtr GetData)
register a MPM engine
Definition: detect-engine-mpm.c:287
detect-engine-siggroup.h
SCFPSupportSMList_::list_id
int list_id
Definition: detect-fast-pattern.h:29
SigTableElmt_::name
const char * name
Definition: detect.h:1211
MpmStoreFree
void MpmStoreFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->mpm_hash_table, allocated by MpmStoreInit() function.
Definition: detect-engine-mpm.c:1187
MpmThreadCtx_
Definition: util-mpm.h:46
Signature_::num
SigIntId num
Definition: detect.h:538
ConfGetBool
int ConfGetBool(const char *name, int *val)
Retrieve a configuration value as an boolen.
Definition: conf.c:516
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1347
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectEngineTransforms
Definition: detect.h:376
MpmFactoryReClaimMpmCtx
void MpmFactoryReClaimMpmCtx(const DetectEngineCtx *de_ctx, MpmCtx *mpm_ctx)
Definition: util-mpm.c:208
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:59
MpmStoreReportStats
void MpmStoreReportStats(const DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:1106
PacketPatternCleanup
void PacketPatternCleanup(DetectEngineThreadCtx *det_ctx)
cleans up the mpm instance after a match
Definition: detect-engine-mpm.c:658
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
MPMB_OTHERIP
@ MPMB_OTHERIP
Definition: detect.h:1255
DetectEngineCtx_::max_fp_id
uint32_t max_fp_id
Definition: detect.h:834
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint16_t matcher)
Definition: util-mpm.c:254
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:73
DetectBufferMpmRegistery_::transforms
DetectEngineTransforms transforms
Definition: detect.h:624
DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED
#define DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED
Definition: detect-content.h:55
MpmStore_::sm_list
int sm_list
Definition: detect.h:1265
PatternStrength
uint32_t PatternStrength(uint8_t *pat, uint16_t patlen)
Predict a strength value for patterns.
Definition: detect-engine-mpm.c:699
detect-engine-dns.h
DetectSetFastPatternAndItsId
int DetectSetFastPatternAndItsId(DetectEngineCtx *de_ctx)
Figured out the FP and their respective content ids for all the sigs in the engine.
Definition: detect-engine-mpm.c:1737
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1111
InspectionBufferGetDataPtr
InspectionBuffer *(* InspectionBufferGetDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, const int list_id)
Definition: detect.h:382
PrefilterGenericMpmRegister
int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:611
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:30
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:767
DetectBufferMpmRegistery_::type
enum DetectBufferMpmType type
Definition: detect.h:618
util-memcpy.h
DETECT_CONTENT_MPM_IS_CONCLUSIVE
#define DETECT_CONTENT_MPM_IS_CONCLUSIVE(c)
Definition: detect-content.h:76
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:290
DetectFPAndItsId_::content_len
uint16_t content_len
Definition: detect-engine-mpm.c:1721
DETECT_CONTENT_DEPTH_VAR
#define DETECT_CONTENT_DEPTH_VAR
Definition: detect-content.h:46
InspectionBufferGetPktDataPtr
InspectionBuffer *(* InspectionBufferGetPktDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Packet *p, const int list_id)
Definition: detect.h:456
DetectMpmInitializeBuiltinMpms
void DetectMpmInitializeBuiltinMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:475
SIG_FLAG_REQUIRE_STREAM
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:224
DE_QUIET
#define DE_QUIET
Definition: detect.h:294
MpmCtx_::maxlen
uint16_t maxlen
Definition: util-mpm.h:100
MPMB_TCP_STREAM_TS
@ MPMB_TCP_STREAM_TS
Definition: detect.h:1251
PatIntId
#define PatIntId
Definition: suricata-common.h:300
DetectBufferMpmRegistery_
one time registration of keywords at start up
Definition: detect.h:611
SIG_GROUP_HEAD_HAVERAWSTREAM
#define SIG_GROUP_HEAD_HAVERAWSTREAM
Definition: detect.h:1239
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:581
DetectContentData_
Definition: detect-content.h:86
DetectContentData_::fp_chop_offset
uint16_t fp_chop_offset
Definition: detect-content.h:93
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:248
detect-engine-payload.h
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:237
MPMB_MAX
@ MPMB_MAX
Definition: detect.h:1256
DetectEngineCtx_::mpm_matcher
uint16_t mpm_matcher
Definition: detect.h:816
DetectEngineCtx_::sgh_mpm_context_proto_udp_packet
int32_t sgh_mpm_context_proto_udp_packet
Definition: detect.h:853
ShortenString
void ShortenString(const char *input, char *output, size_t output_size, char c)
Definition: util-misc.c:219
MPMB_TCP_STREAM_TC
@ MPMB_TCP_STREAM_TC
Definition: detect.h:1252
detect-engine-prefilter.h
DetectFPAndItsId_::content
uint8_t * content
Definition: detect-engine-mpm.c:1725
DetectBufferMpmRegistery_::id
int id
Definition: detect.h:617
MpmBuiltinBuffers
MpmBuiltinBuffers
Definition: detect.h:1248
DetectEngineCtx_::app_mpms_list
DetectBufferMpmRegistery * app_mpms_list
Definition: detect.h:935
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:880
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:116
detect-udphdr.h
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
HashListTable_::array_size
uint32_t array_size
Definition: util-hashlist.h:41
DetectAppLayerMpmRegisterByParentId
void DetectAppLayerMpmRegisterByParentId(DetectEngineCtx *de_ctx, const int id, const int parent_id, DetectEngineTransforms *transforms)
copy a mpm engine from parent_id, add in transforms
Definition: detect-engine-mpm.c:144
util-memcmp.h
SigGroupHeadInitData_::pkt_mpms
MpmCtx ** pkt_mpms
Definition: detect.h:1336
DetectBufferMpmRegistery_::sgh_mpm_context
int sgh_mpm_context
Definition: detect.h:619
Signature_::next
struct Signature_ * next
Definition: detect.h:600
DetectEngineCtx_::sgh_mpm_context_proto_other_packet
int32_t sgh_mpm_context_proto_other_packet
Definition: detect.h:854
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:330
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:58
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:236
HashListTableInit
HashListTable * HashListTableInit(uint32_t size, uint32_t(*Hash)(struct HashListTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hashlist.c:35
decode.h
util-debug.h
DetectFPAndItsId
struct DetectFPAndItsId_ DetectFPAndItsId
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
MpmFactoryGetMpmCtxForProfile
MpmCtx * MpmFactoryGetMpmCtxForProfile(const DetectEngineCtx *de_ctx, int32_t id, int direction)
Definition: util-mpm.c:186
DetectMpmInitializePktMpms
void DetectMpmInitializePktMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:374
MPM_PATTERN_CTX_OWNS_ID
#define MPM_PATTERN_CTX_OWNS_ID
Definition: util-mpm.h:139
DetectEngineThreadCtx_
Definition: detect.h:1010
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
MpmStore_
Definition: detect.h:1259
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:500
DetectBufferMpmRegistery_::PrefilterRegisterWithListId
int(* PrefilterRegisterWithListId)(struct DetectEngineCtx_ *de_ctx, struct SigGroupHead_ *sgh, MpmCtx *mpm_ctx, const struct DetectBufferMpmRegistery_ *mpm_reg, int list_id)
Definition: detect.h:621
DetectEngineGetMaxSigId
#define DetectEngineGetMaxSigId(de_ctx)
Definition: detect-engine.h:83
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
detect-engine-mpm.h
detect.h
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:324
DETECT_CONTENT_IS_SINGLE
#define DETECT_CONTENT_IS_SINGLE(c)
Definition: detect-content.h:66
DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_NEGATED
Definition: detect-content.h:40
PatternMatchThreadPrepare
void PatternMatchThreadPrepare(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:680
SigGroupHead_::init
SigGroupHeadInitData * init
Definition: detect.h:1375
DetectContentData_::id
PatIntId id
Definition: detect-content.h:98
MpmCtx_::minlen
uint16_t minlen
Definition: util-mpm.h:99
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:323
DetectProto_::proto
uint8_t proto[256/8]
Definition: detect-engine-proto.h:37
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:282
sm_fp_support_smlist_list
SCFPSupportSMList * sm_fp_support_smlist_list
Definition: detect-fast-pattern.c:52
SigGroupHead_::sig_cnt
SigIntId sig_cnt
Definition: detect.h:1352
MpmStore_::direction
int direction
Definition: detect.h:1263
PmqReset
void PmqReset(PrefilterRuleStore *)
Reset a Pmq for reusage. Meant to be called after a single search.
Definition: util-prefilter.c:101
MPMCTX_FLAGS_GLOBAL
#define MPMCTX_FLAGS_GLOBAL
Definition: util-mpm.h:85
DetectBufferMpmRegistery_::name
const char * name
Definition: detect.h:612
Signature_::flags
uint32_t flags
Definition: detect.h:529
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:99
stream.h
PatternMatchThreadPrint
void PatternMatchThreadPrint(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:669
DetectEngineCtx_::sgh_mpm_context_stream
int32_t sgh_mpm_context_stream
Definition: detect.h:855
conf.h
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:97
PrefilterPktPayloadRegister
int PrefilterPktPayloadRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx)
Definition: detect-engine-payload.c:130
DETECT_BUFFER_MPM_TYPE_PKT
@ DETECT_BUFFER_MPM_TYPE_PKT
Definition: detect.h:604
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:161
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:597
FastPatternSupportEnabledForSigMatchList
int FastPatternSupportEnabledForSigMatchList(const DetectEngineCtx *de_ctx, const int list_id)
Checks if a particular list(Signature->sm_lists[]) is in the list of lists that need to be searched f...
Definition: detect-fast-pattern.c:63
SignatureInitData_::smlists
struct SigMatch_ ** smlists
Definition: detect.h:522
SCFPSupportSMList_::priority
int priority
Definition: detect-fast-pattern.h:30
HashListTable_
Definition: util-hashlist.h:37
DetectEngineTransforms::transforms
TransformData transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:377
SigGroupHeadInitData_::app_mpms
MpmCtx ** app_mpms
Definition: detect.h:1335
MpmAddPatternCS
int MpmAddPatternCS(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
Definition: util-mpm.c:295
SC_ERR_INVALID_YAML_CONF_ENTRY
@ SC_ERR_INVALID_YAML_CONF_ENTRY
Definition: util-error.h:169
SGH_DIRECTION_TS
#define SGH_DIRECTION_TS(sgh)
Definition: detect-engine-mpm.c:778
MpmStore_::mpm_ctx
MpmCtx * mpm_ctx
Definition: detect.h:1268
MPM_TABLE_SIZE
@ MPM_TABLE_SIZE
Definition: util-mpm.h:40
detect-fast-pattern.h
MpmStorePrepareBuffer
MpmStore * MpmStorePrepareBuffer(DetectEngineCtx *de_ctx, SigGroupHead *sgh, enum MpmBuiltinBuffers buf)
Get MpmStore for a built-in buffer type.
Definition: detect-engine-mpm.c:1294
DetectBufferMpmRegistery_::priority
int priority
Definition: detect.h:616
DetectAppLayerMpmRegister2
void DetectAppLayerMpmRegister2(const char *name, int direction, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id), InspectionBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
register a MPM engine
Definition: detect-engine-mpm.c:89
MPMB_TCP_PKT_TC
@ MPMB_TCP_PKT_TC
Definition: detect.h:1250
SigGroupHead_::match_array
Signature ** match_array
Definition: detect.h:1372
SignatureHasStreamContent
int SignatureHasStreamContent(const Signature *s)
check if a signature has patterns that are to be inspected against the stream payload (as opposed to ...
Definition: detect-engine-mpm.c:581
util-mpm.h
DetectBufferMpmRegistery_::pname
char pname[32]
Definition: detect.h:613
flags
uint8_t flags
Definition: decode-gre.h:0
Signature_::proto
DetectProto proto
Definition: detect.h:545
MpmStoreInit
int MpmStoreInit(DetectEngineCtx *de_ctx)
Initializes the MpmStore mpm hash table to be used by the detection engine context.
Definition: detect-engine-mpm.c:1040
suricata-common.h
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:97
DETECT_BUFFER_MPM_TYPE_APP
@ DETECT_BUFFER_MPM_TYPE_APP
Definition: detect.h:605
DetectBufferTypeSupportsMpm
void DetectBufferTypeSupportsMpm(const char *name)
Definition: detect-engine.c:860
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:82
SupportFastPatternForSigMatchList
void SupportFastPatternForSigMatchList(int list_id, int priority)
Lets one add a sm list id to be searched for potential fp supported keywords later.
Definition: detect-fast-pattern.c:93
ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE
@ ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE
Definition: detect.h:971
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:73
PatternMatchDefaultMatcher
uint16_t PatternMatchDefaultMatcher(void)
Function to return the multi pattern matcher algorithm to be used by the engine, based on the mpm-alg...
Definition: detect-engine-mpm.c:615
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:224
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:87
FatalError
#define FatalError(x,...)
Definition: util-debug.h:532
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:773
DetectMpmPreparePktMpms
int DetectMpmPreparePktMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for applayer buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:429
TransformData_::transform
int transform
Definition: detect.h:372
util-validate.h
detect-flow.h
DetectEngineCtx_::app_mpms_list_cnt
uint32_t app_mpms_list_cnt
Definition: detect.h:936
DetectBufferTypeSupportsTransformations
void DetectBufferTypeSupportsTransformations(const char *name)
Definition: detect-engine.c:870
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
DetectEngineCtx_::sgh_mpm_context
uint8_t sgh_mpm_context
Definition: detect.h:829
DetectBufferMpmRegistery_::app_v2
struct DetectBufferMpmRegistery_::@93::@95 app_v2
builtin_mpms
const char * builtin_mpms[]
Definition: detect-engine-mpm.c:66
DetectEngineCtx_::mpm_hash_table
HashListTable * mpm_hash_table
Definition: detect.h:808
MPMB_UDP_TC
@ MPMB_UDP_TC
Definition: detect.h:1254
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:145
SigMatchListSMBelongsTo
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
Definition: detect-parse.c:625
SigGroupHead_::flags
uint32_t flags
Definition: detect.h:1348
SCFree
#define SCFree(p)
Definition: util-mem.h:61
MPM_CTX_FACTORY_UNIQUE_CONTEXT
#define MPM_CTX_FACTORY_UNIQUE_CONTEXT
Definition: util-mpm.h:113
DetectMpmPrepareBuiltinMpms
int DetectMpmPrepareBuiltinMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for builtin buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:488
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
Signature_::id
uint32_t id
Definition: detect.h:561
HashListTableBucket_
Definition: util-hashlist.h:28
detect-tcphdr.h
mpm_default_matcher
int mpm_default_matcher
Definition: util-mpm.c:49
DETECT_CONTENT_MPM
#define DETECT_CONTENT_MPM
Definition: detect-content.h:61
detect-engine-iponly.h
detect-parse.h
Signature_
Signature container.
Definition: detect.h:528
SigMatch_
a single match condition for a signature
Definition: detect.h:320
MPMB_TCP_PKT_TS
@ MPMB_TCP_PKT_TS
Definition: detect.h:1249
DetectEngineCtx_::buffer_type_map_elements
uint32_t buffer_type_map_elements
Definition: detect.h:925
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:48
MpmFactoryRegisterMpmCtxProfile
int32_t MpmFactoryRegisterMpmCtxProfile(DetectEngineCtx *de_ctx, const char *name)
Register a new Mpm Context.
Definition: util-mpm.c:58
app-layer-protos.h
DetectEngineCtx_::pkt_mpms_list
DetectBufferMpmRegistery * pkt_mpms_list
Definition: detect.h:938
DetectMpmInitializeAppMpms
void DetectMpmInitializeAppMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:208
DetectEngineTransforms::cnt
int cnt
Definition: detect.h:378
suricata.h
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:782
DETECT_BUFFER_MPM_TYPE_SIZE
@ DETECT_BUFFER_MPM_TYPE_SIZE
Definition: detect.h:607
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:88
DetectFPAndItsId_::id
PatIntId id
Definition: detect-engine-mpm.c:1720
PrefilterGenericMpmPktRegister
int PrefilterGenericMpmPktRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:681
DetectBufferMpmRegistery_::pkt_v1
struct DetectBufferMpmRegistery_::@93::@96 pkt_v1
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:768
MpmTableElmt_::DestroyThreadCtx
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:146
SC_ERR_INITIALIZATION
@ SC_ERR_INITIALIZATION
Definition: util-error.h:75
MpmCtx_
Definition: util-mpm.h:88
SGH_PROTO
#define SGH_PROTO(sgh, p)
Definition: detect-engine-mpm.c:777
DETECT_CONTENT_REPLACE
#define DETECT_CONTENT_REPLACE
Definition: detect-content.h:51
util-misc.h
flow.h
MpmCtx_::flags
uint8_t flags
Definition: util-mpm.h:92
DetectPktMpmRegisterByParentId
void DetectPktMpmRegisterByParentId(DetectEngineCtx *de_ctx, const int id, const int parent_id, DetectEngineTransforms *transforms)
copy a mpm engine from parent_id, add in transforms
Definition: detect-engine-mpm.c:338
DETECT_CONTENT_FAST_PATTERN
#define DETECT_CONTENT_FAST_PATTERN
Definition: detect-content.h:34
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-enum.h
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
MpmAddPatternCI
int MpmAddPatternCI(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
Definition: util-mpm.c:304
flow-var.h
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:369
DetectMpmPrepareAppMpms
int DetectMpmPrepareAppMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for applayer buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:262
MpmStore_::sgh_mpm_context
int32_t sgh_mpm_context
Definition: detect.h:1266
SIG_FLAG_PREFILTER
#define SIG_FLAG_PREFILTER
Definition: detect.h:243
PatternMatchThreadDestroy
void PatternMatchThreadDestroy(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:674
DetectFPAndItsId_::sm_list
int sm_list
Definition: detect-engine-mpm.c:1723
MpmStore_::buffer
enum MpmBuiltinBuffers buffer
Definition: detect.h:1264
RetrieveFPForSig
void RetrieveFPForSig(const DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine-mpm.c:844
PrefilterPktStreamRegister
int PrefilterPktStreamRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx)
Definition: detect-engine-payload.c:109
DetectBufferMpmRegistery_::next
struct DetectBufferMpmRegistery_ * next
Definition: detect.h:643
DETECT_CONTENT_OFFSET_VAR
#define DETECT_CONTENT_OFFSET_VAR
Definition: detect-content.h:45
SignatureInitData_::smlists_array_size
uint32_t smlists_array_size
Definition: detect.h:520
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:223