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