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