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