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