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