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 #include "util-hash-string.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 DetectBufferMpmRegistry *g_mpm_list[DETECT_BUFFER_MPM_TYPE_SIZE] = { NULL, NULL, NULL };
83 static int g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_SIZE] = { 0, 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 static void RegisterInternal(const char *name, int direction, int priority,
90  PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData,
92  InspectionMultiBufferGetDataPtr GetMultiData, AppProto alproto, int tx_min_progress)
93 {
94  SCLogDebug("registering %s/%d/%d/%p/%p/%u/%d", name, direction, priority,
95  PrefilterRegister, GetData, alproto, tx_min_progress);
96 
97  BUG_ON(tx_min_progress >= 48);
98 
99  if (PrefilterRegister == PrefilterGenericMpmRegister && GetData == NULL) {
100  // must register GetData with PrefilterGenericMpmRegister
101  abort();
102  }
103 
106  int sm_list = DetectBufferTypeGetByName(name);
107  if (sm_list == -1) {
108  FatalError("MPM engine registration for %s failed", name);
109  }
110 
111  // every HTTP2 can be accessed from DOH2
112  if (alproto == ALPROTO_HTTP2 || alproto == ALPROTO_DNS) {
113  RegisterInternal(name, direction, priority, PrefilterRegister, GetData, GetDataSingle,
114  GetMultiData, ALPROTO_DOH2, tx_min_progress);
115  }
116  DetectBufferMpmRegistry *am = SCCalloc(1, sizeof(*am));
117  BUG_ON(am == NULL);
118  am->name = name;
119  snprintf(am->pname, sizeof(am->pname), "%s", am->name);
120  am->direction = direction;
121  DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > INT16_MAX);
122  am->sm_list = (int16_t)sm_list;
123  am->sm_list_base = (int16_t)sm_list;
124  am->priority = priority;
126 
127  am->PrefilterRegisterWithListId = PrefilterRegister;
128  if (GetData != NULL) {
129  am->app_v2.GetData = GetData;
130  } else if (GetDataSingle != NULL) {
131  am->app_v2.GetDataSingle = GetDataSingle;
132  } else if (GetMultiData != NULL) {
133  am->app_v2.GetMultiData = GetMultiData;
134  }
135  am->app_v2.alproto = alproto;
136  am->app_v2.tx_min_progress = tx_min_progress;
137 
138  if (g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP] == NULL) {
139  g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP] = am;
140  } else {
142  while (t->next != NULL) {
143  t = t->next;
144  }
145 
146  t->next = am;
147  am->id = t->id + 1;
148  }
149  g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_APP]++;
150 
151  SupportFastPatternForSigMatchList(sm_list, priority);
152 }
153 
154 void DetectAppLayerMpmRegister(const char *name, int direction, int priority,
155  PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData,
156  AppProto alproto, int tx_min_progress)
157 {
158  RegisterInternal(name, direction, priority, PrefilterRegister, GetData, NULL, NULL, alproto,
159  tx_min_progress);
160 }
161 
162 void DetectAppLayerMpmRegisterSingle(const char *name, int direction, int priority,
163  PrefilterRegisterFunc PrefilterRegister, InspectionSingleBufferGetDataPtr GetData,
164  AppProto alproto, int tx_min_progress)
165 {
166  RegisterInternal(name, direction, priority, PrefilterRegister, NULL, GetData, NULL, alproto,
167  tx_min_progress);
168 }
169 
170 void DetectAppLayerMpmMultiRegister(const char *name, int direction, int priority,
171  PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData,
172  AppProto alproto, int tx_min_progress)
173 {
174  RegisterInternal(name, direction, priority, PrefilterRegister, NULL, NULL, GetData, alproto,
175  tx_min_progress);
176 }
177 
178 /** \brief copy a mpm engine from parent_id, add in transforms */
180  const int id, const int parent_id,
181  DetectEngineTransforms *transforms)
182 {
183  SCLogDebug("registering %d/%d", id, parent_id);
184 
186  while (t) {
187  if (t->sm_list == parent_id) {
188  DetectBufferMpmRegistry *am = SCCalloc(1, sizeof(*am));
189  BUG_ON(am == NULL);
190  am->name = t->name;
191  am->direction = t->direction;
192  DEBUG_VALIDATE_BUG_ON(id < 0 || id > INT16_MAX);
193  am->sm_list = (uint16_t)id; // use new id
194  am->sm_list_base = t->sm_list;
197  am->app_v2.GetData = t->app_v2.GetData;
198  am->app_v2.alproto = t->app_v2.alproto;
199  am->app_v2.tx_min_progress = t->app_v2.tx_min_progress;
200  am->priority = t->priority;
203  de_ctx, am->name, am->sm_list, am->app_v2.alproto);
204  am->next = t->next;
205  if (transforms) {
206  memcpy(&am->transforms, transforms, sizeof(*transforms));
207 
208  /* create comma separated string of the names of the
209  * transforms and then shorten it if necessary. Finally
210  * use it to construct the 'profile' name for the engine */
211  char xforms[1024] = "";
212  for (int i = 0; i < transforms->cnt; i++) {
213  char ttstr[64];
214  (void)snprintf(ttstr,sizeof(ttstr), "%s,",
215  sigmatch_table[transforms->transforms[i].transform].name);
216  strlcat(xforms, ttstr, sizeof(xforms));
217  }
218  xforms[strlen(xforms)-1] = '\0';
219 
220  size_t space = sizeof(am->pname) - strlen(am->name) - 3;
221  char toprint[space + 1];
222  memset(toprint, 0x00, space + 1);
223  if (space < strlen(xforms)) {
224  ShortenString(xforms, toprint, space, '~');
225  } else {
226  strlcpy(toprint, xforms,sizeof(toprint));
227  }
228  (void)snprintf(am->pname, sizeof(am->pname), "%s#%d (%s)",
229  am->name, id, toprint);
230  } else {
231  (void)snprintf(am->pname, sizeof(am->pname), "%s#%d",
232  am->name, id);
233  }
234  am->id = de_ctx->app_mpms_list_cnt++;
235 
237  t->next = am;
238  SCLogDebug("copied mpm registration for %s id %u "
239  "with parent %u and GetData %p",
240  t->name, id, parent_id, am->app_v2.GetData);
241  t = am;
242  }
243  t = t->next;
244  }
245 }
246 
248 {
249  const DetectBufferMpmRegistry *list = g_mpm_list[DETECT_BUFFER_MPM_TYPE_APP];
251  while (list != NULL) {
252  DetectBufferMpmRegistry *n = SCCalloc(1, sizeof(*n));
253  BUG_ON(n == NULL);
254 
255  *n = *list;
256  n->next = NULL;
257 
258  if (toadd == NULL) {
259  toadd = n;
260  de_ctx->app_mpms_list = n;
261  } else {
262  toadd->next = n;
263  toadd = toadd->next;
264  }
265 
266  /* default to whatever the global setting is */
268 
269  /* see if we use a unique or shared mpm ctx for this type */
270  int confshared = 0;
271  char confstring[256] = "detect.mpm.";
272  strlcat(confstring, n->name, sizeof(confstring));
273  strlcat(confstring, ".shared", sizeof(confstring));
274  if (SCConfGetBool(confstring, &confshared) == 1)
275  shared = confshared;
276 
277  if (shared == 0) {
278  SCLogDebug("using unique mpm ctx' for %s", n->name);
280  } else {
281  SCLogDebug("using shared mpm ctx' for %s", n->name);
282  n->sgh_mpm_context =
284  }
285 
286  list = list->next;
287  }
289  SCLogDebug("mpm: de_ctx app_mpms_list %p %u",
291 }
292 
293 /**
294  * \brief initialize mpm contexts for applayer buffers that are in
295  * "single or "shared" mode.
296  */
298 {
299  int r = 0;
301  while (am != NULL) {
302  int dir = (am->direction == SIG_FLAG_TOSERVER) ? 1 : 0;
303 
305  {
307  if (mpm_ctx != NULL) {
308  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
309  r |= mpm_table[de_ctx->mpm_matcher].Prepare(de_ctx->mpm_cfg, mpm_ctx);
310  }
311  }
312  }
313  am = am->next;
314  }
315  return r;
316 }
317 
318 /** \brief register a MPM engine
319  *
320  * \note to be used at start up / registration only. Errors are fatal.
321  */
322 void DetectFrameMpmRegister(const char *name, int direction, int priority,
323  int (*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
324  const DetectBufferMpmRegistry *mpm_reg, int list_id),
325  AppProto alproto, uint8_t type)
326 {
327  SCLogDebug("registering %s/%d/%p/%s/%u", name, priority, PrefilterRegister,
328  AppProtoToString(alproto), type);
329 
333  int sm_list = DetectBufferTypeGetByName(name);
334  if (sm_list < 0 || sm_list > UINT16_MAX) {
335  FatalError("MPM engine registration for %s failed", name);
336  }
337 
338  DetectBufferMpmRegistry *am = SCCalloc(1, sizeof(*am));
339  BUG_ON(am == NULL);
340  am->name = name;
341  snprintf(am->pname, sizeof(am->pname), "%s", am->name);
342  am->sm_list = (uint16_t)sm_list;
343  am->direction = direction;
344  am->priority = priority;
346 
347  am->PrefilterRegisterWithListId = PrefilterRegister;
348  am->frame_v1.alproto = alproto;
349  am->frame_v1.type = type;
350  SCLogDebug("type %u", type);
351  SCLogDebug("am type %u", am->frame_v1.type);
352 
353  if (g_mpm_list[DETECT_BUFFER_MPM_TYPE_FRAME] == NULL) {
354  g_mpm_list[DETECT_BUFFER_MPM_TYPE_FRAME] = am;
355  } else {
357  while (t->next != NULL) {
358  t = t->next;
359  }
360  t->next = am;
361  am->id = t->id + 1;
362  }
363  g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_FRAME]++;
364 
365  SupportFastPatternForSigMatchList(sm_list, priority);
366  SCLogDebug("%s/%d done", name, sm_list);
367 }
368 
369 /** \brief copy a mpm engine from parent_id, add in transforms */
370 void DetectFrameMpmRegisterByParentId(DetectEngineCtx *de_ctx, const int id, const int parent_id,
371  DetectEngineTransforms *transforms)
372 {
373  SCLogDebug("registering %d/%d", id, parent_id);
374 
376  while (t) {
377  if (t->sm_list == parent_id) {
378  DetectBufferMpmRegistry *am = SCCalloc(1, sizeof(*am));
379  BUG_ON(am == NULL);
380  am->name = t->name;
381  snprintf(am->pname, sizeof(am->pname), "%s#%d", am->name, id);
382  DEBUG_VALIDATE_BUG_ON(id < 0 || id > UINT16_MAX);
383  am->sm_list = (uint16_t)id; // use new id
384  am->sm_list_base = t->sm_list;
387  am->frame_v1 = t->frame_v1;
388  SCLogDebug("am type %u", am->frame_v1.type);
389  am->priority = t->priority;
390  am->direction = t->direction;
392  am->next = t->next;
393  if (transforms) {
394  memcpy(&am->transforms, transforms, sizeof(*transforms));
395  }
396  am->id = de_ctx->frame_mpms_list_cnt++;
397 
399  t->next = am;
400  SCLogDebug("copied mpm registration for %s id %u "
401  "with parent %u",
402  t->name, id, parent_id);
403  t = am;
404  }
405  t = t->next;
406  }
407 }
408 
409 void DetectEngineFrameMpmRegister(DetectEngineCtx *de_ctx, const char *name, int direction,
410  int priority,
411  int (*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
412  const DetectBufferMpmRegistry *mpm_reg, int list_id),
413  AppProto alproto, uint8_t type)
414 {
415  SCLogDebug("registering %s/%d/%p/%s/%u", name, priority, PrefilterRegister,
416  AppProtoToString(alproto), type);
417 
418  const int sm_list = DetectEngineBufferTypeRegister(de_ctx, name);
419  if (sm_list < 0 || sm_list > UINT16_MAX) {
420  FatalError("MPM engine registration for %s failed", name);
421  }
422 
426 
427  DetectBufferMpmRegistry *am = SCCalloc(1, sizeof(*am));
428  BUG_ON(am == NULL);
429  am->name = name;
430  snprintf(am->pname, sizeof(am->pname), "%s", am->name);
431  am->sm_list = (uint16_t)sm_list;
432  am->direction = direction;
433  am->priority = priority;
435 
436  am->PrefilterRegisterWithListId = PrefilterRegister;
437  am->frame_v1.alproto = alproto;
438  am->frame_v1.type = type;
439 
440  // TODO is it ok to do this here?
441 
442  /* default to whatever the global setting is */
444  /* see if we use a unique or shared mpm ctx for this type */
445  int confshared = 0;
446  if (SCConfGetBool("detect.mpm.frame.shared", &confshared) == 1)
447  shared = confshared;
448 
449  if (shared == 0) {
451  } else {
452  am->sgh_mpm_context =
454  }
455 
456  if (de_ctx->frame_mpms_list == NULL) {
457  de_ctx->frame_mpms_list = am;
458  } else {
460  while (t->next != NULL) {
461  t = t->next;
462  }
463 
464  t->next = am;
465  }
467 
468  DetectEngineRegisterFastPatternForId(de_ctx, sm_list, priority);
469  SCLogDebug("%s/%d done", name, sm_list);
470 }
471 
473 {
474  const DetectBufferMpmRegistry *list = g_mpm_list[DETECT_BUFFER_MPM_TYPE_FRAME];
475  while (list != NULL) {
476  DetectBufferMpmRegistry *n = SCCalloc(1, sizeof(*n));
477  BUG_ON(n == NULL);
478 
479  *n = *list;
480  n->next = NULL;
481 
482  if (de_ctx->frame_mpms_list == NULL) {
483  de_ctx->frame_mpms_list = n;
484  } else {
486  while (t->next != NULL) {
487  t = t->next;
488  }
489 
490  t->next = n;
491  }
492 
493  /* default to whatever the global setting is */
495 
496  /* see if we use a unique or shared mpm ctx for this type */
497  int confshared = 0;
498  char confstring[256] = "detect.mpm.";
499  strlcat(confstring, n->name, sizeof(confstring));
500  strlcat(confstring, ".shared", sizeof(confstring));
501  if (SCConfGetBool(confstring, &confshared) == 1)
502  shared = confshared;
503 
504  if (shared == 0) {
505  SCLogDebug("using unique mpm ctx' for %s", n->name);
507  } else {
508  SCLogDebug("using shared mpm ctx' for %s", n->name);
510  de_ctx, n->name, n->sm_list, n->frame_v1.alproto);
511  }
512 
513  list = list->next;
514  }
516  SCLogDebug("mpm: de_ctx frame_mpms_list %p %u", de_ctx->frame_mpms_list,
518 }
519 
520 /**
521  * \brief initialize mpm contexts for applayer buffers that are in
522  * "single or "shared" mode.
523  */
525 {
526  SCLogDebug("preparing frame mpm");
527  int r = 0;
529  while (am != NULL) {
530  SCLogDebug("am %p %s sgh_mpm_context %d", am, am->name, am->sgh_mpm_context);
531  SCLogDebug("%s", am->name);
533  int dir = (am->direction == SIG_FLAG_TOSERVER) ? 1 : 0;
535  SCLogDebug("%s: %d mpm_Ctx %p", am->name, r, mpm_ctx);
536  if (mpm_ctx != NULL) {
537  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
538  r |= mpm_table[de_ctx->mpm_matcher].Prepare(de_ctx->mpm_cfg, mpm_ctx);
539  SCLogDebug("%s: %d", am->name, r);
540  }
541  }
542  }
543  am = am->next;
544  }
545  return r;
546 }
547 
548 /** \brief register a MPM engine
549  *
550  * \note to be used at start up / registration only. Errors are fatal.
551  */
552 void DetectPktMpmRegister(const char *name, int priority,
553  int (*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx,
554  const DetectBufferMpmRegistry *mpm_reg, int list_id),
556 {
557  SCLogDebug("registering %s/%d/%p/%p", name, priority,
558  PrefilterRegister, GetData);
559 
560  if (PrefilterRegister == PrefilterGenericMpmPktRegister && GetData == NULL) {
561  // must register GetData with PrefilterGenericMpmRegister
562  abort();
563  }
564 
567  int sm_list = DetectBufferTypeGetByName(name);
568  if (sm_list == -1) {
569  FatalError("MPM engine registration for %s failed", name);
570  }
571 
572  DetectBufferMpmRegistry *am = SCCalloc(1, sizeof(*am));
573  BUG_ON(am == NULL);
574  am->name = name;
575  snprintf(am->pname, sizeof(am->pname), "%s", am->name);
576  DEBUG_VALIDATE_BUG_ON(sm_list < 0 || sm_list > INT16_MAX);
577  am->sm_list = (uint16_t)sm_list;
578  am->priority = priority;
580 
581  am->PrefilterRegisterWithListId = PrefilterRegister;
582  am->pkt_v1.GetData = GetData;
583 
584  if (g_mpm_list[DETECT_BUFFER_MPM_TYPE_PKT] == NULL) {
585  g_mpm_list[DETECT_BUFFER_MPM_TYPE_PKT] = am;
586  } else {
588  while (t->next != NULL) {
589  t = t->next;
590  }
591  t->next = am;
592  am->id = t->id + 1;
593  }
594  g_mpm_list_cnt[DETECT_BUFFER_MPM_TYPE_PKT]++;
595 
596  SupportFastPatternForSigMatchList(sm_list, priority);
597  SCLogDebug("%s/%d done", name, sm_list);
598 }
599 
600 /** \brief copy a mpm engine from parent_id, add in transforms */
602  const int id, const int parent_id,
603  DetectEngineTransforms *transforms)
604 {
605  SCLogDebug("registering %d/%d", id, parent_id);
606 
608  while (t) {
609  if (t->sm_list == parent_id) {
610  DetectBufferMpmRegistry *am = SCCalloc(1, sizeof(*am));
611  BUG_ON(am == NULL);
612  am->name = t->name;
613  snprintf(am->pname, sizeof(am->pname), "%s#%d", am->name, id);
614  DEBUG_VALIDATE_BUG_ON(id < 0 || id > INT16_MAX);
615  am->sm_list = (uint16_t)id; // use new id
616  am->sm_list_base = t->sm_list;
619  am->pkt_v1.GetData = t->pkt_v1.GetData;
620  am->priority = t->priority;
622  am->next = t->next;
623  if (transforms) {
624  memcpy(&am->transforms, transforms, sizeof(*transforms));
625  }
626  am->id = de_ctx->pkt_mpms_list_cnt++;
627 
629  t->next = am;
630  SCLogDebug("copied mpm registration for %s id %u "
631  "with parent %u and GetData %p",
632  t->name, id, parent_id, am->pkt_v1.GetData);
633  t = am;
634  }
635  t = t->next;
636  }
637 }
638 
640 {
641  const DetectBufferMpmRegistry *list = g_mpm_list[DETECT_BUFFER_MPM_TYPE_PKT];
642  while (list != NULL) {
643  DetectBufferMpmRegistry *n = SCCalloc(1, sizeof(*n));
644  BUG_ON(n == NULL);
645 
646  *n = *list;
647  n->next = NULL;
648 
649  if (de_ctx->pkt_mpms_list == NULL) {
650  de_ctx->pkt_mpms_list = n;
651  } else {
653  while (t->next != NULL) {
654  t = t->next;
655  }
656 
657  t->next = n;
658  }
659 
660  /* default to whatever the global setting is */
662 
663  /* see if we use a unique or shared mpm ctx for this type */
664  int confshared = 0;
665  char confstring[256] = "detect.mpm.";
666  strlcat(confstring, n->name, sizeof(confstring));
667  strlcat(confstring, ".shared", sizeof(confstring));
668  if (SCConfGetBool(confstring, &confshared) == 1)
669  shared = confshared;
670 
671  if (shared == 0) {
672  SCLogDebug("using unique mpm ctx' for %s", n->name);
674  } else {
675  SCLogDebug("using shared mpm ctx' for %s", n->name);
676  n->sgh_mpm_context =
678  }
679 
680  list = list->next;
681  }
683  SCLogDebug("mpm: de_ctx pkt_mpms_list %p %u",
685 }
686 
687 /**
688  * \brief initialize mpm contexts for applayer buffers that are in
689  * "single or "shared" mode.
690  */
692 {
693  SCLogDebug("preparing pkt mpm");
694  int r = 0;
696  while (am != NULL) {
697  SCLogDebug("%s", am->name);
699  {
701  if (mpm_ctx != NULL) {
702  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
703  r |= mpm_table[de_ctx->mpm_matcher].Prepare(de_ctx->mpm_cfg, mpm_ctx);
704  SCLogDebug("%s: %d", am->name, r);
705  }
706  }
707  }
708  am = am->next;
709  }
710  return r;
711 }
712 
713 static int32_t SetupBuiltinMpm(DetectEngineCtx *de_ctx, const char *name)
714 {
715  /* default to whatever the global setting is */
717 
718  /* see if we use a unique or shared mpm ctx for this type */
719  int confshared = 0;
720  char confstring[256] = "detect.mpm.";
721  strlcat(confstring, name, sizeof(confstring));
722  strlcat(confstring, ".shared", sizeof(confstring));
723  if (SCConfGetBool(confstring, &confshared) == 1)
724  shared = confshared;
725 
726  int32_t ctx;
727  if (shared == 0) {
729  SCLogDebug("using unique mpm ctx' for %s", name);
730  } else {
732  SCLogDebug("using shared mpm ctx' for %s", name);
733  }
734  return ctx;
735 }
736 
738 {
739  de_ctx->sgh_mpm_context_proto_tcp_packet = SetupBuiltinMpm(de_ctx, "tcp-packet");
740  de_ctx->sgh_mpm_context_stream = SetupBuiltinMpm(de_ctx, "tcp-stream");
741 
742  de_ctx->sgh_mpm_context_proto_udp_packet = SetupBuiltinMpm(de_ctx, "udp-packet");
743  de_ctx->sgh_mpm_context_proto_other_packet = SetupBuiltinMpm(de_ctx, "other-ip");
744 }
745 
746 /**
747  * \brief initialize mpm contexts for builtin buffers that are in
748  * "single or "shared" mode.
749  */
751 {
752  int r = 0;
753  MpmCtx *mpm_ctx = NULL;
754 
757  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
758  r |= mpm_table[de_ctx->mpm_matcher].Prepare(de_ctx->mpm_cfg, mpm_ctx);
759  }
761  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
762  r |= mpm_table[de_ctx->mpm_matcher].Prepare(de_ctx->mpm_cfg, mpm_ctx);
763  }
764  }
765 
768  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
769  r |= mpm_table[de_ctx->mpm_matcher].Prepare(de_ctx->mpm_cfg, mpm_ctx);
770  }
772  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
773  r |= mpm_table[de_ctx->mpm_matcher].Prepare(de_ctx->mpm_cfg, mpm_ctx);
774  }
775  }
776 
779  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
780  r |= mpm_table[de_ctx->mpm_matcher].Prepare(de_ctx->mpm_cfg, mpm_ctx);
781  }
782  }
783 
786  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
787  r |= mpm_table[de_ctx->mpm_matcher].Prepare(de_ctx->mpm_cfg, mpm_ctx);
788  }
790  if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) {
791  r |= mpm_table[de_ctx->mpm_matcher].Prepare(de_ctx->mpm_cfg, mpm_ctx);
792  }
793  }
794 
795  return r;
796 }
797 
798 /**
799  * \brief check if a signature has patterns that are to be inspected
800  * against a packets payload (as opposed to the stream payload)
801  *
802  * \param s signature
803  *
804  * \retval 1 true
805  * \retval 0 false
806  */
808 {
809  SCEnter();
810 
811  if (!(s->proto.proto[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8))) {
812  SCReturnInt(1);
813  }
814 
815  if (s->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
816  SCLogDebug("no PMATCH");
817  SCReturnInt(0);
818  }
819 
820  if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
821  SCReturnInt(0);
822  }
823 
824  SCReturnInt(1);
825 }
826 
827 /**
828  * \brief check if a signature has patterns that are to be inspected
829  * against the stream payload (as opposed to the individual packets
830  * payload(s))
831  *
832  * \param s signature
833  *
834  * \retval 1 true
835  * \retval 0 false
836  */
838 {
839  SCEnter();
840 
841  if (!(s->proto.proto[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8))) {
842  SCReturnInt(0);
843  }
844 
845  if (s->init_data->smlists[DETECT_SM_LIST_PMATCH] == NULL) {
846  SCLogDebug("no PMATCH");
847  SCReturnInt(0);
848  }
849 
850  if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
851  SCReturnInt(0);
852  }
853 
854  SCReturnInt(1);
855 }
856 
857 
858 /**
859  * \brief Function to return the multi pattern matcher algorithm to be
860  * used by the engine, based on the mpm-algo setting in yaml
861  * Use the default mpm if none is specified in the yaml file.
862  *
863  * \retval mpm algo value
864  */
866 {
867  const char *mpm_algo;
868  uint8_t mpm_algo_val = mpm_default_matcher;
869 
870  /* Get the mpm algo defined in config file by the user */
871  if ((SCConfGet("mpm-algo", &mpm_algo)) == 1) {
872  if (mpm_algo != NULL) {
873 #if __BYTE_ORDER == __BIG_ENDIAN
874  if (strcmp(mpm_algo, "ac-ks") == 0) {
875  FatalError("ac-ks does "
876  "not work on big endian systems at this time.");
877  }
878 #endif
879  if (strcmp("auto", mpm_algo) == 0) {
880  goto done;
881  } else if (strcmp("ac-bs", mpm_algo) == 0) {
882  SCLogWarning("mpm-algo \"ac-bs\" has been removed. See ticket #6586.");
883  goto done;
884  }
885  for (uint8_t u = 0; u < MPM_TABLE_SIZE; u++) {
886  if (mpm_table[u].name == NULL)
887  continue;
888 
889  if (strcmp(mpm_table[u].name, mpm_algo) == 0) {
890  mpm_algo_val = u;
891  goto done;
892  }
893  }
894 
895 #ifndef BUILD_HYPERSCAN
896  if ((strcmp(mpm_algo, "hs") == 0)) {
897  FatalError("Hyperscan (hs) support for mpm-algo is "
898  "not compiled into Suricata.");
899  }
900 #endif
901  }
902  FatalError("Invalid mpm algo supplied "
903  "in the yaml conf file: \"%s\"",
904  mpm_algo);
905  }
906 
907  done:
908  return mpm_algo_val;
909 }
910 
911 void PatternMatchDestroy(MpmCtx *mpm_ctx, uint16_t mpm_matcher)
912 {
913  SCLogDebug("mpm_ctx %p, mpm_matcher %"PRIu16"", mpm_ctx, mpm_matcher);
914  mpm_table[mpm_matcher].DestroyCtx(mpm_ctx);
915 }
916 
917 void PatternMatchThreadDestroy(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
918 {
919  SCLogDebug("mpm_thread_ctx %p, mpm_matcher %"PRIu16"", mpm_thread_ctx, mpm_matcher);
920  MpmDestroyThreadCtx(mpm_thread_ctx, mpm_matcher);
921 }
922 void PatternMatchThreadPrepare(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
923 {
924  SCLogDebug("mpm_thread_ctx %p, type %"PRIu16, mpm_thread_ctx, mpm_matcher);
925  MpmInitThreadCtx(mpm_thread_ctx, mpm_matcher);
926 }
927 
928 /** \brief Predict a strength value for patterns
929  *
930  * Patterns with high character diversity score higher.
931  * Alpha chars score not so high
932  * Other printable + a few common codes a little higher
933  * Everything else highest.
934  * Longer patterns score better than short patters.
935  *
936  * \param pat pattern
937  * \param patlen length of the pattern
938  *
939  * \retval s pattern score
940  */
941 uint32_t PatternStrength(uint8_t *pat, uint16_t patlen)
942 {
943  uint8_t a[256];
944  memset(&a, 0 ,sizeof(a));
945 
946  uint32_t s = 0;
947  uint16_t u = 0;
948  for (u = 0; u < patlen; u++) {
949  if (a[pat[u]] == 0) {
950  if (isalpha(pat[u]))
951  s += 3;
952  else if (isprint(pat[u]) || pat[u] == 0x00 || pat[u] == 0x01 || pat[u] == 0xFF)
953  s += 4;
954  else
955  s += 6;
956 
957  a[pat[u]] = 1;
958  } else {
959  s++;
960  }
961  }
962 
963  return s;
964 }
965 
966 static void PopulateMpmHelperAddPattern(MpmCtx *mpm_ctx, const DetectContentData *cd,
967  const Signature *s, const uint8_t flags, const int chop)
968 {
969  uint16_t pat_offset = cd->offset;
970  uint16_t pat_depth = cd->depth;
971 
972  /* recompute offset/depth to cope with chop */
973  if (chop && (pat_depth || pat_offset)) {
974  pat_offset += cd->fp_chop_offset;
975  if (pat_depth) {
976  pat_depth -= cd->content_len;
977  pat_depth += cd->fp_chop_offset + cd->fp_chop_len;
978  }
979  }
980 
981  /* We have to effectively "wild card" values that will be coming from
982  * byte_extract variables
983  */
985  pat_depth = pat_offset = 0;
986  }
987 
988  if (cd->flags & DETECT_CONTENT_NOCASE) {
989  if (chop) {
990  MpmAddPatternCI(mpm_ctx, cd->content + cd->fp_chop_offset, cd->fp_chop_len, pat_offset,
991  pat_depth, cd->id, s->iid, flags | MPM_PATTERN_CTX_OWNS_ID);
992  } else {
993  MpmAddPatternCI(mpm_ctx, cd->content, cd->content_len, pat_offset, pat_depth, cd->id,
995  }
996  } else {
997  if (chop) {
998  MpmAddPatternCS(mpm_ctx, cd->content + cd->fp_chop_offset, cd->fp_chop_len, pat_offset,
999  pat_depth, cd->id, s->iid, flags | MPM_PATTERN_CTX_OWNS_ID);
1000  } else {
1001  MpmAddPatternCS(mpm_ctx, cd->content, cd->content_len, pat_offset, pat_depth, cd->id,
1003  }
1004  }
1005 }
1006 
1007 #define SGH_PROTO(sgh, p) ((sgh)->init->protos[(p)] == 1)
1008 #define SGH_DIRECTION_TS(sgh) ((sgh)->init->direction & SIG_FLAG_TOSERVER)
1009 #define SGH_DIRECTION_TC(sgh) ((sgh)->init->direction & SIG_FLAG_TOCLIENT)
1011 static void SetMpm(Signature *s, SigMatch *mpm_sm, const int mpm_sm_list)
1012 {
1013  if (s == NULL || mpm_sm == NULL)
1014  return;
1015 
1016  DetectContentData *cd = (DetectContentData *)mpm_sm->ctx;
1018  if (DETECT_CONTENT_IS_SINGLE(cd) &&
1019  !(cd->flags & DETECT_CONTENT_NEGATED) &&
1020  !(cd->flags & DETECT_CONTENT_REPLACE) &&
1021  cd->content_len == cd->fp_chop_len)
1022  {
1024  }
1025  } else {
1026  if (DETECT_CONTENT_IS_SINGLE(cd) &&
1027  !(cd->flags & DETECT_CONTENT_NEGATED) &&
1028  !(cd->flags & DETECT_CONTENT_REPLACE))
1029  {
1031  }
1032  }
1033  cd->flags |= DETECT_CONTENT_MPM;
1034  s->init_data->mpm_sm_list = mpm_sm_list;
1035  s->init_data->mpm_sm = mpm_sm;
1036 }
1037 
1038 static SigMatch *GetMpmForList(const Signature *s, SigMatch *list, SigMatch *mpm_sm,
1039  uint16_t max_len, bool skip_negated_content)
1040 {
1041  for (SigMatch *sm = list; sm != NULL; sm = sm->next) {
1042  if (sm->type != DETECT_CONTENT)
1043  continue;
1044 
1045  const DetectContentData *cd = (DetectContentData *)sm->ctx;
1046  /* skip_negated_content is only set if there's absolutely no
1047  * non-negated content present in the sig */
1048  if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
1049  continue;
1050  if (cd->content_len != max_len) {
1051  SCLogDebug("content_len %u != max_len %u", cd->content_len, max_len);
1052  continue;
1053  }
1054  if (mpm_sm == NULL) {
1055  mpm_sm = sm;
1056  } else {
1057  DetectContentData *data1 = (DetectContentData *)sm->ctx;
1058  DetectContentData *data2 = (DetectContentData *)mpm_sm->ctx;
1059  uint32_t ls = PatternStrength(data1->content, data1->content_len);
1060  uint32_t ss = PatternStrength(data2->content, data2->content_len);
1061  if (ls > ss) {
1062  mpm_sm = sm;
1063  } else if (ls == ss) {
1064  /* if 2 patterns are of equal strength, we pick the longest */
1065  if (data1->content_len > data2->content_len)
1066  mpm_sm = sm;
1067  } else {
1068  SCLogDebug("sticking with mpm_sm");
1069  }
1070  }
1071  }
1072  return mpm_sm;
1073 }
1074 
1076 
1077 // tells if a buffer id is only used to client
1078 bool DetectBufferToClient(const DetectEngineCtx *de_ctx, int buf_id, AppProto alproto)
1079 {
1080  bool r = false;
1082  for (; app != NULL; app = app->next) {
1083  if (app->sm_list == buf_id &&
1084  (AppProtoEquals(alproto, app->alproto) || alproto == ALPROTO_UNKNOWN)) {
1085  if (app->dir == 1) {
1086  // do not return yet in case we have app engines on both sides
1087  r = true;
1088  } else {
1089  // ambiguous keywords have a app-engine to server
1090  return false;
1091  }
1092  }
1093  }
1094  return r;
1095 }
1096 
1098 {
1099  if (g_skip_prefilter)
1100  return;
1101 
1102  if (s->init_data->mpm_sm != NULL)
1103  return;
1104 
1105  const int nlists = s->init_data->max_content_list_id + 1;
1106  int pos_sm_list[nlists];
1107  int neg_sm_list[nlists];
1108  memset(pos_sm_list, 0, nlists * sizeof(int));
1109  memset(neg_sm_list, 0, nlists * sizeof(int));
1110  int pos_sm_list_cnt = 0;
1111  int neg_sm_list_cnt = 0;
1112 
1113  /* inspect rule to see if we have the fast_pattern reg to
1114  * force using a sig, otherwise keep stats about the patterns */
1115  if (s->init_data->smlists[DETECT_SM_LIST_PMATCH] != NULL) {
1117  for (SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_PMATCH]; sm != NULL;
1118  sm = sm->next) {
1119  if (sm->type != DETECT_CONTENT)
1120  continue;
1121 
1122  const DetectContentData *cd = (DetectContentData *)sm->ctx;
1123  /* fast_pattern set in rule, so using this pattern */
1124  if ((cd->flags & DETECT_CONTENT_FAST_PATTERN)) {
1125  SetMpm(s, sm, DETECT_SM_LIST_PMATCH);
1126  return;
1127  }
1128 
1129  if (cd->flags & DETECT_CONTENT_NEGATED) {
1130  neg_sm_list[DETECT_SM_LIST_PMATCH] = 1;
1131  neg_sm_list_cnt++;
1132  } else {
1133  pos_sm_list[DETECT_SM_LIST_PMATCH] = 1;
1134  pos_sm_list_cnt++;
1135  }
1136  }
1137  }
1138  }
1139  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
1140  const int list_id = s->init_data->buffers[x].id;
1141 
1142  SCLogDebug("%u: list_id %d: %s", s->id, list_id,
1144 
1146  SCLogDebug("skip");
1147  continue;
1148  }
1149 
1150  for (SigMatch *sm = s->init_data->buffers[x].head; sm != NULL; sm = sm->next) {
1151  // a buffer with absent keyword cannot be used as fast_pattern
1152  if (sm->type == DETECT_ABSENT)
1153  break;
1154  if (sm->type != DETECT_CONTENT)
1155  continue;
1156 
1157  const DetectContentData *cd = (DetectContentData *)sm->ctx;
1158  /* fast_pattern set in rule, so using this pattern */
1159  if ((cd->flags & DETECT_CONTENT_FAST_PATTERN)) {
1160  SetMpm(s, sm, list_id);
1161  return;
1162  }
1163 
1164  if (cd->flags & DETECT_CONTENT_NEGATED) {
1165  neg_sm_list[list_id] = 1;
1166  neg_sm_list_cnt++;
1167  } else {
1168  pos_sm_list[list_id] = 1;
1169  pos_sm_list_cnt++;
1170  SCLogDebug("pos added for %d", list_id);
1171  }
1172  }
1173  SCLogDebug("ok");
1174  }
1175 
1176  SCLogDebug("neg_sm_list_cnt %d pos_sm_list_cnt %d", neg_sm_list_cnt, pos_sm_list_cnt);
1177 
1178  /* prefer normal not-negated over negated */
1179  int *curr_sm_list = NULL;
1180  int skip_negated_content = 1;
1181  if (pos_sm_list_cnt > 0) {
1182  curr_sm_list = pos_sm_list;
1183  } else if (neg_sm_list_cnt > 0) {
1184  curr_sm_list = neg_sm_list;
1185  skip_negated_content = 0;
1186  } else {
1187  return;
1188  }
1189 
1190  int final_sm_list[nlists];
1191  memset(&final_sm_list, 0, (nlists * sizeof(int)));
1192 
1193  int count_final_sm_list = 0;
1194  int count_txbidir_toclient_sm_list = 0;
1195  int priority;
1196 
1198  while (tmp != NULL) {
1199  for (priority = tmp->priority;
1200  tmp != NULL && priority == tmp->priority;
1201  tmp = tmp->next)
1202  {
1203  SCLogDebug("tmp->list_id %d tmp->priority %d", tmp->list_id, tmp->priority);
1204  if (tmp->list_id >= nlists)
1205  continue;
1206  if (curr_sm_list[tmp->list_id] == 0)
1207  continue;
1208  if (s->flags & SIG_FLAG_TXBOTHDIR) {
1209  // prefer to choose a fast_pattern to server by default
1210  if (DetectBufferToClient(de_ctx, tmp->list_id, s->alproto)) {
1211  if (count_final_sm_list == 0) {
1212  // still put it in in the case we do not have toserver buffer
1213  final_sm_list[count_txbidir_toclient_sm_list++] = tmp->list_id;
1214  }
1215  continue;
1216  }
1217  }
1218  // we may erase tx bidir toclient buffers here as intended if we have a better choice
1219  final_sm_list[count_final_sm_list++] = tmp->list_id;
1220  SCLogDebug("tmp->list_id %d", tmp->list_id);
1221  }
1222  if (count_final_sm_list != 0)
1223  break;
1224  }
1225 
1226  if ((s->flags & SIG_FLAG_TXBOTHDIR) && count_final_sm_list == 0) {
1227  // forced to pick a fast_pattern to client for tx bidir signature
1228  count_final_sm_list = count_txbidir_toclient_sm_list;
1229  }
1230  BUG_ON(count_final_sm_list == 0);
1231  SCLogDebug("count_final_sm_list %d skip_negated_content %d", count_final_sm_list,
1232  skip_negated_content);
1233 
1234  uint16_t max_len = 0;
1235  for (int i = 0; i < count_final_sm_list; i++) {
1236  SCLogDebug("i %d final_sm_list[i] %d", i, final_sm_list[i]);
1237 
1238  if (final_sm_list[i] == DETECT_SM_LIST_PMATCH) {
1239  for (SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_PMATCH]; sm != NULL;
1240  sm = sm->next) {
1241  if (sm->type != DETECT_CONTENT)
1242  continue;
1243 
1244  const DetectContentData *cd = (DetectContentData *)sm->ctx;
1245  /* skip_negated_content is only set if there's absolutely no
1246  * non-negated content present in the sig */
1247  if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
1248  continue;
1249  max_len = MAX(max_len, cd->content_len);
1250  }
1251  } else {
1252  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
1253  if (s->init_data->buffers[x].only_tc) {
1254  // prefer to choose a fast_pattern to server by default
1255  continue;
1256  }
1257  const int list_id = s->init_data->buffers[x].id;
1258 
1259  if (final_sm_list[i] == list_id) {
1260  SCLogDebug("%u: list_id %d: %s", s->id, list_id,
1262 
1263  for (SigMatch *sm = s->init_data->buffers[x].head; sm != NULL; sm = sm->next) {
1264  if (sm->type != DETECT_CONTENT)
1265  continue;
1266 
1267  const DetectContentData *cd = (DetectContentData *)sm->ctx;
1268  /* skip_negated_content is only set if there's absolutely no
1269  * non-negated content present in the sig */
1270  if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
1271  continue;
1272  max_len = MAX(max_len, cd->content_len);
1273  }
1274  }
1275  }
1276  }
1277  }
1278 
1279  SigMatch *mpm_sm = NULL;
1280  int mpm_sm_list = -1;
1281  for (int i = 0; i < count_final_sm_list; i++) {
1282  SCLogDebug("i %d", i);
1283  if (final_sm_list[i] == DETECT_SM_LIST_PMATCH) {
1284  /* GetMpmForList may keep `mpm_sm` the same, so track if it changed */
1285  SigMatch *prev_mpm_sm = mpm_sm;
1286  mpm_sm = GetMpmForList(s, s->init_data->smlists[DETECT_SM_LIST_PMATCH], mpm_sm, max_len,
1287  skip_negated_content);
1288  if (mpm_sm != prev_mpm_sm) {
1289  mpm_sm_list = final_sm_list[i];
1290  }
1291  } else {
1292  SCLogDebug(
1293  "%u: %s", s->id, DetectEngineBufferTypeGetNameById(de_ctx, final_sm_list[i]));
1294  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
1295  const int list_id = s->init_data->buffers[x].id;
1296  if (final_sm_list[i] == list_id) {
1297  SCLogDebug("%u: list_id %d: %s", s->id, list_id,
1299  /* GetMpmForList may keep `mpm_sm` the same, so track if it changed */
1300  SigMatch *prev_mpm_sm = mpm_sm;
1301  mpm_sm = GetMpmForList(s, s->init_data->buffers[x].head, mpm_sm, max_len,
1302  skip_negated_content);
1303  SCLogDebug("mpm_sm %p from %p", mpm_sm, s->init_data->buffers[x].head);
1304  if (mpm_sm != prev_mpm_sm) {
1305  mpm_sm_list = list_id;
1306  }
1307  }
1308  }
1309  }
1310  }
1311 
1312 #ifdef DEBUG
1313  if (mpm_sm != NULL) {
1314  BUG_ON(mpm_sm_list == -1);
1315  int check_list = SigMatchListSMBelongsTo(s, mpm_sm);
1316  BUG_ON(check_list != mpm_sm_list);
1317  }
1318 #endif
1319  /* assign to signature */
1320  SetMpm(s, mpm_sm, mpm_sm_list);
1321 }
1322 
1323 /** \internal
1324  * \brief The hash function for MpmStore
1325  *
1326  * \param ht Pointer to the hash table.
1327  * \param data Pointer to the MpmStore.
1328  * \param datalen Not used in our case.
1329  *
1330  * \retval hash The generated hash value.
1331  */
1332 static uint32_t MpmStoreHashFunc(HashListTable *ht, void *data, uint16_t datalen)
1333 {
1334  const MpmStore *ms = (MpmStore *)data;
1335  uint32_t hash = ms->alproto;
1336 
1337  for (uint32_t b = 0; b < ms->sid_array_size; b++)
1338  hash += ms->sid_array[b];
1339 
1340  return hash % ht->array_size;
1341 }
1342 
1343 /**
1344  * \brief The Compare function for MpmStore
1345  *
1346  * \param data1 Pointer to the first MpmStore.
1347  * \param len1 Not used.
1348  * \param data2 Pointer to the second MpmStore.
1349  * \param len2 Not used.
1350  *
1351  * \retval 1 If the 2 MpmStores sent as args match.
1352  * \retval 0 If the 2 MpmStores sent as args do not match.
1353  */
1354 static char MpmStoreCompareFunc(void *data1, uint16_t len1, void *data2,
1355  uint16_t len2)
1356 {
1357  const MpmStore *ms1 = (MpmStore *)data1;
1358  const MpmStore *ms2 = (MpmStore *)data2;
1359 
1360  if (ms1->alproto != ms2->alproto)
1361  return 0;
1362 
1363  if (ms1->sid_array_size != ms2->sid_array_size)
1364  return 0;
1365 
1366  if (ms1->buffer != ms2->buffer)
1367  return 0;
1368 
1369  if (ms1->direction != ms2->direction)
1370  return 0;
1371 
1372  if (ms1->sm_list != ms2->sm_list)
1373  return 0;
1374 
1375  if (SCMemcmp(ms1->sid_array, ms2->sid_array,
1376  ms1->sid_array_size) != 0)
1377  {
1378  return 0;
1379  }
1380 
1381  return 1;
1382 }
1383 
1384 static void MpmStoreFreeFunc(void *ptr)
1385 {
1386  MpmStore *ms = ptr;
1387  if (ms != NULL) {
1388  if (ms->mpm_ctx != NULL && !(ms->mpm_ctx->flags & MPMCTX_FLAGS_GLOBAL))
1389  {
1390  SCLogDebug("destroying mpm_ctx %p", ms->mpm_ctx);
1392  SCFree(ms->mpm_ctx);
1393  }
1394  ms->mpm_ctx = NULL;
1395 
1396  SCFree(ms->sid_array);
1397  SCFree(ms);
1398  }
1399 }
1400 
1401 /**
1402  * \brief Initializes the MpmStore mpm hash table to be used by the detection
1403  * engine context.
1404  *
1405  * \param de_ctx Pointer to the detection engine context.
1406  *
1407  * \retval 0 On success.
1408  * \retval -1 On failure.
1409  */
1411 {
1413  MpmStoreHashFunc,
1414  MpmStoreCompareFunc,
1415  MpmStoreFreeFunc);
1416  if (de_ctx->mpm_hash_table == NULL)
1417  goto error;
1418 
1419  return 0;
1420 
1421 error:
1422  return -1;
1423 }
1424 
1425 /**
1426  * \brief Adds a MpmStore to the detection engine context MpmStore
1427  *
1428  * \param de_ctx Pointer to the detection engine context.
1429  * \param sgh Pointer to the MpmStore.
1430  *
1431  * \retval ret 0 on Successfully adding the argument sgh; -1 on failure.
1432  */
1433 static int MpmStoreAdd(DetectEngineCtx *de_ctx, MpmStore *s)
1434 {
1435  int ret = HashListTableAdd(de_ctx->mpm_hash_table, (void *)s, 0);
1436  return ret;
1437 }
1438 
1439 /**
1440  * \brief Used to lookup a MpmStore from the MpmStore
1441  *
1442  * \param de_ctx Pointer to the detection engine context.
1443  * \param sgh Pointer to the MpmStore.
1444  *
1445  * \retval rsgh On success a pointer to the MpmStore if the MpmStore is
1446  * found in the hash table; NULL on failure.
1447  */
1448 static MpmStore *MpmStoreLookup(DetectEngineCtx *de_ctx, MpmStore *s)
1449 {
1451  (void *)s, 0);
1452  return rs;
1453 }
1454 
1455 static const DetectBufferMpmRegistry *GetByMpmStore(
1456  const DetectEngineCtx *de_ctx, const MpmStore *ms)
1457 {
1459  while (am != NULL) {
1460  if (ms->sm_list == am->sm_list &&
1461  ms->direction == am->direction) {
1462  return am;
1463  }
1464  am = am->next;
1465  }
1466  am = de_ctx->pkt_mpms_list;
1467  while (am != NULL) {
1468  if (ms->sm_list == am->sm_list) {
1469  return am;
1470  }
1471  am = am->next;
1472  }
1473  return NULL;
1474 }
1475 
1477 {
1478  HashListTableBucket *htb = NULL;
1479 
1480  uint32_t stats[MPMB_MAX] = {0};
1481  int app_mpms_cnt = de_ctx->buffer_type_id;
1482  uint32_t appstats[app_mpms_cnt + 1]; // +1 to silence scan-build
1483  memset(&appstats, 0x00, sizeof(appstats));
1484  int pkt_mpms_cnt = de_ctx->buffer_type_id;
1485  uint32_t pktstats[pkt_mpms_cnt + 1]; // +1 to silence scan-build
1486  memset(&pktstats, 0x00, sizeof(pktstats));
1487  int frame_mpms_cnt = de_ctx->buffer_type_id;
1488  uint32_t framestats[frame_mpms_cnt + 1]; // +1 to silence scan-build
1489  memset(&framestats, 0x00, sizeof(framestats));
1490 
1492  htb != NULL;
1493  htb = HashListTableGetListNext(htb))
1494  {
1495  const MpmStore *ms = (MpmStore *)HashListTableGetListData(htb);
1496  if (ms == NULL || ms->mpm_ctx == NULL) {
1497  continue;
1498  }
1499  if (ms->buffer < MPMB_MAX)
1500  stats[ms->buffer]++;
1501  else if (ms->sm_list != DETECT_SM_LIST_PMATCH) {
1502  const DetectBufferMpmRegistry *am = GetByMpmStore(de_ctx, ms);
1503  if (am != NULL) {
1504  switch (am->type) {
1506  SCLogDebug("%s: %u patterns. Min %u, Max %u. Ctx %p",
1507  am->name,
1508  ms->mpm_ctx->pattern_cnt,
1509  ms->mpm_ctx->minlen, ms->mpm_ctx->maxlen,
1510  ms->mpm_ctx);
1511  pktstats[am->sm_list]++;
1512  break;
1514  SCLogDebug("%s %s %s: %u patterns. Min %u, Max %u. Ctx %p",
1515  AppProtoToString(ms->alproto), am->name,
1516  am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient",
1517  ms->mpm_ctx->pattern_cnt, ms->mpm_ctx->minlen, ms->mpm_ctx->maxlen,
1518  ms->mpm_ctx);
1519  appstats[am->sm_list]++;
1520  break;
1522  SCLogDebug("%s: %u patterns. Min %u, Max %u. Ctx %p", am->name,
1523  ms->mpm_ctx->pattern_cnt, ms->mpm_ctx->minlen, ms->mpm_ctx->maxlen,
1524  ms->mpm_ctx);
1525  framestats[am->sm_list]++;
1526  break;
1528  break;
1529  }
1530  }
1531  }
1532  }
1533 
1534  if (!(de_ctx->flags & DE_QUIET)) {
1535  for (int x = 0; x < MPMB_MAX; x++) {
1536  SCLogPerf("Builtin MPM \"%s\": %u", builtin_mpms[x], stats[x]);
1537  }
1539  while (am != NULL) {
1540  if (appstats[am->sm_list] > 0) {
1541  const char *name = am->name;
1542  const char *direction = am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient";
1543  SCLogPerf("AppLayer MPM \"%s %s (%s)\": %u", direction, name,
1544  AppProtoToString(am->app_v2.alproto), appstats[am->sm_list]);
1545  }
1546  am = am->next;
1547  }
1549  while (pm != NULL) {
1550  if (pktstats[pm->sm_list] > 0) {
1551  const char *name = pm->name;
1552  SCLogPerf("Pkt MPM \"%s\": %u", name, pktstats[pm->sm_list]);
1553  }
1554  pm = pm->next;
1555  }
1557  while (um != NULL) {
1558  if (framestats[um->sm_list] > 0) {
1559  const char *name = um->name;
1560  SCLogPerf("Frame MPM \"%s\": %u", name, framestats[um->sm_list]);
1561  }
1562  um = um->next;
1563  }
1564  }
1565 }
1566 
1567 /**
1568  * \brief Frees the hash table - DetectEngineCtx->mpm_hash_table, allocated by
1569  * MpmStoreInit() function.
1570  *
1571  * \param de_ctx Pointer to the detection engine context.
1572  */
1574 {
1575  if (de_ctx->mpm_hash_table == NULL)
1576  return;
1577 
1579  de_ctx->mpm_hash_table = NULL;
1580 }
1581 
1582 static void MpmStoreSetup(const DetectEngineCtx *de_ctx, MpmStore *ms)
1583 {
1584  const Signature *s = NULL;
1585  uint32_t sig;
1586  int dir = 0;
1587 
1588  if (ms->buffer != MPMB_MAX) {
1590 
1591  switch (ms->buffer) {
1592  /* TS is 1 */
1593  case MPMB_TCP_PKT_TS:
1594  case MPMB_TCP_STREAM_TS:
1595  case MPMB_UDP_TS:
1596  dir = 1;
1597  break;
1598 
1599  /* TC is 0 */
1600  default:
1601  case MPMB_UDP_TC:
1602  case MPMB_TCP_STREAM_TC:
1603  case MPMB_TCP_PKT_TC:
1604  case MPMB_OTHERIP: /**< use 0 for other */
1605  dir = 0;
1606  break;
1607  }
1608  } else {
1610 
1611  if (ms->direction == SIG_FLAG_TOSERVER)
1612  dir = 1;
1613  else
1614  dir = 0;
1615  }
1616 
1618  if (ms->mpm_ctx == NULL) {
1619  return;
1620  }
1621 
1623 
1626 
1627  const bool mpm_supports_endswith =
1629 
1630  /* add the patterns */
1631  for (sig = 0; sig < (ms->sid_array_size * 8); sig++) {
1632  if (ms->sid_array[sig / 8] & (1 << (sig % 8))) {
1633  s = de_ctx->sig_array[sig];
1634  DEBUG_VALIDATE_BUG_ON(s == NULL);
1635  if (s == NULL)
1636  continue;
1637 
1638  SCLogDebug("%p: direction %d adding %u", ms, ms->direction, s->id);
1639 
1641 
1642  int skip = 0;
1643  /* negated logic: if mpm match can't be used to be sure about this
1644  * pattern, we have to inspect the rule fully regardless of mpm
1645  * match. So in this case there is no point of adding it at all.
1646  * The non-mpm list entry for the sig will make sure the sig is
1647  * inspected. */
1648  if ((cd->flags & DETECT_CONTENT_NEGATED) &&
1650  {
1651  skip = 1;
1652  SCLogDebug("not adding negated mpm as it's not 'single'");
1653  }
1654 
1655  if (!skip) {
1656  uint8_t flags = 0;
1657  if ((cd->flags & DETECT_CONTENT_ENDS_WITH) && mpm_supports_endswith)
1659  PopulateMpmHelperAddPattern(ms->mpm_ctx, cd, s, flags,
1661  }
1662  }
1663  }
1664 
1665  if (ms->mpm_ctx->pattern_cnt == 0) {
1667  ms->mpm_ctx = NULL;
1668  } else {
1670  if (mpm_table[ms->mpm_ctx->mpm_type].Prepare != NULL) {
1672  }
1673  }
1674  }
1675 }
1676 
1677 
1678 /** \brief Get MpmStore for a built-in buffer type
1679  *
1680  */
1682  enum MpmBuiltinBuffers buf)
1683 {
1684  const Signature *s = NULL;
1685  uint32_t sig;
1686  uint32_t cnt = 0;
1687  int direction = 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  int sgh_mpm_context = 0;
1692  int sm_list = DETECT_SM_LIST_PMATCH;
1693 
1694  switch (buf) {
1695  case MPMB_TCP_PKT_TS:
1696  case MPMB_TCP_PKT_TC:
1697  sgh_mpm_context = de_ctx->sgh_mpm_context_proto_tcp_packet;
1698  break;
1699  case MPMB_TCP_STREAM_TS:
1700  case MPMB_TCP_STREAM_TC:
1701  sgh_mpm_context = de_ctx->sgh_mpm_context_stream;
1702  break;
1703  case MPMB_UDP_TS:
1704  case MPMB_UDP_TC:
1705  sgh_mpm_context = de_ctx->sgh_mpm_context_proto_udp_packet;
1706  break;
1707  case MPMB_OTHERIP:
1708  sgh_mpm_context = de_ctx->sgh_mpm_context_proto_other_packet;
1709  break;
1710  default:
1711  break;
1712  }
1713 
1714  switch(buf) {
1715  case MPMB_TCP_PKT_TS:
1716  case MPMB_TCP_STREAM_TS:
1717  case MPMB_UDP_TS:
1718  direction = SIG_FLAG_TOSERVER;
1719  break;
1720 
1721  case MPMB_TCP_PKT_TC:
1722  case MPMB_TCP_STREAM_TC:
1723  case MPMB_UDP_TC:
1724  direction = SIG_FLAG_TOCLIENT;
1725  break;
1726 
1727  case MPMB_OTHERIP:
1728  direction = (SIG_FLAG_TOCLIENT|SIG_FLAG_TOSERVER);
1729  break;
1730 
1731  case MPMB_MAX:
1732  BUG_ON(1);
1733  break;
1734  }
1735 
1736  for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
1737  s = sgh->init->match_array[sig];
1738  if (s == NULL)
1739  continue;
1740 
1741  if (s->init_data->mpm_sm == NULL)
1742  continue;
1743 
1744  int list = s->init_data->mpm_sm_list;
1745  if (list < 0)
1746  continue;
1747 
1748  if (list != DETECT_SM_LIST_PMATCH)
1749  continue;
1750 
1751  switch (buf) {
1752  case MPMB_TCP_PKT_TS:
1753  case MPMB_TCP_PKT_TC:
1754  if (SignatureHasPacketContent(s) == 1)
1755  {
1756  sids_array[s->iid / 8] |= 1 << (s->iid % 8);
1757  cnt++;
1758  }
1759  break;
1760  case MPMB_TCP_STREAM_TS:
1761  case MPMB_TCP_STREAM_TC:
1762  if (SignatureHasStreamContent(s) == 1)
1763  {
1764  sids_array[s->iid / 8] |= 1 << (s->iid % 8);
1765  cnt++;
1766  }
1767  break;
1768  case MPMB_UDP_TS:
1769  case MPMB_UDP_TC:
1770  sids_array[s->iid / 8] |= 1 << (s->iid % 8);
1771  cnt++;
1772  break;
1773  case MPMB_OTHERIP:
1774  sids_array[s->iid / 8] |= 1 << (s->iid % 8);
1775  cnt++;
1776  break;
1777  default:
1778  break;
1779  }
1780  }
1781 
1782  if (cnt == 0)
1783  return NULL;
1784 
1785  MpmStore lookup = { sids_array, max_sid, direction, buf, sm_list, 0, 0, NULL };
1786 
1787  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1788  if (result == NULL) {
1789  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1790  if (copy == NULL)
1791  return NULL;
1792  uint8_t *sids = SCCalloc(1, max_sid);
1793  if (sids == NULL) {
1794  SCFree(copy);
1795  return NULL;
1796  }
1797 
1798  memcpy(sids, sids_array, max_sid);
1799  copy->sid_array = sids;
1800  copy->sid_array_size = max_sid;
1801  copy->buffer = buf;
1802  copy->direction = direction;
1803  copy->sm_list = sm_list;
1804  copy->sgh_mpm_context = sgh_mpm_context;
1805 
1806  MpmStoreSetup(de_ctx, copy);
1807  MpmStoreAdd(de_ctx, copy);
1808  return copy;
1809  } else {
1810  return result;
1811  }
1812 }
1813 
1814 struct SidsArray {
1815  uint8_t *sids_array;
1817  /* indicates this has an active engine */
1818  bool active;
1819 
1821 };
1822 
1823 static MpmStore *MpmStorePrepareBufferAppLayer(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
1824  const DetectBufferMpmRegistry *am, const struct SidsArray *sa)
1825 {
1826  if (sa->sids_array_size == 0 || sa->sids_array == NULL)
1827  return NULL;
1828 
1829  SCLogDebug("handling %s direction %s for list %d", am->name,
1830  am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient",
1831  am->sm_list);
1832 
1833  MpmStore lookup = { sa->sids_array, sa->sids_array_size, am->direction, MPMB_MAX, am->sm_list,
1834  0, am->app_v2.alproto, NULL };
1835  SCLogDebug("am->direction %d am->sm_list %d sgh_mpm_context %d", am->direction, am->sm_list,
1836  am->sgh_mpm_context);
1837 
1838  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1839  if (result == NULL) {
1840  SCLogDebug("new unique mpm for %s %s", am->name,
1841  am->direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient");
1842 
1843  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1844  if (copy == NULL)
1845  return NULL;
1846  uint8_t *sids = SCCalloc(1, sa->sids_array_size);
1847  if (sids == NULL) {
1848  SCFree(copy);
1849  return NULL;
1850  }
1851 
1852  memcpy(sids, sa->sids_array, sa->sids_array_size);
1853  copy->sid_array = sids;
1854  copy->sid_array_size = sa->sids_array_size;
1855  copy->buffer = MPMB_MAX;
1856  copy->direction = am->direction;
1857  copy->sm_list = am->sm_list;
1858  copy->sgh_mpm_context = am->sgh_mpm_context;
1859  copy->alproto = am->app_v2.alproto;
1860 
1861  MpmStoreSetup(de_ctx, copy);
1862  MpmStoreAdd(de_ctx, copy);
1863  return copy;
1864  } else {
1865  SCLogDebug("using existing mpm %p", result);
1866  return result;
1867  }
1868  return NULL;
1869 }
1870 
1871 static MpmStore *MpmStorePrepareBufferPkt(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
1872  const DetectBufferMpmRegistry *am, const struct SidsArray *sa)
1873 {
1874  SCLogDebug("handling %s for list %d", am->name,
1875  am->sm_list);
1876 
1877  if (sa->sids_array_size == 0 || sa->sids_array == NULL)
1878  return NULL;
1879 
1881  MPMB_MAX, am->sm_list, 0, 0, NULL };
1882  SCLogDebug("am->sm_list %d", am->sm_list);
1883 
1884  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1885  if (result == NULL) {
1886  SCLogDebug("new unique mpm for %s", am->name);
1887 
1888  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1889  if (copy == NULL)
1890  return NULL;
1891  uint8_t *sids = SCCalloc(1, sa->sids_array_size);
1892  if (sids == NULL) {
1893  SCFree(copy);
1894  return NULL;
1895  }
1896 
1897  memcpy(sids, sa->sids_array, sa->sids_array_size);
1898  copy->sid_array = sids;
1899  copy->sid_array_size = sa->sids_array_size;
1900  copy->buffer = MPMB_MAX;
1902  copy->sm_list = am->sm_list;
1903  copy->sgh_mpm_context = am->sgh_mpm_context;
1904 
1905  MpmStoreSetup(de_ctx, copy);
1906  MpmStoreAdd(de_ctx, copy);
1907  return copy;
1908  } else {
1909  SCLogDebug("using existing mpm %p", result);
1910  return result;
1911  }
1912  return NULL;
1913 }
1914 
1915 static MpmStore *MpmStorePrepareBufferFrame(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
1916  const DetectBufferMpmRegistry *am, const struct SidsArray *sa)
1917 {
1918  SCLogDebug("handling %s for list %d", am->name, am->sm_list);
1919 
1920  if (sa->sids_array_size == 0 || sa->sids_array == NULL)
1921  return NULL;
1922 
1923  MpmStore lookup = { sa->sids_array, sa->sids_array_size, am->direction, MPMB_MAX, am->sm_list,
1924  0, am->frame_v1.alproto, NULL };
1925  SCLogDebug("am->sm_list %d", am->sm_list);
1926 
1927  MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
1928  if (result == NULL) {
1929  SCLogDebug("new unique mpm for %s", am->name);
1930 
1931  MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
1932  if (copy == NULL)
1933  return NULL;
1934  uint8_t *sids = SCCalloc(1, sa->sids_array_size);
1935  if (sids == NULL) {
1936  SCFree(copy);
1937  return NULL;
1938  }
1939 
1940  memcpy(sids, sa->sids_array, sa->sids_array_size);
1941  copy->sid_array = sids;
1942  copy->sid_array_size = sa->sids_array_size;
1943  copy->buffer = MPMB_MAX;
1944  copy->direction = am->direction;
1945  copy->sm_list = am->sm_list;
1946  copy->sgh_mpm_context = am->sgh_mpm_context;
1947  copy->alproto = am->frame_v1.alproto;
1948 
1949  MpmStoreSetup(de_ctx, copy);
1950  MpmStoreAdd(de_ctx, copy);
1951  return copy;
1952  } else {
1953  SCLogDebug("using existing mpm %p", result);
1954  return result;
1955  }
1956  return NULL;
1957 }
1958 
1959 static void SetRawReassemblyFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
1960 {
1961  const Signature *s = NULL;
1962  uint32_t sig;
1963 
1964  for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
1965  s = sgh->init->match_array[sig];
1966  if (s == NULL)
1967  continue;
1968 
1969  if (SignatureHasStreamContent(s) == 1) {
1971  SCLogDebug("rule group %p has SIG_GROUP_HEAD_HAVERAWSTREAM set", sgh);
1972  return;
1973  }
1974  }
1975  SCLogDebug("rule group %p does NOT have SIG_GROUP_HEAD_HAVERAWSTREAM set", sgh);
1976 }
1977 
1978 typedef struct DetectBufferInstance {
1979  // key
1980  int list;
1982 
1983  struct SidsArray ts;
1984  struct SidsArray tc;
1986 
1987 static uint32_t DetectBufferInstanceHashFunc(HashListTable *ht, void *data, uint16_t datalen)
1988 {
1989  const DetectBufferInstance *ms = (const DetectBufferInstance *)data;
1990  uint32_t hash = ms->list + ms->alproto;
1991  return hash % ht->array_size;
1992 }
1993 
1994 static char DetectBufferInstanceCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
1995 {
1996  const DetectBufferInstance *ms1 = (DetectBufferInstance *)data1;
1997  const DetectBufferInstance *ms2 = (DetectBufferInstance *)data2;
1998  return (ms1->list == ms2->list && ms1->alproto == ms2->alproto);
1999 }
2000 
2001 static void DetectBufferInstanceFreeFunc(void *ptr)
2002 {
2003  DetectBufferInstance *ms = ptr;
2004  if (ms->ts.sids_array != NULL)
2005  SCFree(ms->ts.sids_array);
2006  if (ms->tc.sids_array != NULL)
2007  SCFree(ms->tc.sids_array);
2008  SCFree(ms);
2009 }
2010 
2011 static HashListTable *DetectBufferInstanceInit(void)
2012 {
2013  return HashListTableInit(4096, DetectBufferInstanceHashFunc, DetectBufferInstanceCompareFunc,
2014  DetectBufferInstanceFreeFunc);
2015 }
2016 
2017 static void PrepareMpms(DetectEngineCtx *de_ctx, SigGroupHead *sh)
2018 {
2019  HashListTable *bufs = DetectBufferInstanceInit();
2020  BUG_ON(bufs == NULL);
2021 
2022  const int max_buffer_id = de_ctx->buffer_type_id + 1;
2023  const uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
2024 
2025  AppProto engines[max_buffer_id][g_alproto_max];
2026  memset(engines, 0, sizeof(engines));
2027  int engines_idx[max_buffer_id];
2028  memset(engines_idx, 0, sizeof(engines_idx));
2029  int types[max_buffer_id];
2030  memset(types, 0, sizeof(types));
2031 
2032  /* flag the list+directions we have engines for as active */
2033  for (DetectBufferMpmRegistry *a = de_ctx->pkt_mpms_list; a != NULL; a = a->next) {
2034  types[a->sm_list] = a->type;
2035 
2036  DetectBufferInstance lookup = { .list = a->sm_list, .alproto = ALPROTO_UNKNOWN };
2037  DetectBufferInstance *instance = HashListTableLookup(bufs, &lookup, 0);
2038  if (instance == NULL) {
2039  instance = SCCalloc(1, sizeof(*instance));
2040  BUG_ON(instance == NULL);
2041  instance->list = a->sm_list;
2042  instance->alproto = ALPROTO_UNKNOWN;
2043  HashListTableAdd(bufs, instance, 0);
2044  }
2045  instance->ts.active = true;
2046  instance->tc.active = true;
2047  }
2048  for (DetectBufferMpmRegistry *a = de_ctx->frame_mpms_list; a != NULL; a = a->next) {
2049  const bool add_ts = ((a->direction == SIG_FLAG_TOSERVER) && SGH_DIRECTION_TS(sh));
2050  const bool add_tc = ((a->direction == SIG_FLAG_TOCLIENT) && SGH_DIRECTION_TC(sh));
2051  if (add_ts || add_tc) {
2052  types[a->sm_list] = a->type;
2053  engines[a->sm_list][engines_idx[a->sm_list]++] = a->frame_v1.alproto;
2054 
2055  DetectBufferInstance lookup = { .list = a->sm_list, .alproto = a->frame_v1.alproto };
2056  DetectBufferInstance *instance = HashListTableLookup(bufs, &lookup, 0);
2057  if (instance == NULL) {
2058  instance = SCCalloc(1, sizeof(*instance));
2059  BUG_ON(instance == NULL);
2060  instance->list = a->sm_list;
2061  instance->alproto = a->frame_v1.alproto;
2062  HashListTableAdd(bufs, instance, 0);
2063  }
2064  instance->ts.active |= add_ts;
2065  instance->tc.active |= add_tc;
2066  }
2067  }
2068  for (DetectBufferMpmRegistry *a = de_ctx->app_mpms_list; a != NULL; a = a->next) {
2069  const bool add_ts = ((a->direction == SIG_FLAG_TOSERVER) && SGH_DIRECTION_TS(sh));
2070  const bool add_tc = ((a->direction == SIG_FLAG_TOCLIENT) && SGH_DIRECTION_TC(sh));
2071  if (add_ts || add_tc) {
2072  types[a->sm_list] = a->type;
2073  engines[a->sm_list][engines_idx[a->sm_list]++] = a->app_v2.alproto;
2074 
2075  DetectBufferInstance lookup = { .list = a->sm_list, .alproto = a->app_v2.alproto };
2076  DetectBufferInstance *instance = HashListTableLookup(bufs, &lookup, 0);
2077  if (instance == NULL) {
2078  instance = SCCalloc(1, sizeof(*instance));
2079  BUG_ON(instance == NULL);
2080  instance->list = a->sm_list;
2081  instance->alproto = a->app_v2.alproto;
2082  HashListTableAdd(bufs, instance, 0);
2083  }
2084  instance->ts.active |= add_ts;
2085  instance->tc.active |= add_tc;
2086  }
2087  }
2088 
2089  for (uint32_t sig = 0; sig < sh->init->sig_cnt; sig++) {
2090  const Signature *s = sh->init->match_array[sig];
2091  if (s == NULL)
2092  continue;
2093  if (s->init_data->mpm_sm == NULL)
2094  continue;
2095  const int list = s->init_data->mpm_sm_list;
2096  if (list < 0)
2097  continue;
2098  if (list == DETECT_SM_LIST_PMATCH)
2099  continue;
2100 
2101  switch (types[list]) {
2102  /* app engines are direction aware */
2105  for (int e = 0; e < engines_idx[list]; e++) {
2106  const AppProto alproto = engines[list][e];
2107  if (!(AppProtoEquals(s->alproto, alproto) || s->alproto == 0))
2108  continue;
2109 
2110  DetectBufferInstance lookup = { .list = list, .alproto = alproto };
2111  DetectBufferInstance *instance = HashListTableLookup(bufs, &lookup, 0);
2112  if (instance == NULL)
2113  continue;
2114  if (s->flags & SIG_FLAG_TOSERVER) {
2115  struct SidsArray *sa = &instance->ts;
2116  if (sa->active) {
2117  if (sa->sids_array == NULL) {
2118  sa->sids_array = SCCalloc(1, max_sid);
2119  sa->sids_array_size = max_sid;
2120  BUG_ON(sa->sids_array == NULL); // TODO
2121  }
2122  sa->sids_array[s->iid / 8] |= 1 << (s->iid % 8);
2123  SCLogDebug("instance %p: stored %u/%u ts", instance, s->id, s->iid);
2124  }
2125  }
2126  if (s->flags & SIG_FLAG_TOCLIENT) {
2127  struct SidsArray *sa = &instance->tc;
2128  if (sa->active) {
2129  if (sa->sids_array == NULL) {
2130  sa->sids_array = SCCalloc(1, max_sid);
2131  sa->sids_array_size = max_sid;
2132  BUG_ON(sa->sids_array == NULL); // TODO
2133  }
2134  sa->sids_array[s->iid / 8] |= 1 << (s->iid % 8);
2135  SCLogDebug("instance %p: stored %u/%u tc", instance, s->id, s->iid);
2136  }
2137  }
2138  }
2139  break;
2140  }
2141  /* pkt engines are directionless, so only use ts */
2143  DetectBufferInstance lookup = { .list = list, .alproto = ALPROTO_UNKNOWN };
2144  DetectBufferInstance *instance = HashListTableLookup(bufs, &lookup, 0);
2145  if (instance == NULL)
2146  continue;
2147  struct SidsArray *sa = &instance->ts;
2148  if (sa->active) {
2149  if (sa->sids_array == NULL) {
2150  sa->sids_array = SCCalloc(1, max_sid);
2151  sa->sids_array_size = max_sid;
2152  BUG_ON(sa->sids_array == NULL); // TODO
2153  }
2154  sa->sids_array[s->iid / 8] |= 1 << (s->iid % 8);
2155  }
2156  break;
2157  }
2158  default:
2159  abort();
2160  break;
2161  }
2162  }
2163 
2164  sh->init->app_mpms = SCCalloc(de_ctx->app_mpms_list_cnt, sizeof(MpmCtx *));
2165  BUG_ON(sh->init->app_mpms == NULL);
2166 
2167  sh->init->pkt_mpms = SCCalloc(de_ctx->pkt_mpms_list_cnt, sizeof(MpmCtx *));
2168  BUG_ON(sh->init->pkt_mpms == NULL);
2169 
2171  BUG_ON(sh->init->frame_mpms == NULL);
2172 
2173  for (DetectBufferMpmRegistry *a = de_ctx->pkt_mpms_list; a != NULL; a = a->next) {
2174  DetectBufferInstance lookup = { .list = a->sm_list, .alproto = ALPROTO_UNKNOWN };
2175  DetectBufferInstance *instance = HashListTableLookup(bufs, &lookup, 0);
2176  if (instance == NULL) {
2177  continue;
2178  }
2179  struct SidsArray *sa = &instance->ts;
2180  if (!sa->active)
2181  continue;
2182 
2183  MpmStore *mpm_store = MpmStorePrepareBufferPkt(de_ctx, sh, a, sa);
2184  if (mpm_store != NULL) {
2185  sh->init->pkt_mpms[a->id] = mpm_store->mpm_ctx;
2186 
2187  SCLogDebug("a %p a->name %s a->reg->PrefilterRegisterWithListId %p "
2188  "mpm_store->mpm_ctx %p", a, a->name,
2189  a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
2190 
2191  /* if we have just certain types of negated patterns,
2192  * mpm_ctx can be NULL */
2193  if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
2194  BUG_ON(a->PrefilterRegisterWithListId(de_ctx,
2195  sh, mpm_store->mpm_ctx,
2196  a, a->sm_list) != 0);
2197  SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
2198  }
2199  }
2200  }
2201  for (DetectBufferMpmRegistry *a = de_ctx->frame_mpms_list; a != NULL; a = a->next) {
2202  if ((a->direction == SIG_FLAG_TOSERVER && SGH_DIRECTION_TS(sh)) ||
2203  (a->direction == SIG_FLAG_TOCLIENT && SGH_DIRECTION_TC(sh))) {
2204  DetectBufferInstance lookup = { .list = a->sm_list, .alproto = a->frame_v1.alproto };
2205  DetectBufferInstance *instance = HashListTableLookup(bufs, &lookup, 0);
2206  if (instance == NULL) {
2207  continue;
2208  }
2209  struct SidsArray *sa =
2210  (a->direction == SIG_FLAG_TOSERVER) ? &instance->ts : &instance->tc;
2211  if (!sa->active)
2212  continue;
2213 
2214  SCLogDebug("a %s direction %d PrefilterRegisterWithListId %p", a->name, a->direction,
2215  a->PrefilterRegisterWithListId);
2216  MpmStore *mpm_store = MpmStorePrepareBufferFrame(de_ctx, sh, a, sa);
2217  if (mpm_store != NULL) {
2218  sh->init->frame_mpms[a->id] = mpm_store->mpm_ctx;
2219 
2220  SCLogDebug("a %p a->name %s a->reg->PrefilterRegisterWithListId %p "
2221  "mpm_store->mpm_ctx %p",
2222  a, a->name, a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
2223 
2224  /* if we have just certain types of negated patterns,
2225  * mpm_ctx can be NULL */
2226  SCLogDebug("mpm_store %p mpm_ctx %p", mpm_store, mpm_store->mpm_ctx);
2227  if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
2228  BUG_ON(a->PrefilterRegisterWithListId(
2229  de_ctx, sh, mpm_store->mpm_ctx, a, a->sm_list) != 0);
2230  SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
2231  }
2232  }
2233  }
2234  }
2235  for (DetectBufferMpmRegistry *a = de_ctx->app_mpms_list; a != NULL; a = a->next) {
2236  if ((a->direction == SIG_FLAG_TOSERVER && SGH_DIRECTION_TS(sh)) ||
2237  (a->direction == SIG_FLAG_TOCLIENT && SGH_DIRECTION_TC(sh))) {
2238 
2239  DetectBufferInstance lookup = { .list = a->sm_list, .alproto = a->app_v2.alproto };
2240  DetectBufferInstance *instance = HashListTableLookup(bufs, &lookup, 0);
2241  if (instance == NULL) {
2242  continue;
2243  }
2244  struct SidsArray *sa =
2245  (a->direction == SIG_FLAG_TOSERVER) ? &instance->ts : &instance->tc;
2246  if (!sa->active)
2247  continue;
2248 
2249  MpmStore *mpm_store = MpmStorePrepareBufferAppLayer(de_ctx, sh, a, sa);
2250  if (mpm_store != NULL) {
2251  sh->init->app_mpms[a->id] = mpm_store->mpm_ctx;
2252 
2253  SCLogDebug("a %p a->name %s a->PrefilterRegisterWithListId %p "
2254  "mpm_store->mpm_ctx %p",
2255  a, a->name, a->PrefilterRegisterWithListId, mpm_store->mpm_ctx);
2256 
2257  /* if we have just certain types of negated patterns,
2258  * mpm_ctx can be NULL */
2259  if (a->PrefilterRegisterWithListId && mpm_store->mpm_ctx) {
2260  BUG_ON(a->PrefilterRegisterWithListId(
2261  de_ctx, sh, mpm_store->mpm_ctx, a, a->sm_list) != 0);
2262  SCLogDebug("mpm %s %d set up", a->name, a->sm_list);
2263  }
2264  }
2265  }
2266  }
2267  HashListTableFree(bufs);
2268 }
2269 
2270 /** \brief Prepare the pattern matcher ctx in a sig group head.
2271  *
2272  */
2274 {
2275  MpmStore *mpm_store = NULL;
2276  if (SGH_PROTO(sh, IPPROTO_TCP)) {
2277  if (SGH_DIRECTION_TS(sh)) {
2278  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_PKT_TS);
2279  if (mpm_store != NULL) {
2280  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
2281  }
2282 
2284  if (mpm_store != NULL) {
2285  PrefilterPktStreamRegister(de_ctx, sh, mpm_store->mpm_ctx);
2286  }
2287 
2288  SetRawReassemblyFlag(de_ctx, sh);
2289  }
2290  if (SGH_DIRECTION_TC(sh)) {
2291  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_PKT_TC);
2292  if (mpm_store != NULL) {
2293  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
2294  }
2295 
2297  if (mpm_store != NULL) {
2298  PrefilterPktStreamRegister(de_ctx, sh, mpm_store->mpm_ctx);
2299  }
2300 
2301  SetRawReassemblyFlag(de_ctx, sh);
2302  }
2303  } else if (SGH_PROTO(sh, IPPROTO_UDP)) {
2304  if (SGH_DIRECTION_TS(sh)) {
2305  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_UDP_TS);
2306  if (mpm_store != NULL) {
2307  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
2308  }
2309  }
2310  if (SGH_DIRECTION_TC(sh)) {
2311  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_UDP_TC);
2312  if (mpm_store != NULL) {
2313  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
2314  }
2315  }
2316  } else {
2317  mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_OTHERIP);
2318  if (mpm_store != NULL) {
2319  PrefilterPktPayloadRegister(de_ctx, sh, mpm_store->mpm_ctx);
2320  }
2321  }
2322 
2323  PrepareMpms(de_ctx, sh);
2324  return 0;
2325 }
2326 
2327 static inline uint32_t ContentFlagsForHash(const DetectContentData *cd)
2328 {
2331 }
2332 
2333 /** \internal
2334  * \brief The hash function for Pattern. Hashes pattern after chop is applied.
2335  *
2336  * \param ht Pointer to the hash table.
2337  * \param data Pointer to the Pattern.
2338  * \param datalen Not used in our case.
2339  *
2340  * \retval hash The generated hash value.
2341  */
2342 static uint32_t PatternChopHashFunc(HashListTable *ht, void *data, uint16_t datalen)
2343 {
2344  const DetectPatternTracker *p = (DetectPatternTracker *)data;
2345  uint32_t hash = p->sm_list + ContentFlagsForHash(p->cd);
2346  uint16_t content_len = p->cd->content_len;
2347  const uint8_t *content = p->cd->content;
2349  content += p->cd->fp_chop_offset;
2350  content_len = p->cd->fp_chop_len;
2351  }
2352  hash += StringHashDjb2(content, content_len);
2353  return hash % ht->array_size;
2354 }
2355 
2356 /** \internal
2357  * \brief The hash function for Pattern. Ignores chop.
2358  *
2359  * \param ht Pointer to the hash table.
2360  * \param data Pointer to the Pattern.
2361  * \param datalen Not used in our case.
2362  *
2363  * \retval hash The generated hash value.
2364  */
2365 static uint32_t PatternNoChopHashFunc(HashListTable *ht, void *data, uint16_t datalen)
2366 {
2367  const DetectPatternTracker *p = (DetectPatternTracker *)data;
2368  uint32_t hash = p->sm_list + ContentFlagsForHash(p->cd);
2369  hash += StringHashDjb2(p->cd->content, p->cd->content_len);
2370  return hash % ht->array_size;
2371 }
2372 
2373 /**
2374  * \brief The Compare function for Pattern. Compares patterns after chop is applied.
2375  *
2376  * \param data1 Pointer to the first Pattern.
2377  * \param len1 Not used.
2378  * \param data2 Pointer to the second Pattern.
2379  * \param len2 Not used.
2380  *
2381  * \retval 1 If the 2 Patterns sent as args match.
2382  * \retval 0 If the 2 Patterns sent as args do not match.
2383  */
2384 static char PatternChopCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
2385 {
2386  const DetectPatternTracker *p1 = (DetectPatternTracker *)data1;
2387  const DetectPatternTracker *p2 = (DetectPatternTracker *)data2;
2388 
2389  if (p1->sm_list != p2->sm_list)
2390  return 0;
2391 
2392  if (ContentFlagsForHash(p1->cd) != ContentFlagsForHash(p2->cd))
2393  return 0;
2394 
2395  uint16_t p1_content_len = p1->cd->content_len;
2396  uint8_t *p1_content = p1->cd->content;
2398  p1_content += p1->cd->fp_chop_offset;
2399  p1_content_len = p1->cd->fp_chop_len;
2400  }
2401  uint16_t p2_content_len = p2->cd->content_len;
2402  uint8_t *p2_content = p2->cd->content;
2404  p2_content += p2->cd->fp_chop_offset;
2405  p2_content_len = p2->cd->fp_chop_len;
2406  }
2407 
2408  if (p1_content_len != p2_content_len)
2409  return 0;
2410 
2411  if (memcmp(p1_content, p2_content, p1_content_len) != 0) {
2412  return 0;
2413  }
2414 
2415  return 1;
2416 }
2417 
2418 /**
2419  * \brief The Compare function for Pattern. Ignores chop settings
2420  *
2421  * \param data1 Pointer to the first Pattern.
2422  * \param len1 Not used.
2423  * \param data2 Pointer to the second Pattern.
2424  * \param len2 Not used.
2425  *
2426  * \retval 1 If the 2 Patterns sent as args match.
2427  * \retval 0 If the 2 Patterns sent as args do not match.
2428  */
2429 static char PatternNoChopCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
2430 {
2431  const DetectPatternTracker *p1 = (DetectPatternTracker *)data1;
2432  const DetectPatternTracker *p2 = (DetectPatternTracker *)data2;
2433 
2434  if (p1->sm_list != p2->sm_list)
2435  return 0;
2436 
2437  if (ContentFlagsForHash(p1->cd) != ContentFlagsForHash(p2->cd))
2438  return 0;
2439 
2440  if (p1->cd->content_len != p2->cd->content_len)
2441  return 0;
2442 
2443  if (memcmp(p1->cd->content, p2->cd->content, p1->cd->content_len) != 0) {
2444  return 0;
2445  }
2446 
2447  return 1;
2448 }
2449 
2450 static void PatternFreeFunc(void *ptr)
2451 {
2452  SCFree(ptr);
2453 }
2454 
2455 /**
2456  * \brief Figure out the FP and their respective content ids for all the
2457  * sigs in the engine.
2458  *
2459  * \param de_ctx Detection engine context.
2460  *
2461  * \retval 0 On success.
2462  * \retval -1 On failure.
2463  */
2465 {
2466  uint32_t cnt = 0;
2467  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2468  if (s->init_data->mpm_sm != NULL) {
2469  cnt++;
2470  }
2471  }
2472  /* no mpm rules */
2473  if (cnt == 0)
2474  return 0;
2475 
2476  HashListTable *ht =
2477  HashListTableInit(4096, PatternChopHashFunc, PatternChopCompareFunc, PatternFreeFunc);
2478  BUG_ON(ht == NULL);
2479  PatIntId max_id = 0;
2480 
2481  for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
2482  if (s->init_data->mpm_sm == NULL)
2483  continue;
2484 
2485  const int sm_list = s->init_data->mpm_sm_list;
2486  BUG_ON(sm_list == -1);
2487 
2489 
2490  DetectPatternTracker lookup = { .cd = cd, .sm_list = sm_list, .cnt = 0, .mpm = 0 };
2491  DetectPatternTracker *res = HashListTableLookup(ht, &lookup, 0);
2492  if (res) {
2493  res->cnt++;
2494  res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
2495 
2496  cd->id = res->cd->id;
2497  SCLogDebug("%u: res id %u cnt %u", s->id, res->cd->id, res->cnt);
2498  } else {
2499  DetectPatternTracker *add = SCCalloc(1, sizeof(*add));
2500  BUG_ON(add == NULL);
2501  add->cd = cd;
2502  add->sm_list = sm_list;
2503  add->cnt = 1;
2504  add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
2505  HashListTableAdd(ht, (void *)add, 0);
2506 
2507  cd->id = max_id++;
2508  SCLogDebug("%u: add id %u cnt %u", s->id, add->cd->id, add->cnt);
2509  }
2510  }
2511 
2512  HashListTableFree(ht);
2513 
2514  return 0;
2515 }
2516 
2517 /** \brief add all patterns on our stats hash
2518  * Used to fill the hash later used by DumpPatterns()
2519  * \note sets up the hash table on first call
2520  */
2522 {
2523  if (de_ctx->pattern_hash_table == NULL) {
2525  4096, PatternNoChopHashFunc, PatternNoChopCompareFunc, PatternFreeFunc);
2526  BUG_ON(de_ctx->pattern_hash_table == NULL);
2527  }
2528  if (s->sm_arrays[DETECT_SM_LIST_PMATCH]) {
2530  do {
2531  switch (smd->type) {
2532  case DETECT_CONTENT: {
2533  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
2534  DetectPatternTracker lookup = {
2535  .cd = cd, .sm_list = DETECT_SM_LIST_PMATCH, .cnt = 0, .mpm = 0
2536  };
2537  DetectPatternTracker *res =
2539  if (res) {
2540  res->cnt++;
2541  res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
2542  } else {
2543  DetectPatternTracker *add = SCCalloc(1, sizeof(*add));
2544  BUG_ON(add == NULL);
2545  add->cd = cd;
2547  add->cnt = 1;
2548  add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
2549  HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
2550  }
2551  break;
2552  }
2553  }
2554  if (smd->is_last)
2555  break;
2556  smd++;
2557  } while (1);
2558  }
2559 
2561  for (; app != NULL; app = app->next) {
2562  SigMatchData *smd = app->smd;
2563  while (smd) {
2564  switch (smd->type) {
2565  case DETECT_CONTENT: {
2566  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
2567 
2568  DetectPatternTracker lookup = {
2569  .cd = cd, .sm_list = app->sm_list, .cnt = 0, .mpm = 0
2570  };
2571  DetectPatternTracker *res =
2573  if (res) {
2574  res->cnt++;
2575  res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
2576  } else {
2577  DetectPatternTracker *add = SCCalloc(1, sizeof(*add));
2578  BUG_ON(add == NULL);
2579  add->cd = cd;
2580  add->sm_list = app->sm_list;
2581  add->cnt = 1;
2582  add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
2583  HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
2584  }
2585  break;
2586  }
2587  }
2588  if (smd->is_last)
2589  break;
2590  smd++;
2591  }
2592  }
2594  for (; pkt != NULL; pkt = pkt->next) {
2595  SigMatchData *smd = pkt->smd;
2596  do {
2597  if (smd == NULL) {
2599  smd = s->sm_arrays[pkt->sm_list];
2600  }
2601  switch (smd->type) {
2602  case DETECT_CONTENT: {
2603  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
2604 
2605  DetectPatternTracker lookup = {
2606  .cd = cd, .sm_list = pkt->sm_list, .cnt = 0, .mpm = 0
2607  };
2608  DetectPatternTracker *res =
2610  if (res) {
2611  res->cnt++;
2612  res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
2613  } else {
2614  DetectPatternTracker *add = SCCalloc(1, sizeof(*add));
2615  BUG_ON(add == NULL);
2616  add->cd = cd;
2617  add->sm_list = pkt->sm_list;
2618  add->cnt = 1;
2619  add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
2620  HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
2621  }
2622  break;
2623  }
2624  }
2625  if (smd->is_last)
2626  break;
2627  smd++;
2628  } while (1);
2629  }
2631  for (; frame != NULL; frame = frame->next) {
2632  SigMatchData *smd = frame->smd;
2633  do {
2634  if (smd == NULL) {
2636  smd = s->sm_arrays[frame->sm_list];
2637  }
2638  switch (smd->type) {
2639  case DETECT_CONTENT: {
2640  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
2641 
2642  DetectPatternTracker lookup = {
2643  .cd = cd, .sm_list = frame->sm_list, .cnt = 0, .mpm = 0
2644  };
2645  DetectPatternTracker *res =
2647  if (res) {
2648  res->cnt++;
2649  res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
2650  } else {
2651  DetectPatternTracker *add = SCCalloc(1, sizeof(*add));
2652  BUG_ON(add == NULL);
2653  add->cd = cd;
2654  add->sm_list = frame->sm_list;
2655  add->cnt = 1;
2656  add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
2657  HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
2658  }
2659  break;
2660  }
2661  }
2662  if (smd->is_last)
2663  break;
2664  smd++;
2665  } while (1);
2666  }
2667 }
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:807
DetectEngineCtx_::pkt_mpms_list_cnt
uint32_t pkt_mpms_list_cnt
Definition: detect.h:1077
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:56
DetectEngineCtx_::frame_mpms_list_cnt
uint32_t frame_mpms_list_cnt
Definition: detect.h:1080
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:107
SignatureInitData_::max_content_list_id
uint32_t max_content_list_id
Definition: detect.h:642
PrefilterGenericMpmPktRegister
int PrefilterGenericMpmPktRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:1727
DetectAppLayerMpmMultiRegister
void DetectAppLayerMpmMultiRegister(const char *name, int direction, int priority, PrefilterRegisterFunc PrefilterRegister, InspectionMultiBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
Definition: detect-engine-mpm.c:170
DetectPatternTracker
Definition: detect.h:797
SCFPSupportSMList_
Definition: detect.h:828
DetectEngineAppInspectionEngine_
Definition: detect.h:417
util-hash-string.h
MPMB_UDP_TS
@ MPMB_UDP_TS
Definition: detect.h:1462
SignatureInitDataBuffer_::head
SigMatch * head
Definition: detect.h:535
detect-content.h
SGH_DIRECTION_TC
#define SGH_DIRECTION_TC(sgh)
Definition: detect-engine-mpm.c:1009
MpmCtx_::mpm_type
uint8_t mpm_type
Definition: util-mpm.h:95
detect-engine.h
DETECT_SM_LIST_PMATCH
@ DETECT_SM_LIST_PMATCH
Definition: detect.h:119
DetectBufferMpmRegistry_::direction
int direction
Definition: detect.h:754
DETECT_CONTENT_FAST_PATTERN_CHOP
#define DETECT_CONTENT_FAST_PATTERN_CHOP
Definition: detect-content.h:36
SignatureInitData_::smlists
struct SigMatch_ * smlists[DETECT_SM_LIST_MAX]
Definition: detect.h:631
PatternMatchDestroy
void PatternMatchDestroy(MpmCtx *mpm_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:911
MpmStore_::sid_array_size
uint32_t sid_array_size
Definition: detect.h:1470
DetectContentData_::fp_chop_len
uint16_t fp_chop_len
Definition: detect-content.h:98
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
MpmStore_::sid_array
uint8_t * sid_array
Definition: detect.h:1469
DetectEngineCtx_::sgh_mpm_context_proto_tcp_packet
int32_t sgh_mpm_context_proto_tcp_packet
Definition: detect.h:991
PatternMatchPrepareGroup
int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
Prepare the pattern matcher ctx in a sig group head.
Definition: detect-engine-mpm.c:2273
SCFPSupportSMList_::next
struct SCFPSupportSMList_ * next
Definition: detect.h:831
DetectEnginePktInspectionEngine
Definition: detect.h:484
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:47
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:442
detect-engine-siggroup.h
SigGroupHead_::flags
uint16_t flags
Definition: detect.h:1590
SCFPSupportSMList_::list_id
int list_id
Definition: detect.h:829
SigTableElmt_::name
const char * name
Definition: detect.h:1419
MpmStoreFree
void MpmStoreFree(DetectEngineCtx *de_ctx)
Frees the hash table - DetectEngineCtx->mpm_hash_table, allocated by MpmStoreInit() function.
Definition: detect-engine-mpm.c:1573
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:370
MpmThreadCtx_
Definition: util-mpm.h:46
DetectPatternTracker::mpm
uint32_t mpm
Definition: detect.h:801
DETECT_ABSENT
@ DETECT_ABSENT
Definition: detect-engine-register.h:95
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1589
DetectEngineCtx_::pattern_hash_table
HashListTable * pattern_hash_table
Definition: detect.h:952
DetectEngineTransforms
Definition: detect.h:392
DetectBufferMpmRegistry_::sm_list_base
int16_t sm_list_base
Definition: detect.h:756
MpmFactoryReClaimMpmCtx
void MpmFactoryReClaimMpmCtx(const DetectEngineCtx *de_ctx, MpmCtx *mpm_ctx)
Definition: util-mpm.c:156
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:69
MpmStoreReportStats
void MpmStoreReportStats(const DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:1476
Signature_::alproto
AppProto alproto
Definition: detect.h:662
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:270
MPMB_OTHERIP
@ MPMB_OTHERIP
Definition: detect.h:1464
DetectPktMpmRegister
void DetectPktMpmRegister(const char *name, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id), InspectionBufferGetPktDataPtr GetData)
register a MPM engine
Definition: detect-engine-mpm.c:552
SigMatchData_::is_last
bool is_last
Definition: detect.h:368
DetectBufferTypeSupportsFrames
void DetectBufferTypeSupportsFrames(const char *name)
Definition: detect-engine.c:1216
DetectBufferMpmRegistry_::frame_v1
struct DetectBufferMpmRegistry_::@88::@92 frame_v1
DetectMpmInitializeFrameMpms
void DetectMpmInitializeFrameMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:472
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:86
DETECT_SM_LIST_DYNAMIC_START
@ DETECT_SM_LIST_DYNAMIC_START
Definition: detect.h:138
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:369
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:1474
PatternStrength
uint32_t PatternStrength(uint8_t *pat, uint16_t patlen)
Predict a strength value for patterns.
Definition: detect-engine-mpm.c:941
DetectEngineCtx_::pkt_mpms_list
DetectBufferMpmRegistry * pkt_mpms_list
Definition: detect.h:1076
DETECT_BUFFER_MPM_TYPE_FRAME
@ DETECT_BUFFER_MPM_TYPE_FRAME
Definition: detect.h:745
DetectSetFastPatternAndItsId
int DetectSetFastPatternAndItsId(DetectEngineCtx *de_ctx)
Figure out the FP and their respective content ids for all the sigs in the engine.
Definition: detect-engine-mpm.c:2464
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:40
ctx
struct Thresholds ctx
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:919
DetectEnginePktInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:485
SCConfGet
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:350
util-memcpy.h
DETECT_CONTENT_MPM_IS_CONCLUSIVE
#define DETECT_CONTENT_MPM_IS_CONCLUSIVE(c)
Definition: detect-content.h:78
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:287
DETECT_CONTENT_DEPTH_VAR
#define DETECT_CONTENT_DEPTH_VAR
Definition: detect-content.h:46
DetectEngineCtx_::mpm_cfg
MpmConfig * mpm_cfg
Definition: detect.h:923
InspectionBufferGetPktDataPtr
InspectionBuffer *(* InspectionBufferGetPktDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Packet *p, const int list_id)
Definition: detect.h:479
DetectEngineBufferTypeGetNameById
const char * DetectEngineBufferTypeGetNameById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1286
DetectMpmInitializeBuiltinMpms
void DetectMpmInitializeBuiltinMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:737
DetectBufferMpmRegistry_::next
struct DetectBufferMpmRegistry_ * next
Definition: detect.h:793
SIG_FLAG_REQUIRE_STREAM
#define SIG_FLAG_REQUIRE_STREAM
Definition: detect.h:255
DetectPatternTracker::cnt
uint32_t cnt
Definition: detect.h:800
SIG_FLAG_TXBOTHDIR
#define SIG_FLAG_TXBOTHDIR
Definition: detect.h:250
SCConfGetBool
int SCConfGetBool(const char *name, int *val)
Retrieve a configuration value as a boolean.
Definition: conf.c:497
DetectBufferMpmRegistry_
one time registration of keywords at start up
Definition: detect.h:751
DE_QUIET
#define DE_QUIET
Definition: detect.h:330
MpmCtx_::maxlen
uint16_t maxlen
Definition: util-mpm.h:105
MPMB_TCP_STREAM_TS
@ MPMB_TCP_STREAM_TS
Definition: detect.h:1460
DetectPatternTracker::cd
const struct DetectContentData_ * cd
Definition: detect.h:798
PatIntId
#define PatIntId
Definition: suricata-common.h:335
SIG_GROUP_HEAD_HAVERAWSTREAM
#define SIG_GROUP_HEAD_HAVERAWSTREAM
Definition: detect.h:1448
MpmTableElmt_::feature_flags
uint8_t feature_flags
Definition: util-mpm.h:183
mpm_default_matcher
uint8_t mpm_default_matcher
Definition: util-mpm.c:48
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:720
DetectBufferMpmRegistry_::app_v2
struct DetectBufferMpmRegistry_::@88::@90 app_v2
DetectContentData_
Definition: detect-content.h:93
DetectContentData_::fp_chop_offset
uint16_t fp_chop_offset
Definition: detect-content.h:100
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:245
detect-engine-payload.h
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:272
MAX
#define MAX(x, y)
Definition: suricata-common.h:412
MPMB_MAX
@ MPMB_MAX
Definition: detect.h:1465
SigMatchData_
Data needed for Match()
Definition: detect.h:366
DetectEngineCtx_::sgh_mpm_context_proto_udp_packet
int32_t sgh_mpm_context_proto_udp_packet
Definition: detect.h:992
DetectBufferMpmRegistry_::transforms
DetectEngineTransforms transforms
Definition: detect.h:764
ShortenString
void ShortenString(const char *input, char *output, size_t output_size, char c)
Definition: util-misc.c:207
SigMatchData_::type
uint16_t type
Definition: detect.h:367
DetectEngineRegisterFastPatternForId
void DetectEngineRegisterFastPatternForId(DetectEngineCtx *de_ctx, int list_id, int priority)
Definition: detect-fast-pattern.c:134
SidsArray
Definition: detect-engine-mpm.c:1814
MPMB_TCP_STREAM_TC
@ MPMB_TCP_STREAM_TC
Definition: detect.h:1461
detect-engine-prefilter.h
EngineAnalysisAddAllRulePatterns
void EngineAnalysisAddAllRulePatterns(DetectEngineCtx *de_ctx, const Signature *s)
add all patterns on our stats hash Used to fill the hash later used by DumpPatterns()
Definition: detect-engine-mpm.c:2521
Signature_::frame_inspect
DetectEngineFrameInspectionEngine * frame_inspect
Definition: detect.h:716
MpmBuiltinBuffers
MpmBuiltinBuffers
Definition: detect.h:1457
MpmConfig_::cache_dir_path
const char * cache_dir_path
Definition: util-mpm.h:90
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1256
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:114
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:179
util-memcmp.h
SigGroupHeadInitData_::pkt_mpms
MpmCtx ** pkt_mpms
Definition: detect.h:1572
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint8_t matcher)
Definition: util-mpm.c:209
Signature_::next
struct Signature_ * next
Definition: detect.h:739
DetectEngineCtx_::sgh_mpm_context_proto_other_packet
int32_t sgh_mpm_context_proto_other_packet
Definition: detect.h:993
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:425
DetectBufferInstance::alproto
AppProto alproto
Definition: detect-engine-mpm.c:1981
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:55
DetectBufferMpmType
DetectBufferMpmType
Definition: detect.h:742
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:271
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
MpmDestroyThreadCtx
void MpmDestroyThreadCtx(MpmThreadCtx *mpm_thread_ctx, const uint16_t matcher)
Definition: util-mpm.c:202
util-debug.h
DetectBufferInstance::ts
struct SidsArray ts
Definition: detect-engine-mpm.c:1983
SigGroupHeadInitData_::sig_cnt
SigIntId sig_cnt
Definition: detect.h:1582
SidsArray::sids_array_size
uint32_t sids_array_size
Definition: detect-engine-mpm.c:1816
DETECT_CONTENT_ENDS_WITH
#define DETECT_CONTENT_ENDS_WITH
Definition: detect-content.h:42
DetectBufferMpmRegistry_::sgh_mpm_context
int sgh_mpm_context
Definition: detect.h:760
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:18
MpmFactoryGetMpmCtxForProfile
MpmCtx * MpmFactoryGetMpmCtxForProfile(const DetectEngineCtx *de_ctx, int32_t id, int direction)
Definition: util-mpm.c:131
DetectEnginePktInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:487
g_alproto_max
AppProto g_alproto_max
Definition: app-layer-protos.c:29
DetectMpmInitializePktMpms
void DetectMpmInitializePktMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:639
MPM_PATTERN_CTX_OWNS_ID
#define MPM_PATTERN_CTX_OWNS_ID
Definition: util-mpm.h:143
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
MpmStore_
Definition: detect.h:1468
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:612
DetectBufferMpmRegistry_::sm_list
int16_t sm_list
Definition: detect.h:755
DetectEngineGetMaxSigId
#define DetectEngineGetMaxSigId(de_ctx)
Definition: detect-engine.h:90
SignatureInitData_::mpm_sm_list
int mpm_sm_list
Definition: detect.h:610
SidsArray::sids_array
uint8_t * sids_array
Definition: detect-engine-mpm.c:1815
DETECT_CONTENT_DEPTH
#define DETECT_CONTENT_DEPTH
Definition: detect-content.h:33
Signature_::pkt_inspect
DetectEnginePktInspectionEngine * pkt_inspect
Definition: detect.h:715
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:272
detect-engine-mpm.h
detect.h
DetectEngineFrameInspectionEngine::sm_list
uint16_t sm_list
Definition: detect.h:514
InspectionSingleBufferGetDataPtr
bool(* InspectionSingleBufferGetDataPtr)(const void *txv, const uint8_t flow_flags, const uint8_t **buf, uint32_t *buf_len)
Definition: detect-engine-helper.h:45
SigMatch_::next
struct SigMatch_ * next
Definition: detect.h:361
DetectEngineCtx_::mpm_matcher
uint8_t mpm_matcher
Definition: detect.h:922
DETECT_CONTENT_IS_SINGLE
#define DETECT_CONTENT_IS_SINGLE(c)
Definition: detect-content.h:68
DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_NEGATED
Definition: detect-content.h:40
PrefilterGenericMpmRegister
int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:1584
DetectBufferMpmRegistry_::priority
int priority
Definition: detect.h:757
PatternMatchThreadPrepare
void PatternMatchThreadPrepare(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:922
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:250
DetectEngineBufferTypeRegister
int DetectEngineBufferTypeRegister(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1343
SigGroupHead_::init
SigGroupHeadInitData * init
Definition: detect.h:1606
DetectBufferMpmRegistry_::pkt_v1
struct DetectBufferMpmRegistry_::@88::@91 pkt_v1
DetectContentData_::id
PatIntId id
Definition: detect-content.h:105
DetectAppLayerMpmRegister
void DetectAppLayerMpmRegister(const char *name, int direction, int priority, PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
register an app layer keyword for mpm
Definition: detect-engine-mpm.c:154
Signature_::app_inspect
DetectEngineAppInspectionEngine * app_inspect
Definition: detect.h:714
MpmCtx_::minlen
uint16_t minlen
Definition: util-mpm.h:104
SigMatch_::ctx
SigMatchCtx * ctx
Definition: detect.h:360
DetectProto_::proto
uint8_t proto[256/8]
Definition: detect-engine-proto.h:36
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
MpmStore_::direction
int direction
Definition: detect.h:1472
DetectBufferToClient
bool DetectBufferToClient(const DetectEngineCtx *de_ctx, int buf_id, AppProto alproto)
Definition: detect-engine-mpm.c:1078
MPMCTX_FLAGS_GLOBAL
#define MPMCTX_FLAGS_GLOBAL
Definition: util-mpm.h:85
PrefilterRegisterFunc
int(* PrefilterRegisterFunc)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-mpm.h:72
Signature_::flags
uint32_t flags
Definition: detect.h:658
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:106
stream.h
MpmFactoryRegisterMpmCtxProfile
int32_t MpmFactoryRegisterMpmCtxProfile(DetectEngineCtx *de_ctx, const char *name, const int sm_list, const AppProto alproto)
Register a new Mpm Context.
Definition: util-mpm.c:59
ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE
@ ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE
Definition: detect.h:1161
DetectEngineCtx_::sgh_mpm_context_stream
int32_t sgh_mpm_context_stream
Definition: detect.h:994
type
uint16_t type
Definition: decode-vlan.c:106
DetectEngineBufferTypeSupportsFrames
void DetectEngineBufferTypeSupportsFrames(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1382
DetectEngineCtx_::frame_mpms_list
DetectBufferMpmRegistry * frame_mpms_list
Definition: detect.h:1079
conf.h
DetectEngineCtx_::sgh_mpm_ctx_cnf
uint8_t sgh_mpm_ctx_cnf
Definition: detect.h:1020
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:104
PrefilterPktPayloadRegister
int PrefilterPktPayloadRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx)
Definition: detect-engine-payload.c:132
MpmStore_::alproto
AppProto alproto
Definition: detect.h:1476
DetectEngineFrameInspectionEngine
Definition: detect.h:509
DETECT_BUFFER_MPM_TYPE_PKT
@ DETECT_BUFFER_MPM_TYPE_PKT
Definition: detect.h:743
ALPROTO_DOH2
@ ALPROTO_DOH2
Definition: app-layer-protos.h:66
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:736
name
const char * name
Definition: tm-threads.c:2123
FastPatternSupportEnabledForSigMatchList
int FastPatternSupportEnabledForSigMatchList(const DetectEngineCtx *de_ctx, const int list_id)
Checks if a particular buffer is in the list of lists that need to be searched for a keyword that has...
Definition: detect-fast-pattern.c:64
SCFPSupportSMList_::priority
int priority
Definition: detect.h:830
HashListTable_
Definition: util-hashlist.h:37
DetectEngineTransforms::transforms
TransformData transforms[DETECT_TRANSFORMS_MAX]
Definition: detect.h:393
ALPROTO_HTTP2
@ ALPROTO_HTTP2
Definition: app-layer-protos.h:69
SidsArray::type
enum DetectBufferMpmType type
Definition: detect-engine-mpm.c:1820
SigGroupHeadInitData_::app_mpms
MpmCtx ** app_mpms
Definition: detect.h:1571
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:249
DetectEngineBufferTypeSupportsTransformations
void DetectEngineBufferTypeSupportsTransformations(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1406
InspectionMultiBufferGetDataPtr
bool(* InspectionMultiBufferGetDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const void *txv, const uint8_t flow_flags, uint32_t local_id, const uint8_t **buf, uint32_t *buf_len)
Definition: detect-engine-helper.h:42
SGH_DIRECTION_TS
#define SGH_DIRECTION_TS(sgh)
Definition: detect-engine-mpm.c:1008
DetectEngineAppInspectionEngine_::alproto
AppProto alproto
Definition: detect.h:418
DetectPatternTracker::sm_list
int sm_list
Definition: detect.h:799
DetectEngineAppInspectionEngine_::smd
SigMatchData * smd
Definition: detect.h:440
DetectBufferInstance
Definition: detect-engine-mpm.c:1978
MpmStore_::mpm_ctx
MpmCtx * mpm_ctx
Definition: detect.h:1477
MPM_FEATURE_FLAG_ENDSWITH
#define MPM_FEATURE_FLAG_ENDSWITH
Definition: util-mpm.h:148
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:1681
MPMB_TCP_PKT_TC
@ MPMB_TCP_PKT_TC
Definition: detect.h:1459
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
DetectMpmPrepareFrameMpms
int DetectMpmPrepareFrameMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for applayer buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:524
DetectEngineFrameMpmRegister
void DetectEngineFrameMpmRegister(DetectEngineCtx *de_ctx, const char *name, int direction, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id), AppProto alproto, uint8_t type)
Definition: detect-engine-mpm.c:409
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:837
util-mpm.h
flags
uint8_t flags
Definition: decode-gre.h:0
Signature_::proto
DetectProto proto
Definition: detect.h:676
DetectBufferMpmRegistry_::type
enum DetectBufferMpmType type
Definition: detect.h:759
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:1410
DetectAppLayerMpmRegisterSingle
void DetectAppLayerMpmRegisterSingle(const char *name, int direction, int priority, PrefilterRegisterFunc PrefilterRegister, InspectionSingleBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
Definition: detect-engine-mpm.c:162
DetectEngineCtx_::app_mpms_list
DetectBufferMpmRegistry * app_mpms_list
Definition: detect.h:1071
suricata-common.h
MpmCtx_::pattern_cnt
uint32_t pattern_cnt
Definition: util-mpm.h:102
DETECT_BUFFER_MPM_TYPE_APP
@ DETECT_BUFFER_MPM_TYPE_APP
Definition: detect.h:744
DetectBufferTypeSupportsMpm
void DetectBufferTypeSupportsMpm(const char *name)
Definition: detect-engine.c:1236
DetectBufferInstance::list
int list
Definition: detect-engine-mpm.c:1980
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:88
SigGroupHeadInitData_::match_array
Signature ** match_array
Definition: detect.h:1585
DetectBufferMpmRegistry_::name
const char * name
Definition: detect.h:752
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:129
DetectEngineFrameInspectionEngine::next
struct DetectEngineFrameInspectionEngine * next
Definition: detect.h:522
SCLogPerf
#define SCLogPerf(...)
Definition: util-debug.h:231
DetectEnginePktInspectionEngine::next
struct DetectEnginePktInspectionEngine * next
Definition: detect.h:495
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:94
PatternMatchDefaultMatcher
uint8_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:865
FatalError
#define FatalError(...)
Definition: util-debug.h:503
DetectEngineCtx_::sig_list
Signature * sig_list
Definition: detect.h:928
DetectMpmPreparePktMpms
int DetectMpmPreparePktMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for applayer buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:691
TransformData_::transform
int transform
Definition: detect.h:388
DetectEngineBufferTypeSupportsMpm
void DetectEngineBufferTypeSupportsMpm(DetectEngineCtx *de_ctx, const char *name)
Definition: detect-engine.c:1398
util-validate.h
detect-flow.h
DetectEngineCtx_::app_mpms_list_cnt
uint32_t app_mpms_list_cnt
Definition: detect.h:1070
DetectBufferTypeSupportsTransformations
void DetectBufferTypeSupportsTransformations(const char *name)
Definition: detect-engine.c:1246
MPM_PATTERN_FLAG_ENDSWITH
#define MPM_PATTERN_FLAG_ENDSWITH
Definition: util-mpm.h:144
builtin_mpms
const char * builtin_mpms[]
Definition: detect-engine-mpm.c:66
SignatureInitData_::buffers
SignatureInitDataBuffer * buffers
Definition: detect.h:636
DetectEngineCtx_::app_inspect_engines
DetectEngineAppInspectionEngine * app_inspect_engines
Definition: detect.h:1074
MPM_TABLE_SIZE
@ MPM_TABLE_SIZE
Definition: util-mpm.h:40
g_skip_prefilter
int g_skip_prefilter
Definition: detect-engine-mpm.c:1075
DetectEngineCtx_::mpm_hash_table
HashListTable * mpm_hash_table
Definition: detect.h:951
MpmTableElmt_::Prepare
int(* Prepare)(MpmConfig *, struct MpmCtx_ *)
Definition: util-mpm.h:174
MPMB_UDP_TC
@ MPMB_UDP_TC
Definition: detect.h:1463
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:154
Signature_::iid
SigIntId iid
Definition: detect.h:669
DetectBufferMpmRegistry_::id
int id
Definition: detect.h:758
SigMatchListSMBelongsTo
int SigMatchListSMBelongsTo(const Signature *s, const SigMatch *key_sm)
Definition: detect-parse.c:763
SCFree
#define SCFree(p)
Definition: util-mem.h:61
MPM_CTX_FACTORY_UNIQUE_CONTEXT
#define MPM_CTX_FACTORY_UNIQUE_CONTEXT
Definition: util-mpm.h:118
DetectMpmPrepareBuiltinMpms
int DetectMpmPrepareBuiltinMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for builtin buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:750
Signature_::id
uint32_t id
Definition: detect.h:702
DETECT_CONTENT_OFFSET
#define DETECT_CONTENT_OFFSET
Definition: detect-content.h:32
HashListTableBucket_
Definition: util-hashlist.h:28
DetectBufferMpmRegistry_::PrefilterRegisterWithListId
int(* PrefilterRegisterWithListId)(struct DetectEngineCtx_ *de_ctx, struct SigGroupHead_ *sgh, MpmCtx *mpm_ctx, const struct DetectBufferMpmRegistry_ *mpm_reg, int list_id)
Definition: detect.h:762
detect-tcphdr.h
DETECT_CONTENT_MPM
#define DETECT_CONTENT_MPM
Definition: detect-content.h:61
detect-engine-iponly.h
detect-parse.h
SignatureInitDataBuffer_::id
uint32_t id
Definition: detect.h:526
Signature_
Signature container.
Definition: detect.h:657
SigMatch_
a single match condition for a signature
Definition: detect.h:357
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
MPMB_TCP_PKT_TS
@ MPMB_TCP_PKT_TS
Definition: detect.h:1458
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:47
app-layer-protos.h
DetectMpmInitializeAppMpms
void DetectMpmInitializeAppMpms(DetectEngineCtx *de_ctx)
Definition: detect-engine-mpm.c:247
DetectEngineTransforms::cnt
int cnt
Definition: detect.h:394
suricata.h
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:937
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-engine-helper.h:39
DetectEngineAppInspectionEngine_::dir
uint8_t dir
Definition: detect.h:419
DETECT_BUFFER_MPM_TYPE_SIZE
@ DETECT_BUFFER_MPM_TYPE_SIZE
Definition: detect.h:747
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:95
DetectBufferInstance::tc
struct SidsArray tc
Definition: detect-engine-mpm.c:1984
SignatureInitDataBuffer_::only_tc
bool only_tc
Definition: detect.h:532
DetectEngineCtx_::buffer_type_id
uint32_t buffer_type_id
Definition: detect.h:1068
id
uint32_t id
Definition: detect-flowbits.c:933
DetectEngineCtx_::flags
uint8_t flags
Definition: detect.h:921
MpmCtx_
Definition: util-mpm.h:93
SGH_PROTO
#define SGH_PROTO(sgh, p)
Definition: detect-engine-mpm.c:1007
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:97
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:601
DETECT_CONTENT_FAST_PATTERN
#define DETECT_CONTENT_FAST_PATTERN
Definition: detect-content.h:34
MPMCTX_FLAGS_CACHE_TO_DISK
#define MPMCTX_FLAGS_CACHE_TO_DISK
Definition: util-mpm.h:87
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DetectFrameMpmRegister
void DetectFrameMpmRegister(const char *name, int direction, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id), AppProto alproto, uint8_t type)
register a MPM engine
Definition: detect-engine-mpm.c:322
util-enum.h
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:276
DetectBufferInstance
struct DetectBufferInstance DetectBufferInstance
SidsArray::active
bool active
Definition: detect-engine-mpm.c:1818
SignatureInitData_::buffer_index
uint32_t buffer_index
Definition: detect.h:637
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:258
flow-var.h
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:290
DetectMpmPrepareAppMpms
int DetectMpmPrepareAppMpms(DetectEngineCtx *de_ctx)
initialize mpm contexts for applayer buffers that are in "single or "shared" mode.
Definition: detect-engine-mpm.c:297
DetectEngineCtx_::fp_support_smlist_list
SCFPSupportSMList * fp_support_smlist_list
Definition: detect.h:1093
MpmStore_::sgh_mpm_context
int32_t sgh_mpm_context
Definition: detect.h:1475
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
PatternMatchThreadDestroy
void PatternMatchThreadDestroy(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
Definition: detect-engine-mpm.c:917
MpmStore_::buffer
enum MpmBuiltinBuffers buffer
Definition: detect.h:1473
RetrieveFPForSig
void RetrieveFPForSig(const DetectEngineCtx *de_ctx, Signature *s)
Definition: detect-engine-mpm.c:1097
StringHashDjb2
uint32_t StringHashDjb2(const uint8_t *data, uint32_t datalen)
Definition: util-hash-string.c:22
PrefilterPktStreamRegister
int PrefilterPktStreamRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx)
Definition: detect-engine-payload.c:109
DETECT_CONTENT_OFFSET_VAR
#define DETECT_CONTENT_OFFSET_VAR
Definition: detect-content.h:45
SigGroupHeadInitData_::frame_mpms
MpmCtx ** frame_mpms
Definition: detect.h:1573
DetectBufferMpmRegistry_::pname
char pname[32]
Definition: detect.h:753
SIG_FLAG_REQUIRE_PACKET
#define SIG_FLAG_REQUIRE_PACKET
Definition: detect.h:254
DetectEngineFrameInspectionEngine::smd
SigMatchData * smd
Definition: detect.h:521