suricata
detect-engine-prefilter.c
Go to the documentation of this file.
1 /* Copyright (C) 2016-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  *
23  * Prefilter engine
24  *
25  * Prefilter engines have as purpose to check for a critical common part of
26  * a set of rules. If the condition is present in the traffic, the rules
27  * will have to be inspected individually. Otherwise, the rules can be
28  * skipped.
29  *
30  * The best example of this is the MPM. From each rule take a pattern and
31  * add it to the MPM state machine. Inspect that in one step and only
32  * individually inspect the rules that had a match in MPM.
33  *
34  * This prefilter API is designed to abstract this logic so that it becomes
35  * easier to add other types of prefilters.
36  *
37  * The prefilter engines are structured as a simple list of engines. Each
38  * engine checks for a condition using it's callback function and private
39  * data. It then adds the rule match candidates to the PrefilterRuleStore
40  * structure.
41  *
42  * After the engines have run the resulting list of match candidates is
43  * sorted by the rule id's so that the individual inspection happens in
44  * the correct order.
45  */
46 
47 #include "suricata-common.h"
48 #include "suricata.h"
49 
50 #include "detect-engine.h"
52 #include "detect-engine-mpm.h"
53 #include "detect-engine-frame.h"
54 
55 #include "app-layer-parser.h"
56 #include "app-layer-htp.h"
57 
58 #include "util-profiling.h"
59 #include "util-validate.h"
60 
61 static int PrefilterStoreGetId(DetectEngineCtx *de_ctx,
62  const char *name, void (*FreeFunc)(void *));
63 static const PrefilterStore *PrefilterStoreGetStore(const DetectEngineCtx *de_ctx,
64  const uint32_t id);
65 
66 static inline void QuickSortSigIntId(SigIntId *sids, uint32_t n)
67 {
68  if (n < 2)
69  return;
70  SigIntId p = sids[n / 2];
71  SigIntId *l = sids;
72  SigIntId *r = sids + n - 1;
73  while (l <= r) {
74  if (*l < p)
75  l++;
76  else if (*r > p)
77  r--;
78  else {
79  SigIntId t = *l;
80  *l = *r;
81  *r = t;
82  l++;
83  r--;
84  }
85  }
86  QuickSortSigIntId(sids, r - sids + 1);
87  QuickSortSigIntId(l, sids + n - l);
88 }
89 
90 /**
91  * \brief run prefilter engines on a transaction
92  */
94  const SigGroupHead *sgh,
95  Packet *p,
96  const uint8_t ipproto,
97  const uint8_t flow_flags,
98  const AppProto alproto,
99  void *alstate,
100  DetectTransaction *tx)
101 {
102  /* reset rule store */
103  det_ctx->pmq.rule_id_array_cnt = 0;
104 
105  SCLogDebug("packet %" PRIu64 " tx %p progress %d tx->prefilter_flags %" PRIx64, p->pcap_cnt,
106  tx->tx_ptr, tx->tx_progress, tx->prefilter_flags);
107 
108  PrefilterEngine *engine = sgh->tx_engines;
109  do {
110  if (engine->alproto != alproto)
111  goto next;
112  if (engine->ctx.tx_min_progress > tx->tx_progress)
113  break;
114  if (tx->tx_progress > engine->ctx.tx_min_progress) {
115  if (tx->prefilter_flags & BIT_U64(engine->ctx.tx_min_progress)) {
116  goto next;
117  }
118  }
119 
120  PREFILTER_PROFILING_START(det_ctx);
121  engine->cb.PrefilterTx(det_ctx, engine->pectx, p, p->flow, tx->tx_ptr, tx->tx_id,
122  tx->tx_data_ptr, flow_flags);
123  PREFILTER_PROFILING_END(det_ctx, engine->gid);
124 
125  if (tx->tx_progress > engine->ctx.tx_min_progress && engine->is_last_for_progress) {
126  tx->prefilter_flags |= BIT_U64(engine->ctx.tx_min_progress);
127  }
128  next:
129  if (engine->is_last)
130  break;
131  engine++;
132  } while (1);
133 
134  /* Sort the rule list to lets look at pmq.
135  * NOTE due to merging of 'stream' pmqs we *MAY* have duplicate entries */
136  if (likely(det_ctx->pmq.rule_id_array_cnt > 1)) {
138  QuickSortSigIntId(det_ctx->pmq.rule_id_array, det_ctx->pmq.rule_id_array_cnt);
140  }
141 }
142 
143 void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh,
144  Packet *p, const uint8_t flags)
145 {
146  SCEnter();
147 #if 0
148  /* TODO review this check */
149  SCLogDebug("sgh %p frame_engines %p", sgh, sgh->frame_engines);
150  if (p->proto == IPPROTO_TCP && sgh->frame_engines && p->flow &&
151  p->flow->alproto != ALPROTO_UNKNOWN && p->flow->alparser != NULL) {
153  PrefilterFrames(det_ctx, sgh, p, flags, p->flow->alproto);
155  }
156 #endif
157  if (sgh->pkt_engines) {
159  /* run packet engines */
160  PrefilterEngine *engine = sgh->pkt_engines;
161  do {
162  PREFILTER_PROFILING_START(det_ctx);
163  engine->cb.Prefilter(det_ctx, p, engine->pectx);
164  PREFILTER_PROFILING_END(det_ctx, engine->gid);
165 
166  if (engine->is_last)
167  break;
168  engine++;
169  } while (1);
171  }
172 
173  /* run payload inspecting engines */
174  if (sgh->payload_engines &&
177  {
179  PrefilterEngine *engine = sgh->payload_engines;
180  while (1) {
181  PREFILTER_PROFILING_START(det_ctx);
182  engine->cb.Prefilter(det_ctx, p, engine->pectx);
183  PREFILTER_PROFILING_END(det_ctx, engine->gid);
184 
185  if (engine->is_last)
186  break;
187  engine++;
188  }
190  }
191 
192  /* Sort the rule list to lets look at pmq.
193  * NOTE due to merging of 'stream' pmqs we *MAY* have duplicate entries */
194  if (likely(det_ctx->pmq.rule_id_array_cnt > 1)) {
196  QuickSortSigIntId(det_ctx->pmq.rule_id_array, det_ctx->pmq.rule_id_array_cnt);
198  }
199  SCReturn;
200 }
201 
203  void (*PrefilterFunc)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx),
204  void *pectx, void (*FreeFunc)(void *pectx),
205  const char *name)
206 {
207  if (sgh == NULL || PrefilterFunc == NULL || pectx == NULL)
208  return -1;
209 
210  PrefilterEngineList *e = SCMallocAligned(sizeof(*e), CLS);
211  if (e == NULL)
212  return -1;
213  memset(e, 0x00, sizeof(*e));
214 
215  e->Prefilter = PrefilterFunc;
216  e->pectx = pectx;
217  e->Free = FreeFunc;
218 
219  if (sgh->init->pkt_engines == NULL) {
220  sgh->init->pkt_engines = e;
221  } else {
223  while (t->next != NULL) {
224  t = t->next;
225  }
226 
227  t->next = e;
228  e->id = t->id + 1;
229  }
230 
231  e->name = name;
232  e->gid = PrefilterStoreGetId(de_ctx, e->name, e->Free);
233  return 0;
234 }
235 
237  void (*PrefilterFunc)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx),
238  void *pectx, void (*FreeFunc)(void *pectx),
239  const char *name)
240 {
241  if (sgh == NULL || PrefilterFunc == NULL || pectx == NULL)
242  return -1;
243 
244  PrefilterEngineList *e = SCMallocAligned(sizeof(*e), CLS);
245  if (e == NULL)
246  return -1;
247  memset(e, 0x00, sizeof(*e));
248 
249  e->Prefilter = PrefilterFunc;
250  e->pectx = pectx;
251  e->Free = FreeFunc;
252 
253  if (sgh->init->payload_engines == NULL) {
254  sgh->init->payload_engines = e;
255  } else {
257  while (t->next != NULL) {
258  t = t->next;
259  }
260 
261  t->next = e;
262  e->id = t->id + 1;
263  }
264 
265  e->name = name;
266  e->gid = PrefilterStoreGetId(de_ctx, e->name, e->Free);
267  return 0;
268 }
269 
271  PrefilterTxFn PrefilterTxFunc, AppProto alproto, int tx_min_progress, void *pectx,
272  void (*FreeFunc)(void *pectx), const char *name)
273 {
274  if (sgh == NULL || PrefilterTxFunc == NULL || pectx == NULL)
275  return -1;
276 
277  PrefilterEngineList *e = SCMallocAligned(sizeof(*e), CLS);
278  if (e == NULL)
279  return -1;
280  memset(e, 0x00, sizeof(*e));
281 
282  e->PrefilterTx = PrefilterTxFunc;
283  e->pectx = pectx;
284  e->alproto = alproto;
285  // TODO change function prototype ?
286  DEBUG_VALIDATE_BUG_ON(tx_min_progress > UINT8_MAX);
287  e->tx_min_progress = (uint8_t)tx_min_progress;
288  e->Free = FreeFunc;
289 
290  if (sgh->init->tx_engines == NULL) {
291  sgh->init->tx_engines = e;
292  } else {
294  while (t->next != NULL) {
295  t = t->next;
296  }
297 
298  t->next = e;
299  e->id = t->id + 1;
300  }
301 
302  e->name = name;
303  e->gid = PrefilterStoreGetId(de_ctx, e->name, e->Free);
304  return 0;
305 }
306 
308  PrefilterFrameFn PrefilterFrameFunc, AppProto alproto, uint8_t frame_type, void *pectx,
309  void (*FreeFunc)(void *pectx), const char *name)
310 {
311  if (sgh == NULL || PrefilterFrameFunc == NULL || pectx == NULL)
312  return -1;
313 
314  PrefilterEngineList *e = SCMallocAligned(sizeof(*e), CLS);
315  if (e == NULL)
316  return -1;
317  memset(e, 0x00, sizeof(*e));
318 
319  e->frame_type = frame_type;
320  e->alproto = alproto;
321  e->PrefilterFrame = PrefilterFrameFunc;
322  e->pectx = pectx;
323  e->Free = FreeFunc;
324 
325  if (sgh->init->frame_engines == NULL) {
326  sgh->init->frame_engines = e;
327  } else {
329  while (t->next != NULL) {
330  t = t->next;
331  }
332 
333  t->next = e;
334  e->id = t->id + 1;
335  }
336 
337  e->name = name;
338  e->gid = PrefilterStoreGetId(de_ctx, e->name, e->Free);
339  return 0;
340 }
341 
342 static void PrefilterFreeEngineList(PrefilterEngineList *e)
343 {
344  if (e->Free && e->pectx) {
345  e->Free(e->pectx);
346  }
347  SCFreeAligned(e);
348 }
349 
351 {
352  PrefilterEngineList *t = list;
353 
354  while (t != NULL) {
356  PrefilterFreeEngineList(t);
357  t = next;
358  }
359 }
360 
361 static void PrefilterFreeEngines(const DetectEngineCtx *de_ctx, PrefilterEngine *list)
362 {
363  PrefilterEngine *t = list;
364 
365  while (1) {
366  const PrefilterStore *s = PrefilterStoreGetStore(de_ctx, t->gid);
367  if (s && s->FreeFunc && t->pectx) {
368  s->FreeFunc(t->pectx);
369  }
370 
371  if (t->is_last)
372  break;
373  t++;
374  }
375  SCFreeAligned(list);
376 }
377 
379 {
380  if (sgh->pkt_engines) {
381  PrefilterFreeEngines(de_ctx, sgh->pkt_engines);
382  sgh->pkt_engines = NULL;
383  }
384  if (sgh->payload_engines) {
385  PrefilterFreeEngines(de_ctx, sgh->payload_engines);
386  sgh->payload_engines = NULL;
387  }
388  if (sgh->tx_engines) {
389  PrefilterFreeEngines(de_ctx, sgh->tx_engines);
390  sgh->tx_engines = NULL;
391  }
392  if (sgh->frame_engines) {
393  PrefilterFreeEngines(de_ctx, sgh->frame_engines);
394  sgh->frame_engines = NULL;
395  }
396 }
397 
398 static int PrefilterSetupRuleGroupSortHelper(const void *a, const void *b)
399 {
400  const PrefilterEngine *s0 = a;
401  const PrefilterEngine *s1 = b;
402  if (s1->ctx.tx_min_progress == s0->ctx.tx_min_progress) {
403  if (s1->alproto == s0->alproto) {
404  return s0->local_id > s1->local_id ? 1 : -1;
405  } else {
406  return s0->alproto > s1->alproto ? 1 : -1;
407  }
408  } else {
409  return s0->ctx.tx_min_progress > s1->ctx.tx_min_progress ? 1 : -1;
410  }
411 }
412 
414 {
415  int r = PatternMatchPrepareGroup(de_ctx, sgh);
416  if (r != 0) {
417  FatalError(SC_ERR_INITIALIZATION, "failed to set up pattern matching");
418  }
419 
420  /* set up engines if needed - when prefilter is set to auto we run
421  * all engines, otherwise only those that have been forced by the
422  * prefilter keyword. */
424  for (int i = 0; i < DETECT_TBLSIZE; i++)
425  {
426  if (sigmatch_table[i].SetupPrefilter != NULL &&
427  (setting == DETECT_PREFILTER_AUTO ||
429  {
431  }
432  }
433 
434  /* we have lists of engines in sgh->init now. Lets setup the
435  * match arrays */
437  if (sgh->init->pkt_engines != NULL) {
438  uint32_t cnt = 0;
439  for (el = sgh->init->pkt_engines ; el != NULL; el = el->next) {
440  cnt++;
442  }
443  sgh->pkt_engines = SCMallocAligned(cnt * sizeof(PrefilterEngine), CLS);
444  if (sgh->pkt_engines == NULL) {
445  return;
446  }
447  memset(sgh->pkt_engines, 0x00, (cnt * sizeof(PrefilterEngine)));
448 
449  PrefilterEngine *e = sgh->pkt_engines;
450  for (el = sgh->init->pkt_engines ; el != NULL; el = el->next) {
451  e->local_id = el->id;
452  e->cb.Prefilter = el->Prefilter;
453  e->pectx = el->pectx;
454  el->pectx = NULL; // e now owns the ctx
455  e->gid = el->gid;
456  if (el->next == NULL) {
457  e->is_last = TRUE;
458  }
459  e++;
460  }
461  }
462  if (sgh->init->payload_engines != NULL) {
463  uint32_t cnt = 0;
464  for (el = sgh->init->payload_engines ; el != NULL; el = el->next) {
465  cnt++;
467  }
468  sgh->payload_engines = SCMallocAligned(cnt * sizeof(PrefilterEngine), CLS);
469  if (sgh->payload_engines == NULL) {
470  return;
471  }
472  memset(sgh->payload_engines, 0x00, (cnt * sizeof(PrefilterEngine)));
473 
475  for (el = sgh->init->payload_engines ; el != NULL; el = el->next) {
476  e->local_id = el->id;
477  e->cb.Prefilter = el->Prefilter;
478  e->pectx = el->pectx;
479  el->pectx = NULL; // e now owns the ctx
480  e->gid = el->gid;
481  if (el->next == NULL) {
482  e->is_last = TRUE;
483  }
484  e++;
485  }
486  }
487  if (sgh->init->tx_engines != NULL) {
488  uint32_t cnt = 0;
489  for (el = sgh->init->tx_engines ; el != NULL; el = el->next) {
490  cnt++;
492  }
493  sgh->tx_engines = SCMallocAligned(cnt * sizeof(PrefilterEngine), CLS);
494  if (sgh->tx_engines == NULL) {
495  return;
496  }
497  memset(sgh->tx_engines, 0x00, (cnt * sizeof(PrefilterEngine)));
498 
499  uint16_t local_id = 0;
500  PrefilterEngine *e = sgh->tx_engines;
501  for (el = sgh->init->tx_engines ; el != NULL; el = el->next) {
502  e->local_id = local_id++;
503  e->alproto = el->alproto;
505  e->cb.PrefilterTx = el->PrefilterTx;
506  e->pectx = el->pectx;
507  el->pectx = NULL; // e now owns the ctx
508  e->gid = el->gid;
509  e++;
510  }
511 
512  /* sort by tx_min_progress, then alproto, then local_id */
513  qsort(sgh->tx_engines, local_id, sizeof(PrefilterEngine),
514  PrefilterSetupRuleGroupSortHelper);
515  sgh->tx_engines[local_id - 1].is_last = true;
516  sgh->tx_engines[local_id - 1].is_last_for_progress = true;
517 
518  PrefilterEngine *engine;
519 
520  /* per alproto to set is_last_for_progress per alproto because the inspect
521  * loop skips over engines that are not the correct alproto */
522  for (AppProto a = 1; a < ALPROTO_FAILED; a++) {
523  int last_tx_progress = 0;
524  bool last_tx_progress_set = false;
525  PrefilterEngine *prev_engine = NULL;
526  engine = sgh->tx_engines;
527  do {
528  BUG_ON(engine->ctx.tx_min_progress < last_tx_progress);
529  if (engine->alproto == a) {
530  if (last_tx_progress_set && engine->ctx.tx_min_progress > last_tx_progress) {
531  if (prev_engine) {
532  prev_engine->is_last_for_progress = true;
533  }
534  }
535 
536  last_tx_progress_set = true;
537  prev_engine = engine;
538  } else {
539  if (prev_engine) {
540  prev_engine->is_last_for_progress = true;
541  }
542  }
543  last_tx_progress = engine->ctx.tx_min_progress;
544  if (engine->is_last)
545  break;
546  engine++;
547  } while (1);
548  }
549 #ifdef DEBUG
550  SCLogDebug("sgh %p", sgh);
551  engine = sgh->tx_engines;
552  do {
553  SCLogDebug("engine: gid %u alproto %s tx_min_progress %d is_last %s "
554  "is_last_for_progress %s",
555  engine->gid, AppProtoToString(engine->alproto), engine->ctx.tx_min_progress,
556  engine->is_last ? "true" : "false",
557  engine->is_last_for_progress ? "true" : "false");
558  if (engine->is_last)
559  break;
560  engine++;
561  } while (1);
562 #endif
563  }
564  if (sgh->init->frame_engines != NULL) {
565  uint32_t cnt = 0;
566  for (el = sgh->init->frame_engines; el != NULL; el = el->next) {
567  cnt++;
569  }
570  sgh->frame_engines = SCMallocAligned(cnt * sizeof(PrefilterEngine), CLS);
571  if (sgh->frame_engines == NULL) {
572  return;
573  }
574  memset(sgh->frame_engines, 0x00, (cnt * sizeof(PrefilterEngine)));
575 
576  PrefilterEngine *e = sgh->frame_engines;
577  for (el = sgh->init->frame_engines; el != NULL; el = el->next) {
578  e->local_id = el->id;
579  e->ctx.frame_type = el->frame_type;
581  e->alproto = el->alproto;
582  e->pectx = el->pectx;
583  el->pectx = NULL; // e now owns the ctx
584  e->gid = el->gid;
585  if (el->next == NULL) {
586  e->is_last = TRUE;
587  }
588  e++;
589  }
590  }
591 }
592 
593 /* hash table for assigning a unique id to each engine type. */
594 
595 static uint32_t PrefilterStoreHashFunc(HashListTable *ht, void *data, uint16_t datalen)
596 {
597  PrefilterStore *ctx = data;
598 
599  uint32_t hash = strlen(ctx->name);
600 
601  for (size_t u = 0; u < strlen(ctx->name); u++) {
602  hash += ctx->name[u];
603  }
604 
605  hash %= ht->array_size;
606  return hash;
607 }
608 
609 static char PrefilterStoreCompareFunc(void *data1, uint16_t len1,
610  void *data2, uint16_t len2)
611 {
612  PrefilterStore *ctx1 = data1;
613  PrefilterStore *ctx2 = data2;
614  return (strcmp(ctx1->name, ctx2->name) == 0);
615 }
616 
617 static void PrefilterStoreFreeFunc(void *ptr)
618 {
619  SCFree(ptr);
620 }
621 
623 {
624  if (de_ctx->prefilter_hash_table != NULL) {
626  }
627 }
628 
630 {
632 
634  PrefilterStoreHashFunc,
635  PrefilterStoreCompareFunc,
636  PrefilterStoreFreeFunc);
638 }
639 
640 static int PrefilterStoreGetId(DetectEngineCtx *de_ctx,
641  const char *name, void (*FreeFunc)(void *))
642 {
643  PrefilterStore ctx = { name, FreeFunc, 0 };
644 
646 
647  SCLogDebug("looking up %s", name);
648 
650  if (rctx != NULL) {
651  return rctx->id;
652  }
653 
654  PrefilterStore *actx = SCCalloc(1, sizeof(*actx));
655  if (actx == NULL) {
656  return -1;
657  }
658 
659  actx->name = name;
660  actx->FreeFunc = FreeFunc;
661  actx->id = de_ctx->prefilter_id++;
662  SCLogDebug("prefilter engine %s has profile id %u", actx->name, actx->id);
663 
664  int ret = HashListTableAdd(de_ctx->prefilter_hash_table, actx, 0);
665  if (ret != 0) {
666  SCFree(actx);
667  return -1;
668  }
669 
670  int r = actx->id;
671  return r;
672 }
673 
674 /** \warning slow */
675 static const PrefilterStore *PrefilterStoreGetStore(const DetectEngineCtx *de_ctx,
676  const uint32_t id)
677 {
678 
679  const PrefilterStore *store = NULL;
680  if (de_ctx->prefilter_hash_table != NULL) {
682  for ( ; hb != NULL; hb = HashListTableGetListNext(hb)) {
684  if (ctx->id == id) {
685  store = ctx;
686  break;
687  }
688  }
689  }
690  return store;
691 }
692 
693 #ifdef PROFILING
694 const char *PrefilterStoreGetName(const uint32_t id)
695 {
696  return NULL;
697 }
698 #endif
699 
700 #include "util-print.h"
701 
702 typedef struct PrefilterMpmCtx {
703  int list_id;
705  const MpmCtx *mpm_ctx;
708 
709 /** \brief Generic Mpm prefilter callback
710  *
711  * \param det_ctx detection engine thread ctx
712  * \param p packet to inspect
713  * \param f flow to inspect
714  * \param txv tx to inspect
715  * \param pectx inspection context
716  */
717 static void PrefilterMpm(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f,
718  void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
719 {
720  SCEnter();
721 
722  const PrefilterMpmCtx *ctx = (const PrefilterMpmCtx *)pectx;
723  const MpmCtx *mpm_ctx = ctx->mpm_ctx;
724  SCLogDebug("running on list %d", ctx->list_id);
725 
726  InspectionBuffer *buffer = ctx->GetData(det_ctx, ctx->transforms,
727  f, flags, txv, ctx->list_id);
728  if (buffer == NULL)
729  return;
730 
731  const uint32_t data_len = buffer->inspect_len;
732  const uint8_t *data = buffer->inspect;
733 
734  SCLogDebug("mpm'ing buffer:");
735  //PrintRawDataFp(stdout, data, data_len);
736 
737  if (data != NULL && data_len >= mpm_ctx->minlen) {
738  (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
739  &det_ctx->mtcu, &det_ctx->pmq, data, data_len);
740  PREFILTER_PROFILING_ADD_BYTES(det_ctx, data_len);
741  }
742 }
743 
744 static void PrefilterGenericMpmFree(void *ptr)
745 {
746  SCFree(ptr);
747 }
748 
750  SigGroupHead *sgh, MpmCtx *mpm_ctx,
751  const DetectBufferMpmRegistery *mpm_reg, int list_id)
752 {
753  SCEnter();
754  PrefilterMpmCtx *pectx = SCCalloc(1, sizeof(*pectx));
755  if (pectx == NULL)
756  return -1;
757  pectx->list_id = list_id;
758  pectx->GetData = mpm_reg->app_v2.GetData;
759  pectx->mpm_ctx = mpm_ctx;
760  pectx->transforms = &mpm_reg->transforms;
761 
762  int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpm,
763  mpm_reg->app_v2.alproto, mpm_reg->app_v2.tx_min_progress,
764  pectx, PrefilterGenericMpmFree, mpm_reg->pname);
765  if (r != 0) {
766  SCFree(pectx);
767  }
768  return r;
769 }
770 
771 /* generic mpm for pkt engines */
772 
773 typedef struct PrefilterMpmPktCtx {
774  int list_id;
776  const MpmCtx *mpm_ctx;
779 
780 /** \brief Generic Mpm prefilter callback
781  *
782  * \param det_ctx detection engine thread ctx
783  * \param p packet to inspect
784  * \param f flow to inspect
785  * \param txv tx to inspect
786  * \param pectx inspection context
787  */
788 static void PrefilterMpmPkt(DetectEngineThreadCtx *det_ctx,
789  Packet *p, const void *pectx)
790 {
791  SCEnter();
792 
793  const PrefilterMpmPktCtx *ctx = (const PrefilterMpmPktCtx *)pectx;
794  const MpmCtx *mpm_ctx = ctx->mpm_ctx;
795  SCLogDebug("running on list %d", ctx->list_id);
796 
797  InspectionBuffer *buffer = ctx->GetData(det_ctx, ctx->transforms,
798  p, ctx->list_id);
799  if (buffer == NULL)
800  return;
801 
802  const uint32_t data_len = buffer->inspect_len;
803  const uint8_t *data = buffer->inspect;
804 
805  SCLogDebug("mpm'ing buffer:");
806  //PrintRawDataFp(stdout, data, data_len);
807 
808  if (data != NULL && data_len >= mpm_ctx->minlen) {
809  (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
810  &det_ctx->mtcu, &det_ctx->pmq, data, data_len);
811  PREFILTER_PROFILING_ADD_BYTES(det_ctx, data_len);
812  }
813 }
814 
815 static void PrefilterMpmPktFree(void *ptr)
816 {
817  SCFree(ptr);
818 }
819 
821  SigGroupHead *sgh, MpmCtx *mpm_ctx,
822  const DetectBufferMpmRegistery *mpm_reg, int list_id)
823 {
824  SCEnter();
825  PrefilterMpmPktCtx *pectx = SCCalloc(1, sizeof(*pectx));
826  if (pectx == NULL)
827  return -1;
828  pectx->list_id = list_id;
829  pectx->GetData = mpm_reg->pkt_v1.GetData;
830  pectx->mpm_ctx = mpm_ctx;
831  pectx->transforms = &mpm_reg->transforms;
832 
833  int r = PrefilterAppendEngine(de_ctx, sgh, PrefilterMpmPkt,
834  pectx, PrefilterMpmPktFree, mpm_reg->pname);
835  if (r != 0) {
836  SCFree(pectx);
837  }
838  return r;
839 }
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:59
PrefilterEngineList_::frame_type
uint8_t frame_type
Definition: detect.h:1313
SigGroupHead_::tx_engines
PrefilterEngine * tx_engines
Definition: detect.h:1411
Packet_::proto
uint8_t proto
Definition: decode.h:450
DetectTransaction_::tx_data_ptr
struct AppLayerTxData * tx_data_ptr
Definition: detect-engine-prefilter.h:34
MpmCtx_::mpm_type
uint8_t mpm_type
Definition: util-mpm.h:90
detect-engine.h
PrefilterEngine_::Prefilter
void(* Prefilter)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
Definition: detect.h:1351
PatternMatchPrepareGroup
int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
Prepare the pattern matcher ctx in a sig group head.
Definition: detect-engine-mpm.c:2055
PrefilterMpmPktCtx
struct PrefilterMpmPktCtx PrefilterMpmPktCtx
PrefilterStore_::FreeFunc
void(* FreeFunc)(void *)
Definition: detect-engine-prefilter.h:46
PREFILTER_PROFILING_END
#define PREFILTER_PROFILING_END(ctx, profile_id)
Definition: util-profiling.h:297
PrefilterStore_
Definition: detect-engine-prefilter.h:44
CLS
#define CLS
Definition: suricata-common.h:53
Prefilter
void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, const uint8_t flags)
Definition: detect-engine-prefilter.c:143
PrefilterRuleStore_::rule_id_array_cnt
uint32_t rule_id_array_cnt
Definition: util-prefilter.h:40
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1392
DetectEngineTransforms
Definition: detect.h:371
PrefilterEngineList_::id
uint16_t id
Definition: detect.h:1305
PROF_DETECT_PF_PAYLOAD
@ PROF_DETECT_PF_PAYLOAD
Definition: suricata-common.h:435
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:296
Packet_::pcap_cnt
uint64_t pcap_cnt
Definition: decode.h:594
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:80
PrefilterMpmCtx::GetData
InspectionBufferGetDataPtr GetData
Definition: detect-engine-prefilter.c:704
DetectBufferMpmRegistery_::transforms
DetectEngineTransforms transforms
Definition: detect.h:639
InspectionBuffer
Definition: detect.h:337
Packet_::flags
uint32_t flags
Definition: decode.h:463
DetectEngineCtx_::prefilter_maxid
uint32_t prefilter_maxid
Definition: detect.h:914
DETECT_TBLSIZE
@ DETECT_TBLSIZE
Definition: detect-engine-register.h:335
Flow_
Flow data structure.
Definition: flow.h:356
PREFILTER_PROFILING_START
#define PREFILTER_PROFILING_START(det_ctx)
Definition: util-profiling.h:281
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1131
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:377
PrefilterGenericMpmRegister
int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:749
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:30
DetectBufferMpmRegistery_::app_v2
struct DetectBufferMpmRegistery_::@87::@89 app_v2
PrefilterEngineList_::name
const char * name
Definition: detect.h:1328
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:784
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:290
PrefilterEngine_::tx_min_progress
uint8_t tx_min_progress
Definition: detect.h:1342
InspectionBufferGetPktDataPtr
InspectionBuffer *(* InspectionBufferGetPktDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Packet *p, const int list_id)
Definition: detect.h:437
PrefilterDeinit
void PrefilterDeinit(DetectEngineCtx *de_ctx)
Definition: detect-engine-prefilter.c:622
PrefilterMpmPktCtx
Definition: detect-engine-prefilter.c:773
DetectBufferMpmRegistery_
one time registration of keywords at start up
Definition: detect.h:625
detect-engine-frame.h
PrefilterEngineList_::Prefilter
void(* Prefilter)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
Definition: detect.h:1319
SigGroupHead_::payload_engines
PrefilterEngine * payload_engines
Definition: detect.h:1410
DetectEngineCtx_::prefilter_setting
enum DetectEnginePrefilterSetting prefilter_setting
Definition: detect.h:929
PKT_NOPAYLOAD_INSPECTION
#define PKT_NOPAYLOAD_INSPECTION
Definition: decode.h:991
PACKET_PROFILING_DETECT_END
#define PACKET_PROFILING_DETECT_END(p, id)
Definition: util-profiling.h:242
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:248
PrefilterEngine_::local_id
uint16_t local_id
Definition: detect.h:1334
PrefilterEngineList_::Free
void(* Free)(void *pectx)
Definition: detect.h:1326
MAX
#define MAX(x, y)
Definition: suricata-common.h:384
PrefilterAppendFrameEngine
int PrefilterAppendFrameEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterFrameFn PrefilterFrameFunc, AppProto alproto, uint8_t frame_type, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Definition: detect-engine-prefilter.c:307
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:574
DetectTransaction_::tx_progress
const int tx_progress
Definition: detect-engine-prefilter.h:40
detect-engine-prefilter.h
DetectEngineThreadCtx_::mtcu
MpmThreadCtx mtcu
Definition: detect.h:1129
PrefilterStore_::id
uint32_t id
Definition: detect-engine-prefilter.h:47
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:116
DETECT_PREFILTER_AUTO
@ DETECT_PREFILTER_AUTO
Definition: detect.h:766
HashListTable_::array_size
uint32_t array_size
Definition: util-hashlist.h:41
PrefilterEngine_::is_last_for_progress
bool is_last_for_progress
Definition: detect.h:1359
PROF_DETECT_PF_SORT1
@ PROF_DETECT_PF_SORT1
Definition: suricata-common.h:438
DetectEngineCtx_::prefilter_id
uint32_t prefilter_id
Definition: detect.h:960
PrefilterEngineList_::next
struct PrefilterEngineList_ * next
Definition: detect.h:1323
SigTableElmt_::SetupPrefilter
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1223
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:488
PrefilterGenericMpmPktRegister
int PrefilterGenericMpmPktRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistery *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:820
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:58
DetectEngineCtx_::prefilter_hash_table
HashListTable * prefilter_hash_table
Definition: detect.h:961
app-layer-htp.h
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
PrefilterEngineList_::alproto
AppProto alproto
Definition: detect.h:1308
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
PrefilterStoreGetName
const char * PrefilterStoreGetName(const uint32_t id)
Definition: detect-engine-prefilter.c:694
DetectEngineThreadCtx_
Definition: detect.h:1024
PrefilterEngine_
Definition: detect.h:1333
SigGroupHeadInitData_::tx_engines
PrefilterEngineList * tx_engines
Definition: detect.h:1378
PROF_DETECT_PF_PKT
@ PROF_DETECT_PF_PKT
Definition: suricata-common.h:434
PrefilterEngineList_::PrefilterFrame
PrefilterFrameFn PrefilterFrame
Definition: detect.h:1321
PrefilterEngineList_::pectx
void * pectx
Definition: detect.h:1317
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:298
detect-engine-mpm.h
PrefilterFrameFn
void(* PrefilterFrameFn)(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, const struct Frames *frames, const struct Frame *frame, const uint32_t idx)
Definition: detect.h:1297
PrefilterEngineList_::PrefilterTx
PrefilterTxFn PrefilterTx
Definition: detect.h:1320
PrefilterEngineList_::gid
uint32_t gid
Definition: detect.h:1330
PrefilterMpmPktCtx::GetData
InspectionBufferGetPktDataPtr GetData
Definition: detect-engine-prefilter.c:775
PKT_DETECT_HAS_STREAMDATA
#define PKT_DETECT_HAS_STREAMDATA
Definition: decode.h:1041
PrefilterMpmCtx
struct PrefilterMpmCtx PrefilterMpmCtx
SigGroupHead_::init
SigGroupHeadInitData * init
Definition: detect.h:1415
app-layer-parser.h
MpmCtx_::minlen
uint16_t minlen
Definition: util-mpm.h:99
TRUE
#define TRUE
Definition: suricata-common.h:33
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:289
util-profiling.h
DetectTransaction_::tx_id
const uint64_t tx_id
Definition: detect-engine-prefilter.h:33
SCReturn
#define SCReturn
Definition: util-debug.h:300
PrefilterEngine_::alproto
AppProto alproto
Definition: detect.h:1337
DetectTransaction_::prefilter_flags
uint64_t prefilter_flags
Definition: detect-engine-prefilter.h:37
Packet_
Definition: decode.h:428
SCFreeAligned
#define SCFreeAligned(p)
Definition: util-mem.h:77
PrefilterEngine_::cb
union PrefilterEngine_::@101 cb
PrefilterEngine_::PrefilterFrame
PrefilterFrameFn PrefilterFrame
Definition: detect.h:1353
PrefilterEngine_::frame_type
uint8_t frame_type
Definition: detect.h:1343
HashListTable_
Definition: util-hashlist.h:37
BIT_U64
#define BIT_U64(n)
Definition: suricata-common.h:390
PrefilterTxFn
void(* PrefilterTxFn)(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f, void *tx, const uint64_t tx_id, const AppLayerTxData *tx_data, const uint8_t flags)
Definition: detect.h:1301
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:165
SigGroupHead_::frame_engines
PrefilterEngine * frame_engines
Definition: detect.h:1412
PrefilterMpmCtx::list_id
int list_id
Definition: detect-engine-prefilter.c:703
PrefilterMpmPktCtx::list_id
int list_id
Definition: detect-engine-prefilter.c:774
SigGroupHeadInitData_::pkt_engines
PrefilterEngineList * pkt_engines
Definition: detect.h:1376
AppLayerTxData
struct AppLayerTxData AppLayerTxData
Definition: detect.h:1300
PREFILTER_PROFILING_ADD_BYTES
#define PREFILTER_PROFILING_ADD_BYTES(det_ctx, bytes)
Definition: util-profiling.h:307
Packet_::flow
struct Flow_ * flow
Definition: decode.h:465
DetectBufferMpmRegistery_::pname
char pname[32]
Definition: detect.h:627
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
SigGroupHeadInitData_::frame_engines
PrefilterEngineList * frame_engines
Definition: detect.h:1379
SigGroupHeadInitData_::payload_engines
PrefilterEngineList * payload_engines
Definition: detect.h:1377
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:82
PROF_DETECT_PF_RECORD
@ PROF_DETECT_PF_RECORD
Definition: suricata-common.h:437
SCMallocAligned
#define SCMallocAligned(size, align)
Definition: util-mem.h:68
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:76
DetectEnginePrefilterSetting
DetectEnginePrefilterSetting
Definition: detect.h:764
DetectTransaction_
Definition: detect-engine-prefilter.h:31
PrefilterEngineList_
Definition: detect.h:1304
PrefilterCleanupRuleGroup
void PrefilterCleanupRuleGroup(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Definition: detect-engine-prefilter.c:378
PrefilterEngine_::gid
uint32_t gid
Definition: detect.h:1357
FatalError
#define FatalError(x,...)
Definition: util-debug.h:530
PrefilterMpmPktCtx::transforms
const DetectEngineTransforms * transforms
Definition: detect-engine-prefilter.c:777
PrefilterAppendTxEngine
int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterTxFn PrefilterTxFunc, AppProto alproto, int tx_min_progress, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Definition: detect-engine-prefilter.c:270
PrefilterMpmCtx
Definition: detect-engine-prefilter.c:702
util-validate.h
DetectTransaction_::tx_ptr
void * tx_ptr
Definition: detect-engine-prefilter.h:32
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect.h:340
PrefilterEngine_::pectx
void * pectx
Definition: detect.h:1348
PrefilterInit
void PrefilterInit(DetectEngineCtx *de_ctx)
Definition: detect-engine-prefilter.c:629
DetectEngineCtx_::sm_types_prefilter
bool sm_types_prefilter[DETECT_TBLSIZE]
Definition: detect.h:972
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect.h:338
PACKET_PROFILING_DETECT_START
#define PACKET_PROFILING_DETECT_START(p, id)
Definition: util-profiling.h:235
PrefilterMpmCtx::transforms
const DetectEngineTransforms * transforms
Definition: detect-engine-prefilter.c:706
PrefilterStore_::name
const char * name
Definition: detect-engine-prefilter.h:45
SCFree
#define SCFree(p)
Definition: util-mem.h:61
PrefilterAppendPayloadEngine
int PrefilterAppendPayloadEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, void(*PrefilterFunc)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx), void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Definition: detect-engine-prefilter.c:236
HashListTableBucket_
Definition: util-hashlist.h:28
PrefilterMpmPktCtx::mpm_ctx
const MpmCtx * mpm_ctx
Definition: detect-engine-prefilter.c:776
DetectBufferMpmRegistery_::pkt_v1
struct DetectBufferMpmRegistery_::@87::@90 pkt_v1
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
ALPROTO_FAILED
@ ALPROTO_FAILED
Definition: app-layer-protos.h:70
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:48
PrefilterEngine_::ctx
union PrefilterEngine_::@100 ctx
PrefilterEngine_::is_last
bool is_last
Definition: detect.h:1358
suricata.h
PrefilterEngineList_::tx_min_progress
uint8_t tx_min_progress
Definition: detect.h:1311
PrefilterSetupRuleGroup
void PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Definition: detect-engine-prefilter.c:413
likely
#define likely(expr)
Definition: util-optimize.h:32
SigGroupHead_::pkt_engines
PrefilterEngine * pkt_engines
Definition: detect.h:1409
SC_ERR_INITIALIZATION
@ SC_ERR_INITIALIZATION
Definition: util-error.h:75
PrefilterEngine_::PrefilterTx
PrefilterTxFn PrefilterTx
Definition: detect.h:1352
MpmCtx_
Definition: util-mpm.h:88
PrefilterAppendEngine
int PrefilterAppendEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, void(*PrefilterFunc)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx), void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Definition: detect-engine-prefilter.c:202
SigIntId
#define SigIntId
Definition: suricata-common.h:304
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:463
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
PrefilterFreeEnginesList
void PrefilterFreeEnginesList(PrefilterEngineList *list)
Definition: detect-engine-prefilter.c:350
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:111
PrefilterMpmCtx::mpm_ctx
const MpmCtx * mpm_ctx
Definition: detect-engine-prefilter.c:705
DetectRunPrefilterTx
void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, const uint8_t ipproto, const uint8_t flow_flags, const AppProto alproto, void *alstate, DetectTransaction *tx)
run prefilter engines on a transaction
Definition: detect-engine-prefilter.c:93
PrefilterRuleStore_::rule_id_array
SigIntId * rule_id_array
Definition: util-prefilter.h:38