suricata
detect-engine-mpm.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 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 
57 #include "stream.h"
58 
59 #include "util-misc.h"
60 #include "util-enum.h"
61 #include "util-debug.h"
62 #include "util-print.h"
63 #include "util-validate.h"
64 
65 const char *builtin_mpms[] = {
66  "toserver TCP packet",
67  "toclient TCP packet",
68  "toserver TCP stream",
69  "toclient TCP stream",
70  "toserver UDP packet",
71  "toclient UDP packet",
72  "other IP packet",
73 
74  NULL };
75 
76 /* Registry for mpm keywords
77  *
78  * Keywords are registered at engine start up
79  */
80 
81 static DetectBufferMpmRegistery *g_mpm_list[DETECT_BUFFER_MPM_TYPE_SIZE] = { NULL, NULL, NULL };
82 static int g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_SIZE] = { 0, 0, 0 };
83 
84 /** \brief register a MPM engine
85  *
86  * \note to be used at start up / registration only. Errors are fatal.
87  */
88 void DetectAppLayerMpmRegister2(const char *name,
89  int direction, int priority,
90  int (*PrefilterRegister)(DetectEngineCtx *de_ctx,
91  SigGroupHead *sgh, MpmCtx *mpm_ctx,
92  const DetectBufferMpmRegistery *mpm_reg, int list_id),
94  AppProto alproto, int tx_min_progress)
95 {
96  SCLogDebug("registering %s/%d/%d/%p/%p/%u/%d", name, direction, priority,
97  PrefilterRegister, GetData, alproto, tx_min_progress);
98 
99  BUG_ON(tx_min_progress >= 48);
100 
101  if (PrefilterRegister == PrefilterGenericMpmRegister && GetData == NULL) {
102  // must register GetData with PrefilterGenericMpmRegister
103  abort();
104  }
105 
108  int sm_list = DetectBufferTypeGetByName(name);
109  if (sm_list == -1) {
111  "MPM engine registration for %s failed", name);
112  }
113 
114  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
115  BUG_ON(am == NULL);
116  am->name = name;
117  snprintf(am->pname, sizeof(am->pname), "%s", am->name);
118  am->direction = direction;
119  DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > INT16_MAX);
120  am->sm_list = sm_list;
121  am->sm_list_base = sm_list;
122  am->priority = priority;
124 
125  am->PrefilterRegisterWithListId = PrefilterRegister;
126  am->app_v2.GetData = GetData;
127  am->app_v2.alproto = alproto;
128  am->app_v2.tx_min_progress = tx_min_progress;
129 
130  if (g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP] == NULL) {
131  g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP] = am;
132  } else {
134  while (t->next != NULL) {
135  t = t->next;
136  }
137 
138  t->next = am;
139  am->id = t->id + 1;
140  }
141  g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_APP]++;
142 
143  SupportFastPatternForSigMatchList(sm_list, priority);
144 }
145 
146 /** \brief copy a mpm engine from parent_id, add in transforms */
148  const int id, const int parent_id,
149  DetectEngineTransforms *transforms)
150 {
151  SCLogDebug("registering %d/%d", id, parent_id);
152 
154  while (t) {
155  if (t->sm_list == parent_id) {
156  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
157  BUG_ON(am == NULL);
158  am->name = t->name;
159  am->direction = t->direction;
160  DEBUG_VALIDATE_BUG_ON(id < 0 || id > INT16_MAX);
161  am->sm_list = id; // use new id
162  am->sm_list_base = t->sm_list;
165  am->app_v2.GetData = t->app_v2.GetData;
166  am->app_v2.alproto = t->app_v2.alproto;
167  am->app_v2.tx_min_progress = t->app_v2.tx_min_progress;
168  am->priority = t->priority;
171  am->next = t->next;
172  if (transforms) {
173  memcpy(&am->transforms, transforms, sizeof(*transforms));
174 
175  /* create comma separated string of the names of the
176  * transforms and then shorten it if necessary. Finally
177  * use it to construct the 'profile' name for the engine */
178  char xforms[1024] = "";
179  for (int i = 0; i < transforms->cnt; i++) {
180  char ttstr[64];
181  (void)snprintf(ttstr,sizeof(ttstr), "%s,",
182  sigmatch_table[transforms->transforms[i].transform].name);
183  strlcat(xforms, ttstr, sizeof(xforms));
184  }
185  xforms[strlen(xforms)-1] = '\0';
186 
187  size_t space = sizeof(am->pname) - strlen(am->name) - 3;
188  char toprint[space + 1];
189  memset(toprint, 0x00, space + 1);
190  if (space < strlen(xforms)) {
191  ShortenString(xforms, toprint, space, '~');
192  } else {
193  strlcpy(toprint, xforms,sizeof(toprint));
194  }
195  (void)snprintf(am->pname, sizeof(am->pname), "%s#%d (%s)",
196  am->name, id, toprint);
197  } else {
198  (void)snprintf(am->pname, sizeof(am->pname), "%s#%d",
199  am->name, id);
200  }
201  am->id = de_ctx->app_mpms_list_cnt++;
202 
204  t->next = am;
205  SCLogDebug("copied mpm registration for %s id %u "
206  "with parent %u and GetData %p",
207  t->name, id, parent_id, am->app_v2.GetData);
208  t = am;
209  }
210  t = t->next;
211  }
212 }
213 
215 {
216  const DetectBufferMpmRegistery *list = g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP];
217  while (list != NULL) {
218  DetectBufferMpmRegistery *n = SCCalloc(1, sizeof(*n));
219  BUG_ON(n == NULL);
220 
221  *n = *list;
222  n->next = NULL;
223 
224  if (de_ctx->app_mpms_list == NULL) {
225  de_ctx->app_mpms_list = n;
226  } else {
228  while (t->next != NULL) {
229  t = t->next;
230  }
231  t->next = n;
232  }
233 
234  /* default to whatever the global setting is */
236 
237  /* see if we use a unique or shared mpm ctx for this type */
238  int confshared = 0;
239  char confstring[256] = "detect.mpm.";
240  strlcat(confstring, n->name, sizeof(confstring));
241  strlcat(confstring, ".shared", sizeof(confstring));
242  if (ConfGetBool(confstring, &confshared) == 1)
243  shared = confshared;
244 
245  if (shared == 0) {
246  if (!(de_ctx->flags & DE_QUIET)) {
247  SCLogPerf("using unique mpm ctx' for %s", n->name);
248  }
250  } else {
251  if (!(de_ctx->flags & DE_QUIET)) {
252  SCLogPerf("using shared mpm ctx' for %s", n->name);
253  }
255  }
256 
257  list = list->next;
258  }
260  SCLogDebug("mpm: de_ctx app_mpms_list %p %u",
262 }
263 
264 /**
265  * \brief initialize mpm contexts for applayer buffers that are in
266  * "single or "shared" mode.
267  */
269 {
270  int r = 0;
272  while (am != NULL) {
273  int dir = (am->direction == SIG_FLAG_TOSERVER) ? 1 : 0;
274 
276  {
278  if (mpm_ctx != NULL) {
279  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
280  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
281  }
282  }
283  }
284  am = am->next;
285  }
286  return r;
287 }
288 
289 /** \brief register a MPM engine
290  *
291  * \note to be used at start up / registration only. Errors are fatal.
292  */
293 void DetectFrameMpmRegister(const char *name, int direction, int priority,
294  int (*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
295  const DetectBufferMpmRegistery *mpm_reg, int list_id),
296  AppProto alproto, uint8_t type)
297 {
298  SCLogDebug("registering %s/%d/%p/%s/%u", name, priority, PrefilterRegister,
299  AppProtoToString(alproto), type);
300 
304  int sm_list = DetectBufferTypeGetByName(name);
305  if (sm_list == -1) {
306  FatalError(SC_ERR_INITIALIZATION, "MPM engine registration for %s failed", name);
307  }
308 
309  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
310  BUG_ON(am == NULL);
311  am->name = name;
312  snprintf(am->pname, sizeof(am->pname), "%s", am->name);
313  am->sm_list = sm_list;
314  am->direction = direction;
315  am->priority = priority;
317 
318  am->PrefilterRegisterWithListId = PrefilterRegister;
319  am->frame_v1.alproto = alproto;
320  am->frame_v1.type = type;
321  SCLogDebug("type %u", type);
322  SCLogDebug("am type %u", am->frame_v1.type);
323 
324  if (g_mpm_list[DETECT_BUFFER_MPM_TYPE_FRAME] == NULL) {
325  g_mpm_list[DETECT_BUFFER_MPM_TYPE_FRAME] = am;
326  } else {
328  while (t->next != NULL) {
329  t = t->next;
330  }
331  t->next = am;
332  am->id = t->id + 1;
333  }
334  g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_FRAME]++;
335 
336  SupportFastPatternForSigMatchList(sm_list, priority);
337  SCLogDebug("%s/%d done", name, sm_list);
338 }
339 
340 /** \brief copy a mpm engine from parent_id, add in transforms */
341 void DetectFrameMpmRegisterByParentId(DetectEngineCtx *de_ctx, const int id, const int parent_id,
342  DetectEngineTransforms *transforms)
343 {
344  SCLogDebug("registering %d/%d", id, parent_id);
345 
347  while (t) {
348  if (t->sm_list == parent_id) {
349  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
350  BUG_ON(am == NULL);
351  am->name = t->name;
352  snprintf(am->pname, sizeof(am->pname), "%s#%d", am->name, id);
353  am->sm_list = id; // use new id
354  am->sm_list_base = t->sm_list;
357  am->frame_v1 = t->frame_v1;
358  SCLogDebug("am type %u", am->frame_v1.type);
359  am->priority = t->priority;
360  am->direction = t->direction;
362  am->next = t->next;
363  if (transforms) {
364  memcpy(&am->transforms, transforms, sizeof(*transforms));
365  }
366  am->id = de_ctx->frame_mpms_list_cnt++;
367 
369  t->next = am;
370  SCLogDebug("copied mpm registration for %s id %u "
371  "with parent %u",
372  t->name, id, parent_id);
373  t = am;
374  }
375  t = t->next;
376  }
377 }
378 
379 void DetectEngineFrameMpmRegister(DetectEngineCtx *de_ctx, const char *name, int direction,
380  int priority,
381  int (*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
382  const DetectBufferMpmRegistery *mpm_reg, int list_id),
383  AppProto alproto, uint8_t type)
384 {
385  SCLogDebug("registering %s/%d/%p/%s/%u", name, priority, PrefilterRegister,
386  AppProtoToString(alproto), type);
387 
388  const int sm_list = DetectEngineBufferTypeRegister(de_ctx, name);
389  if (sm_list < 0) {
390  FatalError(SC_ERR_INITIALIZATION, "MPM engine registration for %s failed", name);
391  }
392 
396 
397  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
398  BUG_ON(am == NULL);
399  am->name = name;
400  snprintf(am->pname, sizeof(am->pname), "%s", am->name);
401  am->sm_list = sm_list;
402  am->direction = direction;
403  am->priority = priority;
405 
406  am->PrefilterRegisterWithListId = PrefilterRegister;
407  am->frame_v1.alproto = alproto;
408  am->frame_v1.type = type;
409 
410  // TODO is it ok to do this here?
411 
412  /* default to whatever the global setting is */
414  /* see if we use a unique or shared mpm ctx for this type */
415  int confshared = 0;
416  if (ConfGetBool("detect.mpm.frame.shared", &confshared) == 1)
417  shared = confshared;
418 
419  if (shared == 0) {
421  } else {
423  }
424 
425  if (de_ctx->frame_mpms_list == NULL) {
426  de_ctx->frame_mpms_list = am;
427  } else {
429  while (t->next != NULL) {
430  t = t->next;
431  }
432 
433  t->next = am;
434  }
436 
437  DetectEngineRegisterFastPatternForId(de_ctx, sm_list, priority);
438  SCLogDebug("%s/%d done", name, sm_list);
439 }
440 
442 {
443  const DetectBufferMpmRegistery *list = g_mpm_list[DETECT_BUFFER_MPM_TYPE_FRAME];
444  while (list != NULL) {
445  DetectBufferMpmRegistery *n = SCCalloc(1, sizeof(*n));
446  BUG_ON(n == NULL);
447 
448  *n = *list;
449  n->next = NULL;
450 
451  if (de_ctx->frame_mpms_list == NULL) {
452  de_ctx->frame_mpms_list = n;
453  } else {
455  while (t->next != NULL) {
456  t = t->next;
457  }
458 
459  t->next = n;
460  }
461 
462  /* default to whatever the global setting is */
464 
465  /* see if we use a unique or shared mpm ctx for this type */
466  int confshared = 0;
467  char confstring[256] = "detect.mpm.";
468  strlcat(confstring, n->name, sizeof(confstring));
469  strlcat(confstring, ".shared", sizeof(confstring));
470  if (ConfGetBool(confstring, &confshared) == 1)
471  shared = confshared;
472 
473  if (shared == 0) {
474  if (!(de_ctx->flags & DE_QUIET)) {
475  SCLogPerf("using unique mpm ctx' for %s", n->name);
476  }
478  } else {
479  if (!(de_ctx->flags & DE_QUIET)) {
480  SCLogPerf("using shared mpm ctx' for %s", n->name);
481  }
483  }
484 
485  list = list->next;
486  }
488  SCLogDebug("mpm: de_ctx frame_mpms_list %p %u", de_ctx->frame_mpms_list,
490 }
491 
492 /**
493  * \brief initialize mpm contexts for applayer buffers that are in
494  * "single or "shared" mode.
495  */
497 {
498  SCLogDebug("preparing frame mpm");
499  int r = 0;
501  while (am != NULL) {
502  SCLogDebug("am %p %s sgh_mpm_context %d", am, am->name, am->sgh_mpm_context);
503  SCLogDebug("%s", am->name);
505  int dir = (am->direction == SIG_FLAG_TOSERVER) ? 1 : 0;
507  SCLogDebug("%s: %d mpm_Ctx %p", am->name, r, mpm_ctx);
508  if (mpm_ctx != NULL) {
509  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
510  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
511  SCLogDebug("%s: %d", am->name, r);
512  }
513  }
514  }
515  am = am->next;
516  }
517  return r;
518 }
519 
520 /** \brief register a MPM engine
521  *
522  * \note to be used at start up / registration only. Errors are fatal.
523  */
524 void DetectPktMpmRegister(const char *name,
525  int priority,
526  int (*PrefilterRegister)(DetectEngineCtx *de_ctx,
527  SigGroupHead *sgh, MpmCtx *mpm_ctx,
528  const DetectBufferMpmRegistery *mpm_reg, int list_id),
530 {
531  SCLogDebug("registering %s/%d/%p/%p", name, priority,
532  PrefilterRegister, GetData);
533 
534  if (PrefilterRegister == PrefilterGenericMpmPktRegister && GetData == NULL) {
535  // must register GetData with PrefilterGenericMpmRegister
536  abort();
537  }
538 
541  int sm_list = DetectBufferTypeGetByName(name);
542  if (sm_list == -1) {
544  "MPM engine registration for %s failed", name);
545  }
546 
547  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
548  BUG_ON(am == NULL);
549  am->name = name;
550  snprintf(am->pname, sizeof(am->pname), "%s", am->name);
551  DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > INT16_MAX);
552  am->sm_list = sm_list;
553  am->priority = priority;
555 
556  am->PrefilterRegisterWithListId = PrefilterRegister;
557  am->pkt_v1.GetData = GetData;
558 
559  if (g_mpm_list[DETECT_BUFFER_MPM_TYPE_PKT] == NULL) {
560  g_mpm_list[DETECT_BUFFER_MPM_TYPE_PKT] = am;
561  } else {
563  while (t->next != NULL) {
564  t = t->next;
565  }
566  t->next = am;
567  am->id = t->id + 1;
568  }
569  g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_PKT]++;
570 
571  SupportFastPatternForSigMatchList(sm_list, priority);
572  SCLogDebug("%s/%d done", name, sm_list);
573 }
574 
575 /** \brief copy a mpm engine from parent_id, add in transforms */
577  const int id, const int parent_id,
578  DetectEngineTransforms *transforms)
579 {
580  SCLogDebug("registering %d/%d", id, parent_id);
581 
583  while (t) {
584  if (t->sm_list == parent_id) {
585  DetectBufferMpmRegistery *am = SCCalloc(1, sizeof(*am));
586  BUG_ON(am == NULL);
587  am->name = t->name;
588  snprintf(am->pname, sizeof(am->pname), "%s#%d", am->name, id);
589  DEBUG_VALIDATE_BUG_ON(id < 0 || id > INT16_MAX);
590  am->sm_list = id; // use new id
591  am->sm_list_base = t->sm_list;
594  am->pkt_v1.GetData = t->pkt_v1.GetData;
595  am->priority = t->priority;
597  am->next = t->next;
598  if (transforms) {
599  memcpy(&am->transforms, transforms, sizeof(*transforms));
600  }
601  am->id = de_ctx->pkt_mpms_list_cnt++;
602 
604  t->next = am;
605  SCLogDebug("copied mpm registration for %s id %u "
606  "with parent %u and GetData %p",
607  t->name, id, parent_id, am->pkt_v1.GetData);
608  t = am;
609  }
610  t = t->next;
611  }
612 }
613 
615 {
616  const DetectBufferMpmRegistery *list = g_mpm_list[DETECT_BUFFER_MPM_TYPE_PKT];
617  while (list != NULL) {
618  DetectBufferMpmRegistery *n = SCCalloc(1, sizeof(*n));
619  BUG_ON(n == NULL);
620 
621  *n = *list;
622  n->next = NULL;
623 
624  if (de_ctx->pkt_mpms_list == NULL) {
625  de_ctx->pkt_mpms_list = n;
626  } else {
628  while (t->next != NULL) {
629  t = t->next;
630  }
631 
632  t->next = n;
633  }
634 
635  /* default to whatever the global setting is */
637 
638  /* see if we use a unique or shared mpm ctx for this type */
639  int confshared = 0;
640  char confstring[256] = "detect.mpm.";
641  strlcat(confstring, n->name, sizeof(confstring));
642  strlcat(confstring, ".shared", sizeof(confstring));
643  if (ConfGetBool(confstring, &confshared) == 1)
644  shared = confshared;
645 
646  if (shared == 0) {
647  if (!(de_ctx->flags & DE_QUIET)) {
648  SCLogPerf("using unique mpm ctx' for %s", n->name);
649  }
651  } else {
652  if (!(de_ctx->flags & DE_QUIET)) {
653  SCLogPerf("using shared mpm ctx' for %s", n->name);
654  }
656  }
657 
658  list = list->next;
659  }
661  SCLogDebug("mpm: de_ctx pkt_mpms_list %p %u",
663 }
664 
665 /**
666  * \brief initialize mpm contexts for applayer buffers that are in
667  * "single or "shared" mode.
668  */
670 {
671  SCLogDebug("preparing pkt mpm");
672  int r = 0;
674  while (am != NULL) {
675  SCLogDebug("%s", am->name);
677  {
679  if (mpm_ctx != NULL) {
680  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
681  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
682  SCLogDebug("%s: %d", am->name, r);
683  }
684  }
685  }
686  am = am->next;
687  }
688  return r;
689 }
690 
691 static int32_t SetupBuiltinMpm(DetectEngineCtx *de_ctx, const char *name)
692 {
693  /* default to whatever the global setting is */
695 
696  /* see if we use a unique or shared mpm ctx for this type */
697  int confshared = 0;
698  char confstring[256] = "detect.mpm.";
699  strlcat(confstring, name, sizeof(confstring));
700  strlcat(confstring, ".shared", sizeof(confstring));
701  if (ConfGetBool(confstring, &confshared) == 1)
702  shared = confshared;
703 
704  int32_t ctx;
705  if (shared == 0) {
707  SCLogPerf("using unique mpm ctx' for %s", name);
708  } else {
710  SCLogPerf("using shared mpm ctx' for %s", name);
711  }
712  return ctx;
713 }
714 
716 {
717  de_ctx->sgh_mpm_context_proto_tcp_packet = SetupBuiltinMpm(de_ctx, "tcp-packet");
718  de_ctx->sgh_mpm_context_stream = SetupBuiltinMpm(de_ctx, "tcp-stream");
719 
720  de_ctx->sgh_mpm_context_proto_udp_packet = SetupBuiltinMpm(de_ctx, "udp-packet");
721  de_ctx->sgh_mpm_context_proto_other_packet = SetupBuiltinMpm(de_ctx, "other-ip");
722 }
723 
724 /**
725  * \brief initialize mpm contexts for builtin buffers that are in
726  * "single or "shared" mode.
727  */
729 {
730  int r = 0;
731  MpmCtx *mpm_ctx = NULL;
732 
735  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
736  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
737  }
739  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
740  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
741  }
742  }
743 
746  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
747  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
748  }
750  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
751  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
752  }
753  }
754 
757  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
758  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
759  }
760  }
761 
764  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
765  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
766  }
768  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
769  r |= mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx);
770  }
771  }
772 
773  return r;
774 }
775 
776 /**
777  * \brief check if a signature has patterns that are to be inspected
778  * against a packets payload (as opposed to the stream payload)
779  *
780  * \param s signature
781  *
782  * \retval 1 true
783  * \retval 0 false
784  */
786 {
787  SCEnter();
788 
789  if (s == NULL) {
790  SCReturnInt(0);
791  }
792 
793  if (!(s->proto.proto[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8))) {
794  SCReturnInt(1);
795  }
796 
797  if ((s->init_data != NULL && s->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) ||
798  (s->init_data == NULL && s->sm_arrays[DETECT_SM_LIST_PMATCH] == NULL))
799  {
800  SCLogDebug("no mpm");
801  SCReturnInt(0);
802  }
803 
804  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
805  SCReturnInt(0);
806  }
807 
808  SCReturnInt(1);
809 }
810 
811 /**
812  * \brief check if a signature has patterns that are to be inspected
813  * against the stream payload (as opposed to the individual packets
814  * payload(s))
815  *
816  * \param s signature
817  *
818  * \retval 1 true
819  * \retval 0 false
820  */
822 {
823  SCEnter();
824 
825  if (s == NULL) {
826  SCReturnInt(0);
827  }
828 
829  if (!(s->proto.proto[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8))) {
830  SCReturnInt(0);
831  }
832 
833  if ((s->init_data != NULL && s->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) ||
834  (s->init_data == NULL && s->sm_arrays[DETECT_SM_LIST_PMATCH] == NULL))
835  {
836  SCLogDebug("no mpm");
837  SCReturnInt(0);
838  }
839 
840  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
841  SCReturnInt(0);
842  }
843 
844  SCReturnInt(1);
845 }
846 
847 
848 /**
849  * \brief Function to return the multi pattern matcher algorithm to be
850  * used by the engine, based on the mpm-algo setting in yaml
851  * Use the default mpm if none is specified in the yaml file.
852  *
853  * \retval mpm algo value
854  */
856 {
857  const char *mpm_algo;
858  uint16_t mpm_algo_val = mpm_default_matcher;
859 
860  /* Get the mpm algo defined in config file by the user */
861  if ((ConfGet("mpm-algo", &mpm_algo)) == 1) {
862  if (mpm_algo != NULL) {
863 #if __BYTE_ORDER == __BIG_ENDIAN
864  if (strcmp(mpm_algo, "ac-ks") == 0) {
865  FatalError(SC_ERR_FATAL, "ac-ks does "
866  "not work on big endian systems at this time.");
867  }
868 #endif
869  if (strcmp("auto", mpm_algo) == 0) {
870  goto done;
871  }
872  for (uint16_t u = 0; u < MPM_TABLE_SIZE; u++) {
873  if (mpm_table[u].name == NULL)
874  continue;
875 
876  if (strcmp(mpm_table[u].name, mpm_algo) == 0) {
877  mpm_algo_val = u;
878  goto done;
879  }
880  }
881 
882 #ifndef BUILD_HYPERSCAN
883  if ((strcmp(mpm_algo, "hs") == 0)) {
884  FatalError(SC_ERR_INVALID_VALUE, "Hyperscan (hs) support for mpm-algo is "
885  "not compiled into Suricata.");
886  }
887 #endif
888  }
889  FatalError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Invalid mpm algo supplied "
890  "in the yaml conf file: \"%s\"", mpm_algo);
891  }
892 
893  done:
894  return mpm_algo_val;
895 }
896 
897 void PatternMatchDestroy(MpmCtx *mpm_ctx, uint16_t mpm_matcher)
898 {
899  SCLogDebug("mpm_ctx %p, mpm_matcher %"PRIu16"", mpm_ctx, mpm_matcher);
900  mpm_table[mpm_matcher].DestroyCtx(mpm_ctx);
901 }
902 
903 void PatternMatchThreadPrint(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
904 {
905  SCLogDebug("mpm_thread_ctx %p, mpm_matcher %"PRIu16" defunct", mpm_thread_ctx, mpm_matcher);
906  //mpm_table[mpm_matcher].PrintThreadCtx(mpm_thread_ctx);
907 }
908 void PatternMatchThreadDestroy(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
909 {
910  SCLogDebug("mpm_thread_ctx %p, mpm_matcher %"PRIu16"", mpm_thread_ctx, mpm_matcher);
911  if (mpm_table[mpm_matcher].DestroyThreadCtx != NULL)
912  mpm_table[mpm_matcher].DestroyThreadCtx(NULL, mpm_thread_ctx);
913 }
914 void PatternMatchThreadPrepare(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
915 {
916  SCLogDebug("mpm_thread_ctx %p, type %"PRIu16, mpm_thread_ctx, mpm_matcher);
917  MpmInitThreadCtx(mpm_thread_ctx, mpm_matcher);
918 }
919 
920 /** \brief Predict a strength value for patterns
921  *
922  * Patterns with high character diversity score higher.
923  * Alpha chars score not so high
924  * Other printable + a few common codes a little higher
925  * Everything else highest.
926  * Longer patterns score better than short patters.
927  *
928  * \param pat pattern
929  * \param patlen length of the pattern
930  *
931  * \retval s pattern score
932  */
933 uint32_t PatternStrength(uint8_t *pat, uint16_t patlen)
934 {
935  uint8_t a[256];
936  memset(&a, 0 ,sizeof(a));
937 
938  uint32_t s = 0;
939  uint16_t u = 0;
940  for (u = 0; u < patlen; u++) {
941  if (a[pat[u]] == 0) {
942  if (isalpha(pat[u]))
943  s += 3;
944  else if (isprint(pat[u]) || pat[u] == 0x00 || pat[u] == 0x01 || pat[u] == 0xFF)
945  s += 4;
946  else
947  s += 6;
948 
949  a[pat[u]] = 1;
950  } else {
951  s++;
952  }
953  }
954 
955  return s;
956 }
957 
958 static void PopulateMpmHelperAddPattern(MpmCtx *mpm_ctx,
959  const DetectContentData *cd,
960  const Signature *s, uint8_t flags,
961  int chop)
962 {
963  uint16_t pat_offset = cd->offset;
964  uint16_t pat_depth = cd->depth;
965 
966  /* recompute offset/depth to cope with chop */
967  if (chop && (pat_depth || pat_offset)) {
968  pat_offset += cd->fp_chop_offset;
969  if (pat_depth) {
970  pat_depth -= cd->content_len;
971  pat_depth += cd->fp_chop_offset + cd->fp_chop_len;
972  }
973  }
974 
975  /* We have to effectively "wild card" values that will be coming from
976  * byte_extract variables
977  */
979  pat_depth = pat_offset = 0;
980  }
981 
982  if (cd->flags & DETECT_CONTENT_NOCASE) {
983  if (chop) {
984  MpmAddPatternCI(mpm_ctx,
985  cd->content + cd->fp_chop_offset, cd->fp_chop_len,
986  pat_offset, pat_depth,
988  } else {
989  MpmAddPatternCI(mpm_ctx,
990  cd->content, cd->content_len,
991  pat_offset, pat_depth,
993  }
994  } else {
995  if (chop) {
996  MpmAddPatternCS(mpm_ctx,
997  cd->content + cd->fp_chop_offset, cd->fp_chop_len,
998  pat_offset, pat_depth,
1000  } else {
1001  MpmAddPatternCS(mpm_ctx,
1002  cd->content, cd->content_len,
1003  pat_offset, pat_depth,
1004  cd->id, s->num, flags|MPM_PATTERN_CTX_OWNS_ID);
1005  }
1006  }
1007 
1008  return;
1009 }
1010 
1011 #define SGH_PROTO(sgh, p) ((sgh)->init->protos[(p)] == 1)
1012 #define SGH_DIRECTION_TS(sgh) ((sgh)->init->direction & SIG_FLAG_TOSERVER)
1013 #define SGH_DIRECTION_TC(sgh) ((sgh)->init->direction & SIG_FLAG_TOCLIENT)
1015 static void SetMpm(Signature *s, SigMatch *mpm_sm)
1016 {
1017  if (s == NULL || mpm_sm == NULL)
1018  return;
1019 
1020  DetectContentData *cd = (DetectContentData *)mpm_sm->ctx;
1022  if (DETECT_CONTENT_IS_SINGLE(cd) &&
1023  !(cd->flags & DETECT_CONTENT_NEGATED) &&
1024  !(cd->flags & DETECT_CONTENT_REPLACE) &&
1025  cd->content_len == cd->fp_chop_len)
1026  {
1028  }
1029  } else {
1030  if (DETECT_CONTENT_IS_SINGLE(cd) &&
1031  !(cd->flags & DETECT_CONTENT_NEGATED) &&
1032  !(cd->flags & DETECT_CONTENT_REPLACE))
1033  {
1035  }
1036  }
1037  cd->flags |= DETECT_CONTENT_MPM;
1038  s->init_data->mpm_sm = mpm_sm;
1039  return;
1040 }
1041 
1042 static SigMatch *GetMpmForList(const Signature *s, const int list, SigMatch *mpm_sm,
1043  uint16_t max_len, bool skip_negated_content)
1044 {
1045  for (SigMatch *sm = s->init_data->smlists[list]; sm != NULL; sm = sm->next) {
1046  if (sm->type != DETECT_CONTENT)
1047  continue;
1048 
1049  const DetectContentData *cd = (DetectContentData *)sm->ctx;
1050  /* skip_negated_content is only set if there's absolutely no
1051  * non-negated content present in the sig */
1052  if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
1053  continue;
1054  if (cd->content_len != max_len)
1055  continue;
1056 
1057  if (mpm_sm == NULL) {
1058  mpm_sm = sm;
1059  } else {
1060  DetectContentData *data1 = (DetectContentData *)sm->ctx;
1061  DetectContentData *data2 = (DetectContentData *)mpm_sm->ctx;
1062  uint32_t ls = PatternStrength(data1->content, data1->content_len);
1063  uint32_t ss = PatternStrength(data2->content, data2->content_len);
1064  if (ls > ss) {
1065  mpm_sm = sm;
1066  } else if (ls == ss) {
1067  /* if 2 patterns are of equal strength, we pick the longest */
1068  if (data1->content_len > data2->content_len)
1069  mpm_sm = sm;
1070  } else {
1071  SCLogDebug("sticking with mpm_sm");
1072  }
1073  }
1074  }
1075  return mpm_sm;
1076 }
1077 
1079 {
1080  if (s->init_data->mpm_sm != NULL)
1081  return;
1082 
1083  SigMatch *mpm_sm = NULL, *sm = NULL;
1084  const int nlists = s->init_data->smlists_array_size;
1085  int nn_sm_list[nlists];
1086  int n_sm_list[nlists];
1087  memset(nn_sm_list, 0, nlists * sizeof(int));
1088  memset(n_sm_list, 0, nlists * sizeof(int));
1089  int count_nn_sm_list = 0;
1090  int count_n_sm_list = 0;
1091 
1092  /* inspect rule to see if we have the fast_pattern reg to
1093  * force using a sig, otherwise keep stats about the patterns */
1094  for (int list_id = 0; list_id < nlists; list_id++) {
1095  if (s->init_data->smlists[list_id] == NULL)
1096  continue;
1097 
1099  continue;
1100 
1101  for (sm = s->init_data->smlists[list_id]; sm != NULL; sm = sm->next) {
1102  if (sm->type != DETECT_CONTENT)
1103  continue;
1104 
1105  const DetectContentData *cd = (DetectContentData *)sm->ctx;
1106  /* fast_pattern set in rule, so using this pattern */
1107  if ((cd->flags & DETECT_CONTENT_FAST_PATTERN)) {
1108  SetMpm(s, sm);
1109  return;
1110  }
1111 
1112  if (cd->flags & DETECT_CONTENT_NEGATED) {
1113  n_sm_list[list_id] = 1;
1114  count_n_sm_list++;
1115  } else {
1116  nn_sm_list[list_id] = 1;
1117  count_nn_sm_list++;
1118  }
1119  }
1120  }
1121 
1122  /* prefer normal not-negated over negated */
1123  int *curr_sm_list = NULL;
1124  int skip_negated_content = 1;
1125  if (count_nn_sm_list > 0) {
1126  curr_sm_list = nn_sm_list;
1127  } else if (count_n_sm_list > 0) {
1128  curr_sm_list = n_sm_list;
1129  skip_negated_content = 0;
1130  } else {
1131  return;
1132  }
1133 
1134  int final_sm_list[nlists];
1135  memset(&final_sm_list, 0, (nlists * sizeof(int)));
1136 
1137  int count_final_sm_list = 0;
1138  int priority;
1139 
1141  while (tmp != NULL) {
1142  for (priority = tmp->priority;
1143  tmp != NULL && priority == tmp->priority;
1144  tmp = tmp->next)
1145  {
1146  SCLogDebug("tmp->list_id %d tmp->priority %d", tmp->list_id, tmp->priority);
1147  if (tmp->list_id >= nlists)
1148  continue;
1149  if (curr_sm_list[tmp->list_id] == 0)
1150  continue;
1151  final_sm_list[count_final_sm_list++] = tmp->list_id;
1152  }
1153  if (count_final_sm_list != 0)
1154  break;
1155  }
1156 
1157  BUG_ON(count_final_sm_list == 0);
1158 
1159  uint16_t max_len = 0;
1160  for (int i = 0; i < count_final_sm_list; i++) {
1161  if (final_sm_list[i] >= (int)s->init_data->smlists_array_size)
1162  continue;
1163 
1164  for (sm = s->init_data->smlists[final_sm_list[i]]; sm != NULL; sm = sm->next) {
1165  if (sm->type != DETECT_CONTENT)
1166  continue;
1167 
1168  const DetectContentData *cd = (DetectContentData *)sm->ctx;
1169  /* skip_negated_content is only set if there's absolutely no
1170  * non-negated content present in the sig */
1171  if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
1172  continue;
1173  if (max_len < cd->content_len)
1174  max_len = cd->content_len;
1175  }
1176  }
1177 
1178  for (int i = 0; i < count_final_sm_list; i++) {
1179  if (final_sm_list[i] >= (int)s->init_data->smlists_array_size)
1180  continue;
1181 
1182  mpm_sm = GetMpmForList(s, final_sm_list[i], mpm_sm, max_len, skip_negated_content);
1183  }
1184 
1185  /* assign to signature */
1186  SetMpm(s, mpm_sm);
1187  return;
1188 }
1189 
1190 /** \internal
1191  * \brief The hash function for MpmStore
1192  *
1193  * \param ht Pointer to the hash table.
1194  * \param data Pointer to the MpmStore.
1195  * \param datalen Not used in our case.
1196  *
1197  * \retval hash The generated hash value.
1198  */
1199 static uint32_t MpmStoreHashFunc(HashListTable *ht, void *data, uint16_t datalen)
1200 {
1201  const MpmStore *ms = (MpmStore *)data;
1202  uint32_t hash = 0;
1203  uint32_t b = 0;
1204 
1205  for (b = 0; b < ms->sid_array_size; b++)
1206  hash += ms->sid_array[b];
1207 
1208  return hash % ht->array_size;
1209 }
1210 
1211 /**
1212  * \brief The Compare function for MpmStore
1213  *
1214  * \param data1 Pointer to the first MpmStore.
1215  * \param len1 Not used.
1216  * \param data2 Pointer to the second MpmStore.
1217  * \param len2 Not used.
1218  *
1219  * \retval 1 If the 2 MpmStores sent as args match.
1220  * \retval 0 If the 2 MpmStores sent as args do not match.
1221  */
1222 static char MpmStoreCompareFunc(void *data1, uint16_t len1, void *data2,
1223  uint16_t len2)
1224 {
1225  const MpmStore *ms1 = (MpmStore *)data1;
1226  const MpmStore *ms2 = (MpmStore *)data2;
1227 
1228  if (ms1->sid_array_size != ms2->sid_array_size)
1229  return 0;
1230 
1231  if (ms1->buffer != ms2->buffer)
1232  return 0;
1233 
1234  if (ms1->direction != ms2->direction)
1235  return 0;
1236 
1237  if (ms1->sm_list != ms2->sm_list)
1238  return 0;
1239 
1240  if (SCMemcmp(ms1->sid_array, ms2->sid_array,
1241  ms1->sid_array_size) != 0)
1242  {
1243  return 0;
1244  }
1245 
1246  return 1;
1247 }
1248 
1249 static void MpmStoreFreeFunc(void *ptr)
1250 {
1251  MpmStore *ms = ptr;
1252  if (ms != NULL) {
1253  if (ms->mpm_ctx != NULL && !(ms->mpm_ctx->flags & MPMCTX_FLAGS_GLOBAL))
1254  {
1255  SCLogDebug("destroying mpm_ctx %p", ms->mpm_ctx);
1257  SCFree(ms->mpm_ctx);
1258  }
1259  ms->mpm_ctx = NULL;
1260 
1261  SCFree(ms->sid_array);
1262  SCFree(ms);
1263  }
1264 }
1265 
1266 /**
1267  * \brief Initializes the MpmStore mpm hash table to be used by the detection
1268  * engine context.
1269  *
1270  * \param de_ctx Pointer to the detection engine context.
1271  *
1272  * \retval 0 On success.
1273  * \retval -1 On failure.
1274  */
1276 {
1278  MpmStoreHashFunc,
1279  MpmStoreCompareFunc,
1280  MpmStoreFreeFunc);
1281  if (de_ctx->mpm_hash_table == NULL)
1282  goto error;
1283 
1284  return 0;
1285 
1286 error:
1287  return -1;
1288 }
1289 
1290 /**
1291  * \brief Adds a MpmStore to the detection engine context MpmStore
1292  *
1293  * \param de_ctx Pointer to the detection engine context.
1294  * \param sgh Pointer to the MpmStore.
1295  *
1296  * \retval ret 0 on Successfully adding the argument sgh; -1 on failure.
1297  */
1298 static int MpmStoreAdd(DetectEngineCtx *de_ctx, MpmStore *s)
1299 {
1300  int ret = HashListTableAdd(de_ctx->mpm_hash_table, (void *)s, 0);
1301  return ret;
1302 }
1303 
1304 /**
1305  * \brief Used to lookup a MpmStore from the MpmStore
1306  *
1307  * \param de_ctx Pointer to the detection engine context.
1308  * \param sgh Pointer to the MpmStore.
1309  *
1310  * \retval rsgh On success a pointer to the MpmStore if the MpmStore is
1311  * found in the hash table; NULL on failure.
1312  */
1313 static MpmStore *MpmStoreLookup(DetectEngineCtx *de_ctx, MpmStore *s)
1314 {
1316  (void *)s, 0);
1317  return rs;
1318 }
1319 
1320 static const DetectBufferMpmRegistery *GetByMpmStore(const DetectEngineCtx *de_ctx,
1321  const MpmStore *ms)
1322 {
1324  while (am != NULL) {
1325  if (ms->sm_list == am->sm_list &&
1326  ms->direction == am->direction) {
1327  return am;
1328  }
1329  am = am->next;
1330  }
1331  am = de_ctx->pkt_mpms_list;
1332  while (am != NULL) {
1333  if (ms->sm_list == am->sm_list) {
1334  return am;
1335  }
1336  am = am->next;
1337  }
1338  return NULL;
1339 }
1340 
1342 {
1343  HashListTableBucket *htb = NULL;
1344 
1345  uint32_t stats[MPMB_MAX] = {0};
1346  int app_mpms_cnt = de_ctx->buffer_type_id;
1347  uint32_t appstats[app_mpms_cnt + 1]; // +1 to silence scan-build
1348  memset(&appstats, 0x00, sizeof(appstats));
1349  int pkt_mpms_cnt = de_ctx->buffer_type_id;
1350  uint32_t pktstats[pkt_mpms_cnt + 1]; // +1 to silence scan-build
1351  memset(&pktstats, 0x00, sizeof(pktstats));
1352  int frame_mpms_cnt = de_ctx->buffer_type_id;
1353  uint32_t framestats[frame_mpms_cnt + 1]; // +1 to silence scan-build
1354  memset(&framestats, 0x00, sizeof(framestats));
1355 
1357  htb != NULL;
1358  htb = HashListTableGetListNext(htb))
1359  {
1360  const MpmStore *ms = (MpmStore *)HashListTableGetListData(htb);
1361  if (ms == NULL || ms->mpm_ctx == NULL) {
1362  continue;
1363  }
1364  if (ms->buffer < MPMB_MAX)
1365  stats[ms->buffer]++;
1366  else if (ms->sm_list != DETECT_SM_LIST_PMATCH) {
1367  const DetectBufferMpmRegistery *am = GetByMpmStore(de_ctx, ms);
1368  if (am != NULL) {
1369  switch (am->type) {
1371  SCLogDebug("%s: %u patterns. Min %u, Max %u. Ctx %p",
1372  am->name,
1373  ms->mpm_ctx->pattern_cnt,
1374  ms->mpm_ctx->minlen, ms->mpm_ctx->maxlen,
1375  ms->mpm_ctx);
1376  pktstats[am->sm_list]++;
1377  break;
1379  SCLogDebug("%s %s: %u patterns. Min %u, Max %u. Ctx %p",
1380  am->name,
1381  am->direction == SIG_FLAG_TOSERVER ? "toserver":"toclient",
1382  ms->mpm_ctx->pattern_cnt,
1383  ms->mpm_ctx->minlen, ms->mpm_ctx->maxlen,
1384  ms->mpm_ctx);
1385  appstats[am->sm_list]++;
1386  break;
1388  SCLogDebug("%s: %u patterns. Min %u, Max %u. Ctx %p", am->name,
1389  ms->mpm_ctx->pattern_cnt, ms->mpm_ctx->minlen, ms->mpm_ctx->maxlen,
1390  ms->mpm_ctx);
1391  framestats[am->sm_list]++;
1392  break;
1394  break;
1395  }
1396  }
1397  }
1398  }
1399 
1400  if (!(de_ctx->flags & DE_QUIET)) {
1401  for (int x = 0; x < MPMB_MAX; x++) {
1402  SCLogPerf("Builtin MPM \"%s\": %u", builtin_mpms[x], stats[x]);
1403  }
1405  while (am != NULL) {
1406  if (appstats[am->sm_list] > 0) {
1407  const char *name = am->name;
1408  const char *direction = am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient";
1409  SCLogPerf("AppLayer MPM \"%s %s (%s)\": %u", direction, name,
1410  AppProtoToString(am->app_v2.alproto), appstats[am->sm_list]);
1411  }
1412  am = am->next;
1413  }
1415  while (pm != NULL) {
1416  if (pktstats[pm->sm_list] > 0) {
1417  const char *name = pm->name;
1418  SCLogPerf("Pkt MPM \"%s\": %u", name, pktstats[pm->sm_list]);
1419  }
1420  pm = pm->next;
1421  }
1423  while (um != NULL) {
1424  if (framestats[um->sm_list] > 0) {
1425  const char *name = um->name;
1426  SCLogPerf("Frame MPM \"%s\": %u", name, framestats[um->sm_list]);
1427  }
1428  um = um->next;
1429  }
1430  }
1431 }
1432 
1433 /**
1434  * \brief Frees the hash table - DetectEngineCtx->mpm_hash_table, allocated by
1435  * MpmStoreInit() function.
1436  *
1437  * \param de_ctx Pointer to the detection engine context.
1438  */
1440 {
1441  if (de_ctx->mpm_hash_table == NULL)
1442  return;
1443 
1445  de_ctx->mpm_hash_table = NULL;
1446  return;
1447 }
1448 
1449 static void MpmStoreSetup(const DetectEngineCtx *de_ctx, MpmStore *ms)
1450 {
1451  const Signature *s = NULL;
1452  uint32_t sig;
1453  int dir = 0;
1454 
1455  if (ms->buffer != MPMB_MAX) {
1457 
1458  switch (ms->buffer) {
1459  /* TS is 1 */
1460  case MPMB_TCP_PKT_TS:
1461  case MPMB_TCP_STREAM_TS:
1462  case MPMB_UDP_TS:
1463  dir = 1;
1464  break;
1465 
1466  /* TC is 0 */
1467  default:
1468  case MPMB_UDP_TC:
1469  case MPMB_TCP_STREAM_TC:
1470  case MPMB_TCP_PKT_TC:
1471  case MPMB_OTHERIP: /**< use 0 for other */
1472  dir = 0;
1473  break;
1474  }
1475  } else {
1477 
1478  if (ms->direction == SIG_FLAG_TOSERVER)
1479  dir = 1;
1480  else
1481  dir = 0;
1482  }
1483 
1485  if (ms->mpm_ctx == NULL) {
1486  return;
1487  }
1488 
1490 
1491  /* add the patterns */
1492  for (sig = 0; sig < (ms->sid_array_size * 8); sig++) {
1493  if (ms->sid_array[sig / 8] & (1 << (sig % 8))) {
1494  s = de_ctx->sig_array[sig];
1495  if (s == NULL)
1496  continue;
1497  if ((s->flags & ms->direction) == 0) {
1498  SCLogDebug("s->flags %x ms->direction %x", s->flags, ms->direction);
1499  continue;
1500  }
1501  if (s->init_data->mpm_sm == NULL)
1502  continue;
1503  int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
1504  if (list < 0)
1505  continue;
1506  if (list != ms->sm_list)
1507  continue;
1508 
1509  SCLogDebug("adding %u", s->id);
1510 
1512 
1513  int skip = 0;
1514  /* negated logic: if mpm match can't be used to be sure about this
1515  * pattern, we have to inspect the rule fully regardless of mpm
1516  * match. So in this case there is no point of adding it at all.
1517  * The non-mpm list entry for the sig will make sure the sig is
1518  * inspected. */
1519  if ((cd->flags & DETECT_CONTENT_NEGATED) &&
1521  {
1522  skip = 1;
1523  SCLogDebug("not adding negated mpm as it's not 'single'");
1524  }
1525 
1526  if (!skip) {
1527  PopulateMpmHelperAddPattern(ms->mpm_ctx,
1528  cd, s, 0, (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP));
1529  }
1530  }
1531  }
1532 
1533  if (ms->mpm_ctx->pattern_cnt == 0) {
1535  ms->mpm_ctx = NULL;
1536  } else {
1538  if (mpm_table[ms->mpm_ctx->mpm_type].Prepare != NULL) {
1540  }
1541  }
1542  }
1543 }
1544 
1545 
1546 /** \brief Get MpmStore for a built-in buffer type
1547  *
1548  */
1550  enum MpmBuiltinBuffers buf)
1551 {
1552  const Signature *s = NULL;
1553  uint32_t sig;
1554  uint32_t cnt = 0;
1555  int direction = 0;
1556  uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
1557  uint8_t sids_array[max_sid];
1558  memset(sids_array, 0x00, max_sid);
1559  int sgh_mpm_context = 0;
1560  int sm_list = DETECT_SM_LIST_PMATCH;
1561 
1562  switch (buf) {
1563  case MPMB_TCP_PKT_TS:
1564  case MPMB_TCP_PKT_TC:
1565  sgh_mpm_context = de_ctx->sgh_mpm_context_proto_tcp_packet;
1566  break;
1567  case MPMB_TCP_STREAM_TS:
1568  case MPMB_TCP_STREAM_TC:
1569  sgh_mpm_context = de_ctx->sgh_mpm_context_stream;
1570  break;
1571  case MPMB_UDP_TS:
1572  case MPMB_UDP_TC:
1573  sgh_mpm_context = de_ctx->sgh_mpm_context_proto_udp_packet;
1574  break;
1575  case MPMB_OTHERIP:
1576  sgh_mpm_context = de_ctx->sgh_mpm_context_proto_other_packet;
1577  break;
1578  default:
1579  break;
1580  }
1581 
1582  switch(buf) {
1583  case MPMB_TCP_PKT_TS:
1584  case MPMB_TCP_STREAM_TS:
1585  case MPMB_UDP_TS:
1586  direction = SIG_FLAG_TOSERVER;
1587  break;
1588 
1589  case MPMB_TCP_PKT_TC:
1590  case MPMB_TCP_STREAM_TC:
1591  case MPMB_UDP_TC:
1592  direction = SIG_FLAG_TOCLIENT;
1593  break;
1594 
1595  case MPMB_OTHERIP:
1596  direction = (SIG_FLAG_TOCLIENT|SIG_FLAG_TOSERVER);
1597  break;
1598 
1599  case MPMB_MAX:
1600  BUG_ON(1);
1601  break;
1602  }
1603 
1604  for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
1605  s = sgh->init->match_array[sig];
1606  if (s == NULL)
1607  continue;
1608 
1609  if (s->init_data->mpm_sm == NULL)
1610  continue;
1611 
1612  int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
1613  if (list < 0)
1614  continue;
1615 
1616  if (list != DETECT_SM_LIST_PMATCH)
1617  continue;
1618 
1619  switch (buf) {
1620  case MPMB_TCP_PKT_TS:
1621  case MPMB_TCP_PKT_TC:
1622  if (SignatureHasPacketContent(s) == 1)
1623  {
1624  sids_array[s->num / 8] |= 1 << (s->num % 8);
1625  cnt++;
1626  }
1627  break;
1628  case MPMB_TCP_STREAM_TS:
1629  case MPMB_TCP_STREAM_TC:
1630  if (SignatureHasStreamContent(s) == 1)
1631  {
1632  sids_array[s->num / 8] |= 1 << (s->num % 8);
1633  cnt++;
1634  }
1635  break;
1636  case MPMB_UDP_TS:
1637  case MPMB_UDP_TC:
1638  sids_array[s->num / 8] |= 1 << (s->num % 8);
1639  cnt++;
1640  break;
1641  case MPMB_OTHERIP:
1642  sids_array[s->num / 8] |= 1 << (s->num % 8);
1643  cnt++;
1644  break;
1645  default:
1646  break;
1647  }
1648  }
1649 
1650  if (cnt == 0)
1651  return NULL;
1652 
1653  MpmStore lookup = { sids_array, max_sid, direction, buf, sm_list, 0, NULL};
1654 
1655  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1656  if (result == NULL) {
1657  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1658  if (copy == NULL)
1659  return NULL;
1660  uint8_t *sids = SCCalloc(1, max_sid);
1661  if (sids == NULL) {
1662  SCFree(copy);
1663  return NULL;
1664  }
1665 
1666  memcpy(sids, sids_array, max_sid);
1667  copy->sid_array = sids;
1668  copy->sid_array_size = max_sid;
1669  copy->buffer = buf;
1670  copy->direction = direction;
1671  copy->sm_list = sm_list;
1672  copy->sgh_mpm_context = sgh_mpm_context;
1673 
1674  MpmStoreSetup(de_ctx, copy);
1675  MpmStoreAdd(de_ctx, copy);
1676  return copy;
1677  } else {
1678  return result;
1679  }
1680 }
1681 
1682 static MpmStore *MpmStorePrepareBufferAppLayer(DetectEngineCtx *de_ctx,
1683  SigGroupHead *sgh, const DetectBufferMpmRegistery *am)
1684 {
1685  const Signature *s = NULL;
1686  uint32_t sig;
1687  uint32_t cnt = 0;
1688  uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
1689  uint8_t sids_array[max_sid];
1690  memset(sids_array, 0x00, max_sid);
1691 
1692  SCLogDebug("handling %s direction %s for list %d", am->name,
1693  am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient",
1694  am->sm_list);
1695 
1696  for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
1697  s = sgh->init->match_array[sig];
1698  if (s == NULL)
1699  continue;
1700 
1701  if (s->init_data->mpm_sm == NULL)
1702  continue;
1703 
1704  if ((s->flags & am->direction) == 0)
1705  continue;
1706 
1707  int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
1708  if (list < 0)
1709  continue;
1710 
1711  if (list != am->sm_list)
1712  continue;
1713 
1714  sids_array[s->num / 8] |= 1 << (s->num % 8);
1715  cnt++;
1716  }
1717 
1718  if (cnt == 0)
1719  return NULL;
1720 
1721  MpmStore lookup = { sids_array, max_sid, am->direction,
1722  MPMB_MAX, am->sm_list, 0, NULL};
1723  SCLogDebug("am->direction %d am->sm_list %d",
1724  am->direction, am->sm_list);
1725 
1726  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1727  if (result == NULL) {
1728  SCLogDebug("new unique mpm for %s %s: %u patterns",
1729  am->name,
1730  am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient",
1731  cnt);
1732 
1733  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1734  if (copy == NULL)
1735  return NULL;
1736  uint8_t *sids = SCCalloc(1, max_sid);
1737  if (sids == NULL) {
1738  SCFree(copy);
1739  return NULL;
1740  }
1741 
1742  memcpy(sids, sids_array, max_sid);
1743  copy->sid_array = sids;
1744  copy->sid_array_size = max_sid;
1745  copy->buffer = MPMB_MAX;
1746  copy->direction = am->direction;
1747  copy->sm_list = am->sm_list;
1748  copy->sgh_mpm_context = am->sgh_mpm_context;
1749 
1750  MpmStoreSetup(de_ctx, copy);
1751  MpmStoreAdd(de_ctx, copy);
1752  return copy;
1753  } else {
1754  SCLogDebug("using existing mpm %p", result);
1755  return result;
1756  }
1757  return NULL;
1758 }
1759 
1760 static MpmStore *MpmStorePrepareBufferPkt(DetectEngineCtx *de_ctx,
1761  SigGroupHead *sgh, const DetectBufferMpmRegistery *am)
1762 {
1763  const Signature *s = NULL;
1764  uint32_t sig;
1765  uint32_t cnt = 0;
1766  uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
1767  uint8_t sids_array[max_sid];
1768  memset(sids_array, 0x00, max_sid);
1769 
1770  SCLogDebug("handling %s for list %d", am->name,
1771  am->sm_list);
1772 
1773  for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
1774  s = sgh->init->match_array[sig];
1775  if (s == NULL)
1776  continue;
1777 
1778  if (s->init_data->mpm_sm == NULL)
1779  continue;
1780 
1781  int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
1782  if (list < 0)
1783  continue;
1784 
1785  if (list != am->sm_list)
1786  continue;
1787 
1788  sids_array[s->num / 8] |= 1 << (s->num % 8);
1789  cnt++;
1790  }
1791 
1792  if (cnt == 0)
1793  return NULL;
1794 
1795  MpmStore lookup = { sids_array, max_sid, SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT,
1796  MPMB_MAX, am->sm_list, 0, NULL};
1797  SCLogDebug("am->sm_list %d", am->sm_list);
1798 
1799  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1800  if (result == NULL) {
1801  SCLogDebug("new unique mpm for %s: %u patterns",
1802  am->name, cnt);
1803 
1804  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1805  if (copy == NULL)
1806  return NULL;
1807  uint8_t *sids = SCCalloc(1, max_sid);
1808  if (sids == NULL) {
1809  SCFree(copy);
1810  return NULL;
1811  }
1812 
1813  memcpy(sids, sids_array, max_sid);
1814  copy->sid_array = sids;
1815  copy->sid_array_size = max_sid;
1816  copy->buffer = MPMB_MAX;
1818  copy->sm_list = am->sm_list;
1819  copy->sgh_mpm_context = am->sgh_mpm_context;
1820 
1821  MpmStoreSetup(de_ctx, copy);
1822  MpmStoreAdd(de_ctx, copy);
1823  return copy;
1824  } else {
1825  SCLogDebug("using existing mpm %p", result);
1826  return result;
1827  }
1828  return NULL;
1829 }
1830 
1831 static MpmStore *MpmStorePrepareBufferFrame(
1833 {
1834  const Signature *s = NULL;
1835  uint32_t sig;
1836  uint32_t cnt = 0;
1837  uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
1838  uint8_t sids_array[max_sid];
1839  memset(sids_array, 0x00, max_sid);
1840 
1841  SCLogDebug("handling %s for list %d", am->name, am->sm_list);
1842 
1843  for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
1844  s = sgh->init->match_array[sig];
1845  if (s == NULL)
1846  continue;
1847 
1848  if (s->init_data->mpm_sm == NULL)
1849  continue;
1850 
1851  if ((s->flags & am->direction) == 0)
1852  continue;
1853 
1854  int list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
1855  if (list < 0)
1856  continue;
1857 
1858  if (list != am->sm_list)
1859  continue;
1860 
1861  sids_array[s->num / 8] |= 1 << (s->num % 8);
1862  cnt++;
1863  }
1864 
1865  if (cnt == 0)
1866  return NULL;
1867 
1868  MpmStore lookup = { sids_array, max_sid, am->direction, MPMB_MAX, am->sm_list, 0, NULL };
1869  SCLogDebug("am->sm_list %d", am->sm_list);
1870 
1871  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1872  if (result == NULL) {
1873  SCLogDebug("new unique mpm for %s: %u patterns", am->name, cnt);
1874 
1875  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1876  if (copy == NULL)
1877  return NULL;
1878  uint8_t *sids = SCCalloc(1, max_sid);
1879  if (sids == NULL) {
1880  SCFree(copy);
1881  return NULL;
1882  }
1883 
1884  memcpy(sids, sids_array, max_sid);
1885  copy->sid_array = sids;
1886  copy->sid_array_size = max_sid;
1887  copy->buffer = MPMB_MAX;
1888  copy->direction = am->direction;
1889  copy->sm_list = am->sm_list;
1890  copy->sgh_mpm_context = am->sgh_mpm_context;
1891 
1892  MpmStoreSetup(de_ctx, copy);
1893  MpmStoreAdd(de_ctx, copy);
1894  return copy;
1895  } else {
1896  SCLogDebug("using existing mpm %p", result);
1897  return result;
1898  }
1899  return NULL;
1900 }
1901 
1902 static void SetRawReassemblyFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
1903 {
1904  const Signature *s = NULL;
1905  uint32_t sig;
1906 
1907  for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
1908  s = sgh->init->match_array[sig];
1909  if (s == NULL)
1910  continue;
1911 
1912  if (SignatureHasStreamContent(s) == 1) {
1914  SCLogDebug("rule group %p has SIG_GROUP_HEAD_HAVERAWSTREAM set", sgh);
1915  return;
1916  }
1917  }
1918  SCLogDebug("rule group %p does NOT have SIG_GROUP_HEAD_HAVERAWSTREAM set", sgh);
1919 }
1920 
1921 static void PrepareAppMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
1922 {
1923  if (de_ctx->app_mpms_list_cnt == 0)
1924  return;
1925 
1926  sh->init->app_mpms = SCCalloc(de_ctx->app_mpms_list_cnt, sizeof(MpmCtx *));
1927  BUG_ON(sh->init->app_mpms == NULL);
1928 
1930  while (a != NULL) {
1931  if ((a->direction == SIG_FLAG_TOSERVER && SGH_DIRECTION_TS(sh)) ||
1933  {
1934  MpmStore *mpm_store = MpmStorePrepareBufferAppLayer(de_ctx, sh, a);
1935  if (mpm_store != NULL) {
1936  sh->init->app_mpms[a->id] = mpm_store->mpm_ctx;
1937 
1938  SCLogDebug("a %p a->name %s a->PrefilterRegisterWithListId %p "
1939  "mpm_store->mpm_ctx %p", a, a->name,
1940  a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
1941 
1942  /* if we have just certain types of negated patterns,
1943  * mpm_ctx can be NULL */
1944  if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
1946  sh, mpm_store->mpm_ctx,
1947  a, a->sm_list) != 0);
1948  SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
1949  }
1950  }
1951  }
1952  a = a->next;
1953  }
1954 }
1955 
1956 static void PreparePktMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
1957 {
1958  if (de_ctx->pkt_mpms_list_cnt == 0)
1959  return;
1960 
1961  sh->init->pkt_mpms = SCCalloc(de_ctx->pkt_mpms_list_cnt, sizeof(MpmCtx *));
1962  BUG_ON(sh->init->pkt_mpms == NULL);
1963 
1965  while (a != NULL) {
1966  MpmStore *mpm_store = MpmStorePrepareBufferPkt(de_ctx, sh, a);
1967  if (mpm_store != NULL) {
1968  sh->init->pkt_mpms[a->id] = mpm_store->mpm_ctx;
1969 
1970  SCLogDebug("a %p a->name %s a->reg->PrefilterRegisterWithListId %p "
1971  "mpm_store->mpm_ctx %p", a, a->name,
1972  a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
1973 
1974  /* if we have just certain types of negated patterns,
1975  * mpm_ctx can be NULL */
1976  if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
1978  sh, mpm_store->mpm_ctx,
1979  a, a->sm_list) != 0);
1980  SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
1981  }
1982  }
1983  a = a->next;
1984  }
1985 }
1986 
1987 static void PrepareFrameMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
1988 {
1989  if (de_ctx->frame_mpms_list_cnt == 0)
1990  return;
1991 
1993  BUG_ON(sh->init->frame_mpms == NULL);
1994 
1996  while (a != NULL) {
1997  SCLogDebug("a %s direction %d PrefilterRegisterWithListId %p", a->name, a->direction,
1999  MpmStore *mpm_store = MpmStorePrepareBufferFrame(de_ctx, sh, a);
2000  if (mpm_store != NULL) {
2001  sh->init->frame_mpms[a->id] = mpm_store->mpm_ctx;
2002 
2003  SCLogDebug("a %p a->name %s a->reg->PrefilterRegisterWithListId %p "
2004  "mpm_store->mpm_ctx %p",
2005  a, a->name, a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
2006 
2007  /* if we have just certain types of negated patterns,
2008  * mpm_ctx can be NULL */
2009  SCLogDebug("mpm_store %p mpm_ctx %p", mpm_store, mpm_store->mpm_ctx);
2010  if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
2012  de_ctx, sh, mpm_store->mpm_ctx, a, a->sm_list) != 0);
2013  SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
2014  }
2015  }
2016  a = a->next;
2017  }
2018 }
2019 
2020 /** \brief Prepare the pattern matcher ctx in a sig group head.
2021  *
2022  */
2024 {
2025  MpmStore *mpm_store = NULL;
2026  if (SGH_PROTO(sh, IPPROTO_TCP)) {
2027  if (SGH_DIRECTION_TS(sh)) {
2028  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_PKT_TS);
2029  if (mpm_store != NULL) {
2030  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
2031  }
2032 
2034  if (mpm_store != NULL) {
2035  PrefilterPktStreamRegister(de_ctx, sh, mpm_store->mpm_ctx);
2036  }
2037 
2038  SetRawReassemblyFlag(de_ctx, sh);
2039  }
2040  if (SGH_DIRECTION_TC(sh)) {
2041  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_PKT_TC);
2042  if (mpm_store != NULL) {
2043  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
2044  }
2045 
2047  if (mpm_store != NULL) {
2048  PrefilterPktStreamRegister(de_ctx, sh, mpm_store->mpm_ctx);
2049  }
2050 
2051  SetRawReassemblyFlag(de_ctx, sh);
2052  }
2053  } else if (SGH_PROTO(sh, IPPROTO_UDP)) {
2054  if (SGH_DIRECTION_TS(sh)) {
2055  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_UDP_TS);
2056  if (mpm_store != NULL) {
2057  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
2058  }
2059  }
2060  if (SGH_DIRECTION_TC(sh)) {
2061  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_UDP_TC);
2062  if (mpm_store != NULL) {
2063  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
2064  }
2065  }
2066  } else {
2067  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_OTHERIP);
2068  if (mpm_store != NULL) {
2069  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
2070  }
2071  }
2072 
2073  PrepareAppMpms(de_ctx, sh);
2074  PreparePktMpms(de_ctx, sh);
2075  PrepareFrameMpms(de_ctx, sh);
2076  return 0;
2077 }
2078 
2079 typedef struct DetectFPAndItsId_ {
2081  uint16_t content_len;
2082  uint32_t flags;
2083  int sm_list;
2084 
2085  uint8_t *content;
2087 
2088 /**
2089  * \brief Figured out the FP and their respective content ids for all the
2090  * sigs in the engine.
2091  *
2092  * \param de_ctx Detection engine context.
2093  *
2094  * \retval 0 On success.
2095  * \retval -1 On failure.
2096  */
2098 {
2099  uint32_t struct_total_size = 0;
2100  uint32_t content_total_size = 0;
2101  Signature *s = NULL;
2102 
2103  /* Count the amount of memory needed to store all the structures
2104  * and the content of those structures. This will over estimate the
2105  * true size, since duplicates are removed below, but counted here.
2106  */
2107  for (s = de_ctx->sig_list; s != NULL; s = s->next) {
2108  if (s->flags & SIG_FLAG_PREFILTER)
2109  continue;
2110 
2112  if (s->init_data->mpm_sm != NULL) {
2114  struct_total_size += sizeof(DetectFPAndItsId);
2115  content_total_size += cd->content_len;
2116 
2117  s->flags |= SIG_FLAG_PREFILTER;
2118  }
2119  }
2120  /* no rules */
2121  if (struct_total_size + content_total_size == 0)
2122  return 0;
2123 
2124  /* array hash buffer - I've run out of ideas to name it */
2125  uint8_t *ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
2126  if (unlikely(ahb == NULL))
2127  return -1;
2128 
2129  uint8_t *content = NULL;
2130  uint16_t content_len = 0;
2131  PatIntId max_id = 0;
2132  DetectFPAndItsId *struct_offset = (DetectFPAndItsId *)ahb;
2133  uint8_t *content_offset = ahb + struct_total_size;
2134 
2135  for (s = de_ctx->sig_list; s != NULL; s = s->next) {
2136  if (s->init_data->mpm_sm != NULL) {
2137  int sm_list = SigMatchListSMBelongsTo(s, s->init_data->mpm_sm);
2138  BUG_ON(sm_list == -1);
2139 
2141  DetectFPAndItsId *dup = (DetectFPAndItsId *)ahb;
2143  content = cd->content + cd->fp_chop_offset;
2144  content_len = cd->fp_chop_len;
2145  } else {
2146  content = cd->content;
2147  content_len = cd->content_len;
2148  }
2149  uint32_t flags = cd->flags & DETECT_CONTENT_NOCASE;
2150  /* Check for content already found on the same list */
2151  for (; dup != struct_offset; dup++) {
2152  if (dup->content_len != content_len)
2153  continue;
2154  if (dup->sm_list != sm_list)
2155  continue;
2156  if (dup->flags != flags)
2157  continue;
2158  /* Check for pattern matching a duplicate. Use case insensitive matching
2159  * for case insensitive patterns. */
2160  if (flags & DETECT_CONTENT_NOCASE) {
2161  if (SCMemcmpLowercase(dup->content, content, content_len) != 0)
2162  continue;
2163  } else {
2164  /* Case sensitive matching */
2165  if (SCMemcmp(dup->content, content, content_len) != 0)
2166  continue;
2167  }
2168  /* Found a match with a previous pattern. */
2169  break;
2170  }
2171  if (dup != struct_offset) {
2172  /* Exited for-loop before the end, so found an existing match.
2173  * Use its ID. */
2174  cd->id = dup->id;
2175  continue;
2176  }
2177 
2178  /* Not found, so new content. Give it a new ID and add it
2179  * to the array. Copy the content at the end of the
2180  * content array.
2181  */
2182  struct_offset->id = max_id++;
2183  cd->id = struct_offset->id;
2184  struct_offset->content_len = content_len;
2185  struct_offset->sm_list = sm_list;
2186  struct_offset->content = content_offset;
2187  struct_offset->flags = flags;
2188 
2189  content_offset += content_len;
2190 
2191  if (flags & DETECT_CONTENT_NOCASE) {
2192  /* Need to store case-insensitive patterns as lower case
2193  * because SCMemcmpLowercase() above assumes that all
2194  * patterns are stored lower case so that it doesn't
2195  * need to re-lower its first argument.
2196  */
2197  memcpy_tolower(struct_offset->content, content, content_len);
2198  } else {
2199  memcpy(struct_offset->content, content, content_len);
2200  }
2201 
2202  struct_offset++;
2203  } /* if (s->mpm_sm != NULL) */
2204  } /* for */
2205 
2206  de_ctx->max_fp_id = max_id;
2207 
2208  SCFree(ahb);
2209 
2210  return 0;
2211 }
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:785
DetectEngineCtx_::pkt_mpms_list_cnt
uint32_t pkt_mpms_list_cnt
Definition: detect.h:972
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:59
DetectEngineCtx_::frame_mpms_list_cnt
uint32_t frame_mpms_list_cnt
Definition: detect.h:975
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:100
SCFPSupportSMList_
Definition: detect.h:697
MPMB_UDP_TS
@ MPMB_UDP_TS
Definition: detect.h:1293
DetectBufferMpmRegistery_::direction
int direction
Definition: detect.h:635
DetectFPAndItsId_::flags
uint32_t flags
Definition: detect-engine-mpm.c:2082
detect-content.h
SGH_DIRECTION_TC
#define SGH_DIRECTION_TC(sgh)
Definition: detect-engine-mpm.c:1013
MpmCtx_::mpm_type
uint8_t mpm_type
Definition: util-mpm.h:90
detect-engine.h
MPM_TABLE_SIZE
@ MPM_TABLE_SIZE
Definition: util-mpm.h:40
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:897
MpmStore_::sid_array_size
uint32_t sid_array_size
Definition: detect.h:1301
DetectContentData_::fp_chop_len
uint16_t fp_chop_len
Definition: detect-content.h:91
MpmStore_::sid_array
uint8_t * sid_array
Definition: detect.h:1300
DetectFPAndItsId_
Definition: detect-engine-mpm.c:2079
DetectEngineCtx_::sgh_mpm_context_proto_tcp_packet
int32_t sgh_mpm_context_proto_tcp_packet
Definition: detect.h:887
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:2023
SCFPSupportSMList_::next
struct SCFPSupportSMList_ * next
Definition: detect.h:700
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:524
detect-engine-siggroup.h
SCFPSupportSMList_::list_id
int list_id
Definition: detect.h:698
SigTableElmt_::name
const char * name
Definition: detect.h:1249
MpmStoreFree
void MpmStoreFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->mpm_hash_table, allocated by MpmStoreInit() function.
Definition: detect-engine-mpm.c:1439
DetectFrameMpmRegisterByParentId
void DetectFrameMpmRegisterByParentId(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:341
MpmThreadCtx_
Definition: util-mpm.h:46
Signature_::num
SigIntId num
Definition: detect.h:557
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:1407
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectEngineTransforms
Definition: detect.h:379
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:1341
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
MPMB_OTHERIP
@ MPMB_OTHERIP
Definition: detect.h:1295
DetectEngineCtx_::max_fp_id
uint32_t max_fp_id
Definition: detect.h:869
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint16_t matcher)
Definition: util-mpm.c:200
DetectBufferTypeSupportsFrames
void DetectBufferTypeSupportsFrames(const char *name)
Definition: detect-engine.c:1043
DetectMpmInitializeFrameMpms
void DetectMpmInitializeFrameMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:441
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:80
DetectBufferMpmRegistery_::transforms
DetectEngineTransforms transforms
Definition: detect.h:646
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:1305
PatternStrength
uint32_t PatternStrength(uint8_t *pat, uint16_t patlen)
Predict a strength value for patterns.
Definition: detect-engine-mpm.c:933
DETECT_BUFFER_MPM_TYPE_FRAME
@ DETECT_BUFFER_MPM_TYPE_FRAME
Definition: detect.h:626
ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE
@ ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE
Definition: detect.h:1010
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:2097
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:385
PrefilterGenericMpmRegister
int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:753
DetectEngineCtx_::frame_mpms_list
DetectBufferMpmRegistery * frame_mpms_list
Definition: detect.h:974
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:30
DetectBufferMpmRegistery_::app_v2
struct DetectBufferMpmRegistery_::@87::@89 app_v2
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:801
DetectBufferMpmRegistery_::type
enum DetectBufferMpmType type
Definition: detect.h:640
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:2081
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:446
DetectMpmInitializeBuiltinMpms
void DetectMpmInitializeBuiltinMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:715
SIG_FLAG_REQUIRE_STREAM
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:224
DE_QUIET
#define DE_QUIET
Definition: detect.h:295
MpmCtx_::maxlen
uint16_t maxlen
Definition: util-mpm.h:100
MPMB_TCP_STREAM_TS
@ MPMB_TCP_STREAM_TS
Definition: detect.h:1291
PatIntId
#define PatIntId
Definition: suricata-common.h:299
DetectBufferMpmRegistery_
one time registration of keywords at start up
Definition: detect.h:632
SIG_GROUP_HEAD_HAVERAWSTREAM
#define SIG_GROUP_HEAD_HAVERAWSTREAM
Definition: detect.h:1279
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:601
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:1296
DetectEngineCtx_::mpm_matcher
uint16_t mpm_matcher
Definition: detect.h:851
DetectEngineCtx_::sgh_mpm_context_proto_udp_packet
int32_t sgh_mpm_context_proto_udp_packet
Definition: detect.h:888
ShortenString
void ShortenString(const char *input, char *output, size_t output_size, char c)
Definition: util-misc.c:217
DetectEngineRegisterFastPatternForId
void DetectEngineRegisterFastPatternForId(DetectEngineCtx *de_ctx, int list_id, int priority)
Definition: detect-fast-pattern.c:136
MPMB_TCP_STREAM_TC
@ MPMB_TCP_STREAM_TC
Definition: detect.h:1292
detect-engine-prefilter.h
DetectFPAndItsId_::content
uint8_t * content
Definition: detect-engine-mpm.c:2085
DetectBufferMpmRegistery_::id
int id
Definition: detect.h:639
DetectBufferMpmRegistery_::frame_v1
struct DetectBufferMpmRegistery_::@87::@91 frame_v1
MpmBuiltinBuffers
MpmBuiltinBuffers
Definition: detect.h:1288
mpm_default_matcher
uint16_t mpm_default_matcher
Definition: util-mpm.c:49
DetectEngineCtx_::app_mpms_list
DetectBufferMpmRegistery * app_mpms_list
Definition: detect.h:968
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1083
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:147
util-memcmp.h
SigGroupHeadInitData_::pkt_mpms
MpmCtx ** pkt_mpms
Definition: detect.h:1388
DetectBufferMpmRegistery_::sgh_mpm_context
int sgh_mpm_context
Definition: detect.h:641
Signature_::next
struct Signature_ * next
Definition: detect.h:620
DetectEngineCtx_::sgh_mpm_context_proto_other_packet
int32_t sgh_mpm_context_proto_other_packet
Definition: detect.h:889
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
DetectEngineFrameMpmRegister
void DetectEngineFrameMpmRegister(DetectEngineCtx *de_ctx, const char *name, int direction, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id), AppProto alproto, uint8_t type)
Definition: detect-engine-mpm.c:379
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
type
uint8_t type
Definition: decode-icmpv4.h:0
SigGroupHeadInitData_::sig_cnt
SigIntId sig_cnt
Definition: detect.h:1397
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:614
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:1299
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:518
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:643
DetectEngineGetMaxSigId
#define DetectEngineGetMaxSigId(de_ctx)
Definition: detect-engine.h:103
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:325
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:914
DetectEngineBufferTypeRegister
int DetectEngineBufferTypeRegister(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1170
SigGroupHead_::init
SigGroupHeadInitData * init
Definition: detect.h:1430
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:324
DetectProto_::proto
uint8_t proto[256/8]
Definition: detect-engine-proto.h:37
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:281
MpmStore_::direction
int direction
Definition: detect.h:1303
MPMCTX_FLAGS_GLOBAL
#define MPMCTX_FLAGS_GLOBAL
Definition: util-mpm.h:85
DetectBufferMpmRegistery_::name
const char * name
Definition: detect.h:633
Signature_::flags
uint32_t flags
Definition: detect.h:547
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:99
DetectFrameMpmRegister
void DetectFrameMpmRegister(const char *name, int direction, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id), AppProto alproto, uint8_t type)
register a MPM engine
Definition: detect-engine-mpm.c:293
stream.h
PatternMatchThreadPrint
void PatternMatchThreadPrint(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:903
DetectEngineCtx_::sgh_mpm_context_stream
int32_t sgh_mpm_context_stream
Definition: detect.h:890
DetectEngineBufferTypeSupportsFrames
void DetectEngineBufferTypeSupportsFrames(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1209
conf.h
DetectEngineCtx_::sgh_mpm_ctx_cnf
uint8_t sgh_mpm_ctx_cnf
Definition: detect.h:864
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:127
DETECT_BUFFER_MPM_TYPE_PKT
@ DETECT_BUFFER_MPM_TYPE_PKT
Definition: detect.h:624
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:164
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:617
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:540
SCFPSupportSMList_::priority
int priority
Definition: detect.h:699
HashListTable_
Definition: util-hashlist.h:37
DetectEngineTransforms::transforms
TransformData transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:380
SigGroupHeadInitData_::app_mpms
MpmCtx ** app_mpms
Definition: detect.h:1387
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
DetectEngineBufferTypeSupportsTransformations
void DetectEngineBufferTypeSupportsTransformations(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1233
SGH_DIRECTION_TS
#define SGH_DIRECTION_TS(sgh)
Definition: detect-engine-mpm.c:1012
MpmStore_::mpm_ctx
MpmCtx * mpm_ctx
Definition: detect.h:1308
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:1549
DetectBufferMpmRegistery_::priority
int priority
Definition: detect.h:638
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:88
MPMB_TCP_PKT_TC
@ MPMB_TCP_PKT_TC
Definition: detect.h:1290
DetectMpmPrepareFrameMpms
int DetectMpmPrepareFrameMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for applayer buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:496
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:821
util-mpm.h
DetectBufferMpmRegistery_::pname
char pname[32]
Definition: detect.h:634
flags
uint8_t flags
Definition: decode-gre.h:0
Signature_::proto
DetectProto proto
Definition: detect.h:564
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:1275
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:625
DetectBufferTypeSupportsMpm
void DetectBufferTypeSupportsMpm(const char *name)
Definition: detect-engine.c:1063
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:82
SigGroupHeadInitData_::match_array
Signature ** match_array
Definition: detect.h:1400
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:131
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:855
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:807
DetectMpmPreparePktMpms
int DetectMpmPreparePktMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for applayer buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:669
TransformData_::transform
int transform
Definition: detect.h:375
DetectEngineBufferTypeSupportsMpm
void DetectEngineBufferTypeSupportsMpm(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1225
util-validate.h
detect-flow.h
DetectEngineCtx_::app_mpms_list_cnt
uint32_t app_mpms_list_cnt
Definition: detect.h:969
DetectBufferTypeSupportsTransformations
void DetectBufferTypeSupportsTransformations(const char *name)
Definition: detect-engine.c:1073
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
builtin_mpms
const char * builtin_mpms[]
Definition: detect-engine-mpm.c:65
DetectEngineCtx_::mpm_hash_table
HashListTable * mpm_hash_table
Definition: detect.h:842
MPMB_UDP_TC
@ MPMB_UDP_TC
Definition: detect.h:1294
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:1408
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:728
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
Signature_::id
uint32_t id
Definition: detect.h:580
HashListTableBucket_
Definition: util-hashlist.h:28
detect-tcphdr.h
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:546
SigMatch_
a single match condition for a signature
Definition: detect.h:321
DetectBufferMpmRegistery_::pkt_v1
struct DetectBufferMpmRegistery_::@87::@90 pkt_v1
MPMB_TCP_PKT_TS
@ MPMB_TCP_PKT_TS
Definition: detect.h:1289
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:971
DetectMpmInitializeAppMpms
void DetectMpmInitializeAppMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:214
DetectEngineTransforms::cnt
int cnt
Definition: detect.h:381
suricata.h
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:816
DETECT_BUFFER_MPM_TYPE_SIZE
@ DETECT_BUFFER_MPM_TYPE_SIZE
Definition: detect.h:628
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:88
DetectFPAndItsId_::id
PatIntId id
Definition: detect-engine-mpm.c:2080
DetectEngineCtx_::buffer_type_id
uint32_t buffer_type_id
Definition: detect.h:963
PrefilterGenericMpmPktRegister
int PrefilterGenericMpmPktRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:823
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:802
MpmTableElmt_::DestroyThreadCtx
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:149
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:1011
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:576
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:636
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:268
DetectEngineCtx_::fp_support_smlist_list
SCFPSupportSMList * fp_support_smlist_list
Definition: detect.h:994
MpmStore_::sgh_mpm_context
int32_t sgh_mpm_context
Definition: detect.h:1306
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:908
DetectFPAndItsId_::sm_list
int sm_list
Definition: detect-engine-mpm.c:2083
MpmStore_::buffer
enum MpmBuiltinBuffers buffer
Definition: detect.h:1304
RetrieveFPForSig
void RetrieveFPForSig(const DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine-mpm.c:1078
PrefilterPktStreamRegister
int PrefilterPktStreamRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx)
Definition: detect-engine-payload.c:106
DetectBufferMpmRegistery_::next
struct DetectBufferMpmRegistery_ * next
Definition: detect.h:671
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:538
DetectBufferMpmRegistery_::sm_list_base
int16_t sm_list_base
Definition: detect.h:637
SigGroupHeadInitData_::frame_mpms
MpmCtx ** frame_mpms
Definition: detect.h:1389
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:223