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