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