suricata
detect-engine-prefilter.c
Go to the documentation of this file.
1 /* Copyright (C) 2016-2025 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 #include "detect-engine-uint.h"
55 
56 #include "app-layer-parser.h"
57 #include "app-layer-htp.h"
58 
59 #include "util-profiling.h"
60 #include "util-validate.h"
61 #include "util-hash-string.h"
62 
63 static int PrefilterStoreGetId(DetectEngineCtx *de_ctx,
64  const char *name, void (*FreeFunc)(void *));
65 static const PrefilterStore *PrefilterStoreGetStore(const DetectEngineCtx *de_ctx,
66  const uint32_t id);
67 
68 static inline void QuickSortSigIntId(SigIntId *sids, uint32_t n)
69 {
70  if (n < 2)
71  return;
72  SigIntId p = sids[n / 2];
73  SigIntId *l = sids;
74  SigIntId *r = sids + n - 1;
75  while (l <= r) {
76  if (*l < p)
77  l++;
78  else if (*r > p)
79  r--;
80  else {
81  SigIntId t = *l;
82  *l = *r;
83  *r = t;
84  l++;
85  r--;
86  }
87  }
88  QuickSortSigIntId(sids, (uint32_t)(r - sids) + 1);
89  QuickSortSigIntId(l, (uint32_t)(sids + n - l));
90 }
91 
92 /**
93  * \brief run prefilter engines on a transaction
94  */
96  const SigGroupHead *sgh,
97  Packet *p,
98  const uint8_t ipproto,
99  const uint8_t flow_flags,
100  const AppProto alproto,
101  void *alstate,
102  DetectTransaction *tx)
103 {
104  /* reset rule store */
105  det_ctx->pmq.rule_id_array_cnt = 0;
106 
107  SCLogDebug("packet %" PRIu64 " tx %p id %" PRIu64 " progress %d tx->detect_progress %02x",
109 
110  PrefilterEngine *engine = sgh->tx_engines;
111  do {
112  SCLogDebug("%" PRIu64 ": engine %p for %s progress %u sub_state %u tx %u",
113  PcapPacketCntGet(p), engine, AppProtoToString(engine->alproto),
114  engine->ctx.app.tx_min_progress, engine->ctx.app.sub_state, tx->tx_type);
115 
117  AppLayerParserSupportsSubStates(engine->alproto) && engine->ctx.app.sub_state == 0);
119  engine->ctx.app.sub_state != 0);
120 
121  if (engine->alproto != ALPROTO_UNKNOWN && engine->ctx.app.sub_state != tx->tx_type) {
122  SCLogDebug("%" PRIu64 ": engine %p sub_state %u mismatch with tx %u",
123  PcapPacketCntGet(p), engine, engine->ctx.app.sub_state, tx->tx_type);
124  // not for the tx sub state
125  goto next;
126  }
127  // based on flow alproto, and engine, we get right tx_ptr
128  void *tx_ptr = DetectGetInnerTx(tx->tx_ptr, alproto, engine->alproto, flow_flags);
129  if (tx_ptr == NULL) {
130  // incompatible engine->alproto with flow alproto
131  goto next;
132  }
133 
134  if (engine->ctx.app.tx_min_progress != -1) {
136 #ifdef DEBUG
137  const char *pname = AppLayerParserGetStateNameById(ipproto, engine->alproto,
138  engine->ctx.app.tx_min_progress,
139  flow_flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
140  SCLogDebug("engine %p min_progress %d %s:%s", engine, engine->ctx.app.tx_min_progress,
141  AppProtoToString(engine->alproto), pname);
142 #endif
143  /* if engine needs tx state to be higher, break out. */
144  if (engine->ctx.app.tx_min_progress > tx->tx_progress)
145  break;
146  if (tx->tx_progress > engine->ctx.app.tx_min_progress) {
147  SCLogDebug("tx->tx_progress %u > engine->ctx.app.tx_min_progress %d",
148  tx->tx_progress, engine->ctx.app.tx_min_progress);
149 
150  /* if state value is at or beyond engine state, we can skip it. It means we ran at
151  * least once already. A run-always engine (stateful keyword) is revisited on
152  * every update, so detect_progress must not skip it. */
153  if (!engine->run_always && tx->detect_progress > engine->ctx.app.tx_min_progress) {
154  SCLogDebug("tx already marked progress as beyond engine: %u > %u",
155  tx->detect_progress, engine->ctx.app.tx_min_progress);
156  goto next;
157  } else {
158  SCLogDebug("tx->tx_progress %u > engine->ctx.app.tx_min_progress %d: "
159  "tx->detect_progress %u",
160  tx->tx_progress, engine->ctx.app.tx_min_progress, tx->detect_progress);
161  }
162  }
163 #ifdef DEBUG
164  uint32_t old = det_ctx->pmq.rule_id_array_cnt;
165 #endif
166  PREFILTER_PROFILING_START(det_ctx);
167  engine->cb.PrefilterTx(det_ctx, engine->pectx, p, p->flow, tx_ptr, tx->tx_id,
168  tx->tx_data_ptr, flow_flags);
169  PREFILTER_PROFILING_END(det_ctx, engine->gid);
170  SCLogDebug("engine %p min_progress %d %s:%s: results %u", engine,
171  engine->ctx.app.tx_min_progress, AppProtoToString(engine->alproto), pname,
172  det_ctx->pmq.rule_id_array_cnt - old);
173 
174  if (tx->tx_progress > engine->ctx.app.tx_min_progress && engine->is_last_for_progress &&
175  tx->tx_ptr == tx_ptr) {
176  /* track with an offset of one, so that tx->progress 0 complete is tracked
177  * as 1, progress 1 as 2, etc. This is to allow 0 to mean: nothing tracked, even
178  * though a parser may use 0 as a valid value. */
179  // tx->tx_ptr == tx_ptr ensures we do not use a dns engine progress
180  // to update a HTTP2 tx detect_progress in case of DOH2
181  //
182  // monotonic: a run-always engine at a lower progress is revisited
183  // after the tx moved on, and must not re-enable the engines it
184  // already completed
185  if (tx->detect_progress < engine->ctx.app.tx_min_progress + 1) {
186  tx->detect_progress = engine->ctx.app.tx_min_progress + 1;
187  }
188  SCLogDebug("tx->tx_progress %d engine->ctx.app.tx_min_progress %d "
189  "engine->is_last_for_progress %d => tx->detect_progress updated to %02x",
190  tx->tx_progress, engine->ctx.app.tx_min_progress,
192  }
193  } else {
195  PREFILTER_PROFILING_START(det_ctx);
196  engine->cb.PrefilterTx(det_ctx, engine->pectx, p, p->flow, tx_ptr, tx->tx_id,
197  tx->tx_data_ptr, flow_flags);
198  PREFILTER_PROFILING_END(det_ctx, engine->gid);
199  }
200  next:
201  if (engine->is_last)
202  break;
203  engine++;
204  } while (1);
205 
206  /* Sort the rule list to lets look at pmq.
207  * NOTE due to merging of 'stream' pmqs we *MAY* have duplicate entries */
208  if (likely(det_ctx->pmq.rule_id_array_cnt > 1)) {
210  QuickSortSigIntId(det_ctx->pmq.rule_id_array, det_ctx->pmq.rule_id_array_cnt);
212  }
213 }
214 
215 /** \brief invoke post-rule match "prefilter" engines
216  *
217  * Invoke prefilter engines that depend on a rule match to run.
218  * e.g. the flowbits:set prefilter that adds sids that depend on
219  * a flowbit "set" to the match array.
220  */
222  DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, Flow *f)
223 {
224  SCLogDebug("post-rule-match engines %p", sgh->post_rule_match_engines);
225  if (sgh->post_rule_match_engines) {
227  do {
228  SCLogDebug("running post-rule-match engine");
229  PREFILTER_PROFILING_START(det_ctx);
230  engine->cb.PrefilterPostRule(det_ctx, engine->pectx, p, f);
231  PREFILTER_PROFILING_END(det_ctx, engine->gid);
232 
233  if (engine->is_last)
234  break;
235  engine++;
236  } while (1);
237 
238  if (det_ctx->pmq.rule_id_array_cnt > 1) {
239  QuickSortSigIntId(det_ctx->pmq.rule_id_array, det_ctx->pmq.rule_id_array_cnt);
240  }
241  }
242 }
243 
245  const uint8_t flags, const SignatureMask mask)
246 {
247  SCEnter();
248 #if 0
249  /* TODO review this check */
250  SCLogDebug("sgh %p frame_engines %p", sgh, sgh->frame_engines);
251  if (p->proto == IPPROTO_TCP && sgh->frame_engines && p->flow &&
252  p->flow->alproto != ALPROTO_UNKNOWN && p->flow->alparser != NULL) {
254  PrefilterFrames(det_ctx, sgh, p, flags, p->flow->alproto);
256  }
257 #endif
258  if (sgh->pkt_engines) {
260  /* run packet engines */
261  PrefilterEngine *engine = sgh->pkt_engines;
262  do {
263  /* run engine if:
264  * mask matches
265  * no hook is used OR hook matches
266  */
267  if (((engine->ctx.pkt.mask & mask) == engine->ctx.pkt.mask) &&
268  (engine->ctx.pkt.hook == 0 || (p->pkt_hooks & BIT_U16(engine->ctx.pkt.hook)))) {
269  PREFILTER_PROFILING_START(det_ctx);
270  engine->cb.Prefilter(det_ctx, p, engine->pectx);
271  PREFILTER_PROFILING_END(det_ctx, engine->gid);
272  }
273 
274  if (engine->is_last)
275  break;
276  engine++;
277  } while (1);
279  }
280 
281  /* run payload inspecting engines */
282  if (sgh->payload_engines &&
285  {
287  PrefilterEngine *engine = sgh->payload_engines;
288  while (1) {
289  PREFILTER_PROFILING_START(det_ctx);
290  engine->cb.Prefilter(det_ctx, p, engine->pectx);
291  PREFILTER_PROFILING_END(det_ctx, engine->gid);
292 
293  if (engine->is_last)
294  break;
295  engine++;
296  }
298  }
299 
300  /* Sort the rule list to lets look at pmq.
301  * NOTE due to merging of 'stream' pmqs we *MAY* have duplicate entries */
302  if (likely(det_ctx->pmq.rule_id_array_cnt > 1)) {
304  QuickSortSigIntId(det_ctx->pmq.rule_id_array, det_ctx->pmq.rule_id_array_cnt);
306  }
307  SCReturn;
308 }
309 
311  SignatureMask mask, enum SignatureHookPkt hook, void *pectx, void (*FreeFunc)(void *pectx),
312  const char *name)
313 {
314  if (sgh == NULL || PrefilterFunc == NULL || pectx == NULL)
315  return -1;
316 
317  PrefilterEngineList *e = SCMallocAligned(sizeof(*e), CLS);
318  if (e == NULL)
319  return -1;
320  memset(e, 0x00, sizeof(*e));
321 
322  // TODO right now we represent the hook in a u8 in the prefilter engine for space reasons.
323  BUG_ON(hook >= 8);
324 
325  e->Prefilter = PrefilterFunc;
326  e->pectx = pectx;
327  e->Free = FreeFunc;
328  e->pkt_mask = mask;
329  e->pkt_hook = hook;
330 
331  if (sgh->init->pkt_engines == NULL) {
332  sgh->init->pkt_engines = e;
333  } else {
335  while (t->next != NULL) {
336  t = t->next;
337  }
338 
339  t->next = e;
340  e->id = t->id + 1;
341  }
342 
343  e->name = name;
344  e->gid = PrefilterStoreGetId(de_ctx, e->name, e->Free);
345  SCLogDebug("sgh->init->pkt_engines %p", sgh->init->pkt_engines);
346  return 0;
347 }
348 
350  PrefilterPktFn PrefilterFunc, void *pectx, void (*FreeFunc)(void *pectx), const char *name)
351 {
352  if (sgh == NULL || PrefilterFunc == NULL || pectx == NULL)
353  return -1;
354 
355  PrefilterEngineList *e = SCMallocAligned(sizeof(*e), CLS);
356  if (e == NULL)
357  return -1;
358  memset(e, 0x00, sizeof(*e));
359 
360  e->Prefilter = PrefilterFunc;
361  e->pectx = pectx;
362  e->Free = FreeFunc;
363 
364  if (sgh->init->payload_engines == NULL) {
365  sgh->init->payload_engines = e;
366  } else {
368  while (t->next != NULL) {
369  t = t->next;
370  }
371 
372  t->next = e;
373  e->id = t->id + 1;
374  }
375 
376  e->name = name;
377  e->gid = PrefilterStoreGetId(de_ctx, e->name, e->Free);
378  return 0;
379 }
380 
382  PrefilterTxFn PrefilterTxFunc, AppProto alproto, uint8_t sub_state,
383  const int8_t tx_min_progress, void *pectx, void (*FreeFunc)(void *pectx), const char *name)
384 {
385  BUG_ON(AppLayerParserSupportsSubStates(alproto) && sub_state == 0);
386  if (sgh == NULL || PrefilterTxFunc == NULL || pectx == NULL)
387  return -1;
388 
389  PrefilterEngineList *e = SCMallocAligned(sizeof(*e), CLS);
390  if (e == NULL)
391  return -1;
392  memset(e, 0x00, sizeof(*e));
393 
394  e->PrefilterTx = PrefilterTxFunc;
395  e->pectx = pectx;
396  e->alproto = alproto;
397  e->tx_min_progress = tx_min_progress;
398  e->sub_state = sub_state;
399  e->Free = FreeFunc;
400 
401  if (sgh->init->tx_engines == NULL) {
402  sgh->init->tx_engines = e;
403  } else {
405  while (t->next != NULL) {
406  t = t->next;
407  }
408 
409  t->next = e;
410  e->id = t->id + 1;
411  }
412 
413  e->name = name;
414  e->gid = PrefilterStoreGetId(de_ctx, e->name, e->Free);
415  SCLogDebug("%s: sub_state %u", name, e->sub_state);
416  return 0;
417 }
418 
420  PrefilterTxFn PrefilterTxFunc, AppProto alproto, const int8_t tx_min_progress, void *pectx,
421  void (*FreeFunc)(void *pectx), const char *name)
422 {
424  de_ctx, sgh, PrefilterTxFunc, alproto, 0, tx_min_progress, pectx, FreeFunc, name);
425 }
426 
428  PrefilterFrameFn PrefilterFrameFunc, AppProto alproto, uint8_t frame_type, void *pectx,
429  void (*FreeFunc)(void *pectx), const char *name)
430 {
431  if (sgh == NULL || PrefilterFrameFunc == NULL || pectx == NULL)
432  return -1;
433 
434  PrefilterEngineList *e = SCMallocAligned(sizeof(*e), CLS);
435  if (e == NULL)
436  return -1;
437  memset(e, 0x00, sizeof(*e));
438 
439  e->frame_type = frame_type;
440  e->alproto = alproto;
441  e->PrefilterFrame = PrefilterFrameFunc;
442  e->pectx = pectx;
443  e->Free = FreeFunc;
444 
445  if (sgh->init->frame_engines == NULL) {
446  sgh->init->frame_engines = e;
447  } else {
449  while (t->next != NULL) {
450  t = t->next;
451  }
452 
453  t->next = e;
454  e->id = t->id + 1;
455  }
456 
457  e->name = name;
458  e->gid = PrefilterStoreGetId(de_ctx, e->name, e->Free);
459  return 0;
460 }
461 
463  void (*PrefilterPostRuleFunc)(
464  DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f),
465  void *pectx, void (*FreeFunc)(void *pectx), const char *name)
466 {
467  if (sgh == NULL || PrefilterPostRuleFunc == NULL || pectx == NULL)
468  return -1;
469 
470  PrefilterEngineList *e = SCMallocAligned(sizeof(*e), CLS);
471  if (e == NULL)
472  return -1;
473  memset(e, 0x00, sizeof(*e));
474  e->PrefilterPostRule = PrefilterPostRuleFunc;
475  e->pectx = pectx;
476  e->Free = FreeFunc;
477 
478  if (sgh->init->post_rule_match_engines == NULL) {
479  sgh->init->post_rule_match_engines = e;
480  } else {
482  while (t->next != NULL) {
483  t = t->next;
484  }
485 
486  t->next = e;
487  e->id = t->id + 1;
488  }
489 
490  e->name = name;
491  e->gid = PrefilterStoreGetId(de_ctx, e->name, e->Free);
492  return 0;
493 }
494 
495 static void PrefilterFreeEngineList(PrefilterEngineList *e)
496 {
497  if (e->Free && e->pectx) {
498  e->Free(e->pectx);
499  }
500  SCFreeAligned(e);
501 }
502 
504 {
505  PrefilterEngineList *t = list;
506 
507  while (t != NULL) {
509  PrefilterFreeEngineList(t);
510  t = next;
511  }
512 }
513 
514 static void PrefilterFreeEngines(const DetectEngineCtx *de_ctx, PrefilterEngine *list)
515 {
516  PrefilterEngine *t = list;
517 
518  while (1) {
519  const PrefilterStore *s = PrefilterStoreGetStore(de_ctx, t->gid);
520  if (s && s->FreeFunc && t->pectx) {
521  s->FreeFunc(t->pectx);
522  }
523 
524  if (t->is_last)
525  break;
526  t++;
527  }
528  SCFreeAligned(list);
529 }
530 
532 {
533  if (sgh->pkt_engines) {
534  PrefilterFreeEngines(de_ctx, sgh->pkt_engines);
535  sgh->pkt_engines = NULL;
536  }
537  if (sgh->payload_engines) {
538  PrefilterFreeEngines(de_ctx, sgh->payload_engines);
539  sgh->payload_engines = NULL;
540  }
541  if (sgh->tx_engines) {
542  PrefilterFreeEngines(de_ctx, sgh->tx_engines);
543  sgh->tx_engines = NULL;
544  }
545  if (sgh->frame_engines) {
546  PrefilterFreeEngines(de_ctx, sgh->frame_engines);
547  sgh->frame_engines = NULL;
548  }
549  if (sgh->post_rule_match_engines) {
550  PrefilterFreeEngines(de_ctx, sgh->post_rule_match_engines);
551  sgh->post_rule_match_engines = NULL;
552  }
553 }
554 
555 static int PrefilterSetupRuleGroupSortHelper(const void *a, const void *b)
556 {
557  const PrefilterEngine *s0 = a;
558  const PrefilterEngine *s1 = b;
559  if (s1->ctx.app.sub_state == s0->ctx.app.sub_state) {
560  if (s1->ctx.app.tx_min_progress == s0->ctx.app.tx_min_progress) {
561  if (s1->alproto == s0->alproto) {
562  return s0->local_id > s1->local_id ? 1 : -1;
563  } else {
564  return s0->alproto > s1->alproto ? 1 : -1;
565  }
566  } else {
567  return s0->ctx.app.tx_min_progress > s1->ctx.app.tx_min_progress ? 1 : -1;
568  }
569  } else {
570  return s0->ctx.app.sub_state > s1->ctx.app.sub_state ? 1 : -1;
571  }
572 }
573 
574 /** prefilter engine data for the non-prefilter engine for the prefilter API */
576  uint32_t sid : 30;
577  uint32_t type : 2; /**< type for `value` field below: 0:alproto 1:dport 2:dsize */
578  uint16_t value;
579  /* since we have 2 more bytes available due to padding, we can add some additional
580  * filters here. */
581  union {
582  struct {
584  } pkt;
585  struct {
586  /* filter for frame type */
587  uint8_t type;
588  } frame;
589  struct {
590  uint8_t foo; // TODO unused
591  } app;
592  };
593 };
594 
596  uint32_t size;
597  struct PrefilterNonPFDataSig array[];
598 };
599 
601  uint32_t size;
602  uint32_t array[];
603 };
604 
605 /** \internal
606  * \brief wrapper for use in APIs */
607 static void PrefilterNonPFDataFree(void *data)
608 {
609  SCFree(data);
610 }
611 
612 static void PrefilterTxNonPF(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f,
613  void *tx, const uint64_t tx_id, const AppLayerTxData *tx_data, const uint8_t flags)
614 {
615  const struct PrefilterNonPFDataTx *data = (const struct PrefilterNonPFDataTx *)pectx;
616  SCLogDebug("adding %u sids", data->size);
617  PrefilterAddSids(&det_ctx->pmq, data->array, data->size);
618 }
619 
620 #ifdef NONPF_PKT_STATS
621 static thread_local uint64_t prefilter_pkt_nonpf_called = 0;
622 static thread_local uint64_t prefilter_pkt_nonpf_mask_fail = 0;
623 static thread_local uint64_t prefilter_pkt_nonpf_alproto_fail = 0;
624 static thread_local uint64_t prefilter_pkt_nonpf_dsize_fail = 0;
625 static thread_local uint64_t prefilter_pkt_nonpf_dport_fail = 0;
626 static thread_local uint64_t prefilter_pkt_nonpf_sids = 0;
627 #define NONPF_PKT_STATS_INCR(s) (s)++
628 #else
629 #define NONPF_PKT_STATS_INCR(s)
630 #endif
631 
633 {
634 #ifdef NONPF_PKT_STATS
635  SCLogDebug("prefilter non-pf: called:%" PRIu64 ", mask_fail:%" PRIu64 ", alproto fail:%" PRIu64
636  ", dport fail:%" PRIu64 ", dsize fail:%" PRIu64 ", sids:%" PRIu64
637  ", avg sids:%" PRIu64,
638  prefilter_pkt_nonpf_called, prefilter_pkt_nonpf_mask_fail,
639  prefilter_pkt_nonpf_alproto_fail, prefilter_pkt_nonpf_dport_fail,
640  prefilter_pkt_nonpf_dsize_fail, prefilter_pkt_nonpf_sids,
641  prefilter_pkt_nonpf_called ? prefilter_pkt_nonpf_sids / prefilter_pkt_nonpf_called : 0);
642 #endif
643 }
644 
645 static void PrefilterPktNonPF(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
646 {
647  const uint16_t alproto = p->flow ? p->flow->alproto : ALPROTO_UNKNOWN;
648  const SignatureMask mask = p->sig_mask;
649  const struct PrefilterNonPFData *data = (const struct PrefilterNonPFData *)pectx;
650  SCLogDebug("adding %u sids", data->size);
651  NONPF_PKT_STATS_INCR(prefilter_pkt_nonpf_called);
652  for (uint32_t i = 0; i < data->size; i++) {
653  const struct PrefilterNonPFDataSig *ds = &data->array[i];
654  const SignatureMask rule_mask = ds->pkt.sig_mask;
655  if ((rule_mask & mask) == rule_mask) {
656  switch (ds->type) {
657  case 0:
658  if (ds->value == ALPROTO_UNKNOWN || AppProtoEquals(ds->value, alproto)) {
659  const uint32_t sid = ds->sid;
660  PrefilterAddSids(&det_ctx->pmq, &sid, 1);
661  NONPF_PKT_STATS_INCR(prefilter_pkt_nonpf_sids);
662  } else {
663  NONPF_PKT_STATS_INCR(prefilter_pkt_nonpf_alproto_fail);
664  }
665  break;
666  case 1:
667  if (ds->value == p->dp) {
668  const uint32_t sid = ds->sid;
669  PrefilterAddSids(&det_ctx->pmq, &sid, 1);
670  NONPF_PKT_STATS_INCR(prefilter_pkt_nonpf_sids);
671  } else {
672  NONPF_PKT_STATS_INCR(prefilter_pkt_nonpf_dport_fail);
673  }
674  break;
675  case 2:
676  if (ds->value == p->payload_len) {
677  const uint32_t sid = ds->sid;
678  PrefilterAddSids(&det_ctx->pmq, &sid, 1);
679  NONPF_PKT_STATS_INCR(prefilter_pkt_nonpf_sids);
680  } else {
681  NONPF_PKT_STATS_INCR(prefilter_pkt_nonpf_dsize_fail);
682  }
683  break;
684  }
685  } else {
686  NONPF_PKT_STATS_INCR(prefilter_pkt_nonpf_mask_fail);
687  }
688  }
689 }
690 
691 static void PrefilterPktNonPFHookFlowStart(
692  DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
693 {
695  PrefilterPktNonPF(det_ctx, p, pectx);
696  }
697 }
698 
699 /** \internal
700  * \brief engine to select the non-prefilter rules for frames
701  * Checks the alproto and type as well.
702  * Direction needs no checking as the rule groups are per direction. */
703 static void PrefilterFrameNonPF(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
704  const Frames *frames, const Frame *frame)
705 {
706  DEBUG_VALIDATE_BUG_ON(p->flow == NULL);
707  const uint16_t alproto = p->flow->alproto;
708  const struct PrefilterNonPFData *data = (const struct PrefilterNonPFData *)pectx;
709  SCLogDebug("adding %u sids", data->size);
710  for (uint32_t i = 0; i < data->size; i++) {
711  const struct PrefilterNonPFDataSig *ds = &data->array[i];
712  if (ds->frame.type == frame->type &&
713  (ds->value == ALPROTO_UNKNOWN || AppProtoEquals(ds->value, alproto))) {
714  const uint32_t sid = ds->sid;
715  PrefilterAddSids(&det_ctx->pmq, &sid, 1);
716  }
717  }
718 }
719 
720 /* helper funcs for the non prefilter names hash */
721 
722 static uint32_t NonPFNamesHash(HashTable *h, void *data, uint16_t _len)
723 {
724  const char *str = data;
725  return StringHashDjb2((const uint8_t *)str, (uint16_t)strlen(str)) % h->array_size;
726 }
727 
728 static char NonPFNamesCompare(void *data1, uint16_t _len1, void *data2, uint16_t len2)
729 {
730  const char *s1 = data1;
731  const char *s2 = data2;
732  return StringHashCompareFunc(data1, (uint16_t)strlen(s1), data2, (uint16_t)strlen(s2));
733 }
734 
735 static void NonPFNamesFree(void *data)
736 {
737  SCFree(data);
738 }
739 
740 /* helper funcs for assembling non-prefilter engines */
741 
742 struct TxNonPFData {
744  uint8_t sub_state;
745  int dir; /**< 0: toserver, 1: toclient */
746  uint8_t progress; /**< progress state value to register at */
747  int sig_list; /**< special handling: normally 0, but for special cases (app-layer-state,
748  app-layer-event) use the list id to create separate engines */
749  /** the buffer holds a stateful keyword: evaluate its engine on every tx
750  * update (engine progress -1) so a provisional miss can be revisited as
751  * the transaction advances. */
753  uint32_t sigs_cnt;
755  const char *engine_name; /**< pointer to name owned by DetectEngineCtx::non_pf_engine_names */
756 };
757 
758 static uint32_t TxNonPFHash(HashListTable *h, void *data, uint16_t _len)
759 {
760  struct TxNonPFData *d = data;
761  return (d->alproto + d->sub_state + d->progress + d->dir + d->sig_list + d->run_always) %
762  h->array_size;
763 }
764 
765 static char TxNonPFCompare(void *data1, uint16_t _len1, void *data2, uint16_t len2)
766 {
767  struct TxNonPFData *d1 = data1;
768  struct TxNonPFData *d2 = data2;
769  return d1->alproto == d2->alproto && d1->sub_state == d2->sub_state &&
770  d1->progress == d2->progress && d1->dir == d2->dir && d1->sig_list == d2->sig_list &&
771  d1->run_always == d2->run_always;
772 }
773 
774 static void TxNonPFFree(void *data)
775 {
776  struct TxNonPFData *d = data;
777  SCFree(d->sigs);
778  SCFree(d);
779 }
780 
781 static int TxNonPFAddSig(DetectEngineCtx *de_ctx, HashListTable *tx_engines_hash,
782  const AppProto alproto, const uint8_t sub_state, const int dir, const uint8_t progress,
783  const int sig_list, const char *name, const Signature *s, const bool run_always)
784 {
785  const uint32_t max_sids = DetectEngineGetMaxSigId(de_ctx);
786 
787  struct TxNonPFData lookup = {
788  .alproto = alproto,
789  .sub_state = sub_state,
790  .dir = dir,
791  .progress = progress,
792  .sig_list = sig_list,
793  .run_always = run_always,
794  .sigs_cnt = 0,
795  .sigs = NULL,
796  .engine_name = NULL,
797  };
798  struct TxNonPFData *e = HashListTableLookup(tx_engines_hash, &lookup, 0);
799  if (e != NULL) {
800  bool found = false;
801  // avoid adding same sid multiple times
802  for (uint32_t y = 0; y < e->sigs_cnt; y++) {
803  if (e->sigs[y].sid == s->iid) {
804  found = true;
805  break;
806  }
807  }
808  if (!found) {
809  BUG_ON(e->sigs_cnt == max_sids);
810  e->sigs[e->sigs_cnt].sid = s->iid;
811  e->sigs[e->sigs_cnt].value = alproto;
812  e->sigs_cnt++;
813  }
814  return 0;
815  }
816 
817  struct TxNonPFData *add = SCCalloc(1, sizeof(*add));
818  if (add == NULL) {
819  return -1;
820  }
821  add->dir = dir;
822  add->sub_state = sub_state;
823  add->alproto = alproto;
824  add->progress = progress;
825  add->sig_list = sig_list;
826  add->run_always = run_always;
827  add->sigs = SCCalloc(max_sids, sizeof(struct PrefilterNonPFDataSig));
828  if (add->sigs == NULL) {
829  SCFree(add);
830  return -1;
831  }
832  add->sigs_cnt = 0;
833  add->sigs[add->sigs_cnt].sid = s->iid;
834  add->sigs[add->sigs_cnt].value = alproto;
835  add->sigs_cnt++;
836 
837  char engine_name[128];
838  /* the id-to-name lookup can return null for a state id outside
839  * the protocol's table (e.g. the ssh completion state); a null
840  * %s argument is UB and would register a "(null)" engine name */
841  snprintf(engine_name, sizeof(engine_name), "%s:%s:non_pf:%s", AppProtoToString(alproto),
842  name ? name : "unknown", dir == 0 ? "toserver" : "toclient");
843  char *engine_name_heap = SCStrdup(engine_name);
844  if (engine_name_heap == NULL) {
845  SCFree(add->sigs);
846  SCFree(add);
847  return -1;
848  }
849  int result = HashTableAdd(
850  de_ctx->non_pf_engine_names, engine_name_heap, (uint16_t)strlen(engine_name_heap));
851  if (result != 0) {
852  SCFree(add->sigs);
853  SCFree(add);
854  return -1;
855  }
856 
857  add->engine_name = engine_name_heap;
858  SCLogDebug("engine_name_heap %s", engine_name_heap);
859 
860  int ret = HashListTableAdd(tx_engines_hash, add, 0);
861  if (ret != 0) {
862  SCFree(add->sigs);
863  SCFree(add);
864  return -1;
865  }
866 
867  return 0;
868 }
869 
870 /** \internal
871  * \brief setup non-prefilter rules in special "non-prefilter" engines that are registered in the
872  * prefilter logic.
873  *
874  * \retval 0 ok
875  * \retval -1 error
876  */
877 static int SetupNonPrefilter(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
878 {
879  const uint32_t max_sids = DetectEngineGetMaxSigId(de_ctx);
880  SCLogDebug("max_sids %u", max_sids);
881  struct PrefilterNonPFDataSig *pkt_non_pf_array = SCCalloc(max_sids, sizeof(*pkt_non_pf_array));
882  if (pkt_non_pf_array == NULL) {
883  return -1;
884  }
885  uint32_t pkt_non_pf_array_size = 0;
886  struct PrefilterNonPFDataSig *frame_non_pf_array =
887  SCCalloc(max_sids, sizeof(*frame_non_pf_array));
888  if (frame_non_pf_array == NULL) {
889  SCFree(pkt_non_pf_array);
890  return -1;
891  }
892  uint32_t frame_non_pf_array_size = 0;
893 
894  struct PrefilterNonPFDataSig *pkt_hook_flow_start_non_pf_array =
895  SCCalloc(max_sids, sizeof(*pkt_hook_flow_start_non_pf_array));
896  if (pkt_hook_flow_start_non_pf_array == NULL) {
897  SCFree(pkt_non_pf_array);
898  SCFree(frame_non_pf_array);
899  return -1;
900  }
901  uint32_t pkt_hook_flow_start_non_pf_array_size = 0;
902  SignatureMask pkt_hook_flow_start_mask = 0;
903  bool pkt_hook_flow_start_mask_init = false;
904 
905  HashListTable *tx_engines_hash =
906  HashListTableInit(256, TxNonPFHash, TxNonPFCompare, TxNonPFFree);
907  if (tx_engines_hash == NULL) {
908  SCFree(pkt_non_pf_array);
909  SCFree(pkt_hook_flow_start_non_pf_array);
910  SCFree(frame_non_pf_array);
911  return -1;
912  }
913 
914  if (de_ctx->non_pf_engine_names == NULL) {
916  HashTableInit(512, NonPFNamesHash, NonPFNamesCompare, NonPFNamesFree);
917  if (de_ctx->non_pf_engine_names == NULL) {
918  SCFree(pkt_non_pf_array);
919  SCFree(pkt_hook_flow_start_non_pf_array);
920  SCFree(frame_non_pf_array);
921  HashListTableFree(tx_engines_hash);
922  return -1;
923  }
924  }
925 
926  SignatureMask pkt_mask = 0;
927  bool pkt_mask_init = false;
928 #ifdef NONPF_PKT_STATS
929  uint32_t nonpf_pkt_alproto = 0;
930  uint32_t nonpf_pkt_dsize = 0;
931  uint32_t nonpf_pkt_dport = 0;
932 #endif
933  const int app_events_list_id = DetectBufferTypeGetByName("app-layer-events");
934  SCLogDebug("app_events_list_id %d", app_events_list_id);
935  const int app_state_list_id = DetectBufferTypeGetByName("app-layer-state");
936  SCLogDebug("app_state_list_id %d", app_state_list_id);
937  for (uint32_t sig = 0; sig < sgh->init->sig_cnt; sig++) {
938  Signature *s = sgh->init->match_array[sig];
939  if (s == NULL)
940  continue;
941  SCLogDebug("checking sid %u for non-prefilter", s->id);
942  if (s->init_data->mpm_sm != NULL && (s->flags & SIG_FLAG_MPM_NEG) == 0)
943  continue;
944  if (s->init_data->prefilter_sm != NULL)
945  continue;
947  continue;
948  SCLogDebug("setting up sid %u for non-prefilter", s->id);
949 
950  uint8_t frame_type = 0; /**< only a single type per rule */
951  bool tx_non_pf = false;
952  bool frame_non_pf = false;
953  bool pkt_non_pf = false;
954 
957  // TODO code duplication with regular pkt case below
958 
959  /* for pkt non prefilter, we have some space in the structure,
960  * so we can squeeze another filter */
961  uint8_t type;
962  uint16_t value;
963  if ((s->flags & SIG_FLAG_DSIZE) && s->dsize_mode == DETECT_UINT_EQ) {
964  SCLogDebug("dsize extra match");
965  type = 2;
966  value = s->dsize_low;
967  } else if (s->dp != NULL && s->dp->next == NULL && s->dp->port == s->dp->port2) {
968  type = 1;
969  value = s->dp->port;
970  } else {
971  type = 0;
972  value = s->alproto;
973  }
974  pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].sid = s->iid;
975  pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].value = value;
976  pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].type = type;
977  pkt_hook_flow_start_non_pf_array[pkt_hook_flow_start_non_pf_array_size].pkt.sig_mask =
978  s->mask;
979  pkt_hook_flow_start_non_pf_array_size++;
980 
981  if (pkt_hook_flow_start_mask_init) {
982  pkt_hook_flow_start_mask &= s->mask;
983  } else {
984  pkt_hook_flow_start_mask = s->mask;
985  pkt_hook_flow_start_mask_init = true;
986  }
987 
988  SCLogDebug("flow_start hook");
989  continue; // done for this sig
990  }
991 
992  /* special case: insert sigs at hook before Signature::app_progress_hook for the HOOK_LTE
993  * case: we need a addition per hook to make sure that the sig is called when needed. For
994  * hook 0 it could have a preceding rule that makes sure this sig isn't triggered, but then
995  * for hook 1 we would need to be called. */
996  if (s->flags & SIG_FLAG_FW_HOOK_LTE) {
997  for (uint8_t state = 0; state < s->app_progress_hook; state++) {
998  SCLogDebug("handle HOOK %u LTE", state);
999  const int dir = (s->flags & SIG_FLAG_TOSERVER) ? 0 : 1;
1000  const uint8_t sub_state = s->init_data->hook.t.app.sub_state;
1001  const char *pname = DetectEngineAppHookToName(
1002  s->alproto, sub_state, state, dir == 0 ? STREAM_TOSERVER : STREAM_TOCLIENT);
1003  if (pname == NULL) {
1004  goto error;
1005  }
1006  const uint8_t direction = dir == 0 ? STREAM_TOSERVER : STREAM_TOCLIENT;
1007  const int sm_list =
1008  DetectEngineAppHookToSmlist(s->alproto, sub_state, state, direction);
1009  if (TxNonPFAddSig(de_ctx, tx_engines_hash, s->alproto, sub_state, dir, state,
1010  sm_list, pname, s, false) != 0) {
1011  goto error;
1012  }
1013  tx_non_pf = true;
1014  }
1015  }
1016 
1017  for (uint32_t x = 0; x < s->init_data->buffer_index; x++) {
1018  const int list_id = s->init_data->buffers[x].id;
1019  const DetectBufferType *buf = DetectEngineBufferTypeGetById(de_ctx, list_id);
1020  if (buf == NULL)
1021  continue;
1022  /* for now, exclude app-layer-events, as they are not tied to a specific
1023  * progress value like other keywords. */
1024  SCLogDebug("list_id %d buf %p", list_id, buf);
1025  if (list_id == app_events_list_id)
1026  continue;
1027  if (buf->packet) {
1028  SCLogDebug("packet buf");
1029  /* packet is handled below */
1030  pkt_non_pf = true;
1031  } else if (buf->frame) {
1033  f != NULL; f = f->next) {
1034  if (!((((s->flags & SIG_FLAG_TOSERVER) != 0 && f->dir == 0) ||
1035  ((s->flags & SIG_FLAG_TOCLIENT) != 0 && f->dir == 1)) &&
1036  list_id == (int)f->sm_list &&
1037  AppProtoEquals(s->alproto, f->alproto)))
1038  continue;
1039 
1040  SCLogDebug("frame '%s' type %u", buf->name, f->type);
1041  frame_type = f->type;
1042  frame_non_pf = true;
1043 
1044  frame_non_pf_array[frame_non_pf_array_size].sid = s->iid;
1045  frame_non_pf_array[frame_non_pf_array_size].value = s->alproto;
1046  frame_non_pf_array[frame_non_pf_array_size].frame.type = frame_type;
1047  frame_non_pf_array_size++;
1048  break;
1049  }
1050 
1051  } else {
1052  SCLogDebug("x %u list_id %d", x, list_id);
1054  app != NULL; app = app->next) {
1055  SCLogDebug("app %p proto %s list_d %d sig dir %0x", app,
1056  AppProtoToString(app->alproto), app->sm_list,
1058 
1059  /* extra strict alproto check for SIGNATURE_HOOK_TYPE_APP,
1060  * just like with mpm and per rule app engine. */
1062  if (!AppProtoEqualsStrict(s->alproto, app->alproto))
1063  continue;
1064  }
1065 
1066  /* skip if:
1067  * - not in our dir
1068  * - not our list
1069  * - app proto mismatch. Both sig and app can have proto or unknown */
1070  if (!((((s->flags & SIG_FLAG_TOSERVER) != 0 && app->dir == 0) ||
1071  ((s->flags & SIG_FLAG_TOCLIENT) != 0 && app->dir == 1)) &&
1072  list_id == (int)app->sm_list &&
1073  (s->alproto == ALPROTO_UNKNOWN || app->alproto == ALPROTO_UNKNOWN ||
1074  AppProtoEquals(s->alproto, app->alproto))))
1075  continue;
1076 
1077  int sig_list = 0;
1078  if (list_id == app_state_list_id)
1079  sig_list = app_state_list_id;
1080  /* buffers marked run-always (stateful keywords) must be
1081  * revisited as the tx advances. */
1082  const bool run_always = buf != NULL && buf->run_always;
1083  const uint8_t sub_state = app->sub_state;
1084  if (TxNonPFAddSig(de_ctx, tx_engines_hash, app->alproto, sub_state, app->dir,
1085  app->progress, sig_list, buf->name, s, run_always) != 0) {
1086  goto error;
1087  }
1088  tx_non_pf = true;
1089  }
1090  }
1091  if (frame_non_pf) {
1092  // we found a frame, do not look for other buffers
1093  // which may include the same frame + transform
1094  // but we only want 1 per signature
1095  break;
1096  }
1097  }
1098  /* handle hook only rules */
1099  if (!tx_non_pf && s->init_data->hook.type == SIGNATURE_HOOK_TYPE_APP) {
1100  const int dir = (s->flags & SIG_FLAG_TOSERVER) ? 0 : 1;
1101  const char *pname = AppLayerParserGetStateNameById(IPPROTO_TCP, // TODO
1102  s->alproto, s->init_data->hook.t.app.app_progress,
1103  dir == 0 ? STREAM_TOSERVER : STREAM_TOCLIENT);
1104 
1105  uint8_t sub_state = s->init_data->hook.t.app.sub_state;
1106  if (TxNonPFAddSig(de_ctx, tx_engines_hash, s->alproto, sub_state, dir,
1107  s->init_data->hook.t.app.app_progress, s->init_data->hook.sm_list, pname, s,
1108  false) != 0) {
1109  goto error;
1110  }
1111  tx_non_pf = true;
1112  }
1113  /* mark as prefiltered as the sig is now part of a engine */
1114  // s->flags |= SIG_FLAG_PREFILTER;
1115  // TODO doesn't work for sigs that are in multiple sgh's
1116 
1117  /* default to pkt if there was no tx or frame match */
1118  if (!(tx_non_pf || frame_non_pf)) {
1119  if (!pkt_non_pf) {
1120  SCLogDebug("not frame, not tx, so pkt");
1121  }
1122  pkt_non_pf = true;
1123  }
1124 
1125  SCLogDebug("setting up sid %u for non-prefilter: %s", s->id,
1126  tx_non_pf ? "tx engine" : (frame_non_pf ? "frame engine" : "pkt engine"));
1127 
1128  if (pkt_non_pf) {
1129  /* for pkt non prefilter, we have some space in the structure,
1130  * so we can squeeze another filter */
1131  uint8_t type;
1132  uint16_t value;
1133  if ((s->flags & SIG_FLAG_DSIZE) && s->dsize_mode == DETECT_UINT_EQ) {
1134  SCLogDebug("dsize extra match");
1135  type = 2;
1136  value = s->dsize_low;
1137 #ifdef NONPF_PKT_STATS
1138  nonpf_pkt_dsize++;
1139 #endif
1140  } else if (s->dp != NULL && s->dp->next == NULL && s->dp->port == s->dp->port2) {
1141  type = 1;
1142  value = s->dp->port;
1143 #ifdef NONPF_PKT_STATS
1144  nonpf_pkt_dport++;
1145 #endif
1146  } else {
1147  type = 0;
1148  value = s->alproto;
1149 #ifdef NONPF_PKT_STATS
1150  nonpf_pkt_alproto++;
1151 #endif
1152  }
1153 
1154  pkt_non_pf_array[pkt_non_pf_array_size].sid = s->iid;
1155  pkt_non_pf_array[pkt_non_pf_array_size].value = value;
1156  pkt_non_pf_array[pkt_non_pf_array_size].type = type;
1157  pkt_non_pf_array[pkt_non_pf_array_size].pkt.sig_mask = s->mask;
1158  pkt_non_pf_array_size++;
1159 
1160  if (pkt_mask_init) {
1161  pkt_mask &= s->mask;
1162  } else {
1163  pkt_mask = s->mask;
1164  pkt_mask_init = true;
1165  }
1166  SCLogDebug("s->id %u added", s->id);
1167  }
1168  }
1169 
1170  /* for each unique sig set, add an engine */
1171  for (HashListTableBucket *b = HashListTableGetListHead(tx_engines_hash); b != NULL;
1172  b = HashListTableGetListNext(b)) {
1173  struct TxNonPFData *t = HashListTableGetListData(b);
1174  SCLogDebug("%s engine for %s hook %d has %u non-pf sigs",
1175  t->dir == 0 ? "toserver" : "toclient", AppProtoToString(t->alproto), t->progress,
1176  t->sigs_cnt);
1177 
1178  if (((sgh->init->direction & SIG_FLAG_TOSERVER) && t->dir == 1) ||
1179  ((sgh->init->direction & SIG_FLAG_TOCLIENT) && t->dir == 0)) {
1180  SCLogDebug("skipped");
1181  continue;
1182  }
1183 
1184  DEBUG_VALIDATE_BUG_ON(t->progress > INT8_MAX);
1185  int8_t engine_progress = (int8_t)t->progress;
1186  if (t->sig_list == app_state_list_id) {
1187  /* app-layer-state engines use the -1 "run every update" sentinel;
1188  * they are proto-agnostic (ALPROTO_UNKNOWN), which that path
1189  * requires. */
1190  SCLogDebug("engine %s for state list, run always", t->engine_name);
1191  engine_progress = -1;
1192  }
1193 
1194  struct PrefilterNonPFDataTx *data =
1195  SCCalloc(1, sizeof(*data) + t->sigs_cnt * sizeof(data->array[0]));
1196  if (data == NULL)
1197  goto error;
1198  data->size = t->sigs_cnt;
1199  for (uint32_t i = 0; i < t->sigs_cnt; i++) {
1200  data->array[i] = t->sigs[i].sid;
1201  }
1202  if (PrefilterAppendTxEngineSubState(de_ctx, sgh, PrefilterTxNonPF, t->alproto, t->sub_state,
1203  engine_progress, (void *)data, PrefilterNonPFDataFree, t->engine_name) < 0) {
1204  SCFree(data);
1205  goto error;
1206  }
1207  if (t->run_always) {
1208  /* A stateful keyword must be revisited as the tx advances. Keep
1209  * its real progress (so the progress bookkeeping runs and the
1210  * proto-agnostic -1 invariant holds) and carry an explicit flag. */
1212  while (tail->next != NULL)
1213  tail = tail->next;
1214  tail->run_always = true;
1215  }
1216  }
1217  HashListTableFree(tx_engines_hash);
1218  tx_engines_hash = NULL;
1219 
1220  if (pkt_non_pf_array_size) {
1221  SCLogDebug("pkt_non_pf_array_size %u", pkt_non_pf_array_size);
1222  struct PrefilterNonPFData *data =
1223  SCCalloc(1, sizeof(*data) + pkt_non_pf_array_size * sizeof(data->array[0]));
1224  if (data == NULL)
1225  goto error;
1226  data->size = pkt_non_pf_array_size;
1227  memcpy((uint8_t *)&data->array, pkt_non_pf_array,
1228  pkt_non_pf_array_size * sizeof(data->array[0]));
1229  enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
1230  if (PrefilterAppendEngine(de_ctx, sgh, PrefilterPktNonPF, pkt_mask, hook, (void *)data,
1231  PrefilterNonPFDataFree, "packet:non_pf") < 0) {
1232  SCFree(data);
1233  goto error;
1234  }
1235  }
1236  if (pkt_hook_flow_start_non_pf_array_size) {
1237  struct PrefilterNonPFData *data = SCCalloc(
1238  1, sizeof(*data) + pkt_hook_flow_start_non_pf_array_size * sizeof(data->array[0]));
1239  if (data == NULL)
1240  goto error;
1241  data->size = pkt_hook_flow_start_non_pf_array_size;
1242  memcpy((uint8_t *)&data->array, pkt_hook_flow_start_non_pf_array,
1243  pkt_hook_flow_start_non_pf_array_size * sizeof(data->array[0]));
1244  SCLogDebug("packet:flow_start:non_pf added with %u rules", data->size);
1246  if (PrefilterAppendEngine(de_ctx, sgh,
1247  PrefilterPktNonPFHookFlowStart, // TODO no longer needed to have a dedicated
1248  // callback
1249  pkt_hook_flow_start_mask, hook, (void *)data, PrefilterNonPFDataFree,
1250  "packet:flow_start:non_pf") < 0) {
1251  SCFree(data);
1252  goto error;
1253  }
1254  }
1255  if (frame_non_pf_array_size) {
1256  SCLogDebug("%u frame non-pf sigs", frame_non_pf_array_size);
1257  struct PrefilterNonPFData *data =
1258  SCCalloc(1, sizeof(*data) + frame_non_pf_array_size * sizeof(data->array[0]));
1259  if (data == NULL)
1260  goto error;
1261  data->size = frame_non_pf_array_size;
1262  memcpy((uint8_t *)&data->array, frame_non_pf_array,
1263  frame_non_pf_array_size * sizeof(data->array[0]));
1264  if (PrefilterAppendFrameEngine(de_ctx, sgh, PrefilterFrameNonPF, ALPROTO_UNKNOWN,
1265  FRAME_ANY_TYPE, (void *)data, PrefilterNonPFDataFree, "frame:non_pf") < 0) {
1266  SCFree(data);
1267  goto error;
1268  }
1269  }
1270 
1271  SCFree(pkt_hook_flow_start_non_pf_array);
1272  pkt_hook_flow_start_non_pf_array = NULL;
1273  SCFree(pkt_non_pf_array);
1274  pkt_non_pf_array = NULL;
1275  SCFree(frame_non_pf_array);
1276  frame_non_pf_array = NULL;
1277  return 0;
1278 
1279 error:
1280  if (tx_engines_hash) {
1281  HashListTableFree(tx_engines_hash);
1282  }
1283  SCFree(pkt_hook_flow_start_non_pf_array);
1284  SCFree(pkt_non_pf_array);
1285  SCFree(frame_non_pf_array);
1286  return -1;
1287 }
1288 
1290 {
1291  int r = PatternMatchPrepareGroup(de_ctx, sgh);
1292  if (r != 0) {
1293  FatalError("failed to set up pattern matching");
1294  }
1295 
1296  /* set up engines if needed - when prefilter is set to auto we run
1297  * all engines, otherwise only those that have been forced by the
1298  * prefilter keyword. */
1300  for (int i = 0; i < DETECT_TBLSIZE; i++) {
1301  if (sigmatch_table[i].SetupPrefilter != NULL &&
1302  (setting == DETECT_PREFILTER_AUTO || de_ctx->sm_types_prefilter[i])) {
1304  }
1305  }
1306 
1307  if (SetupNonPrefilter(de_ctx, sgh) != 0) {
1308  return -1;
1309  }
1310 
1311  /* we have lists of engines in sgh->init now. Lets setup the
1312  * match arrays */
1313  PrefilterEngineList *el;
1314  if (sgh->init->pkt_engines != NULL) {
1315  SCLogDebug("for %p we have %p", sgh, sgh->init->pkt_engines);
1316  uint32_t cnt = 0;
1317  for (el = sgh->init->pkt_engines ; el != NULL; el = el->next) {
1318  cnt++;
1319  }
1320  SCLogDebug("cnt %u", cnt);
1321  sgh->pkt_engines = SCMallocAligned(cnt * sizeof(PrefilterEngine), CLS);
1322  if (sgh->pkt_engines == NULL) {
1323  return -1;
1324  }
1325  memset(sgh->pkt_engines, 0x00, (cnt * sizeof(PrefilterEngine)));
1326 
1327  PrefilterEngine *e = sgh->pkt_engines;
1328  for (el = sgh->init->pkt_engines ; el != NULL; el = el->next) {
1329  e->local_id = el->id;
1330  e->cb.Prefilter = el->Prefilter;
1331  e->ctx.pkt.mask = el->pkt_mask;
1332  // TODO right now we represent the hook in a u8 in the prefilter engine for space
1333  // reasons.
1334  BUG_ON(el->pkt_hook >= 8);
1335  e->ctx.pkt.hook = (uint8_t)el->pkt_hook;
1336  e->pectx = el->pectx;
1337  el->pectx = NULL; // e now owns the ctx
1338  e->gid = el->gid;
1339  if (el->next == NULL) {
1340  e->is_last = true;
1341  }
1342  e++;
1343  }
1344  }
1345  if (sgh->init->payload_engines != NULL) {
1346  uint32_t cnt = 0;
1347  for (el = sgh->init->payload_engines ; el != NULL; el = el->next) {
1348  cnt++;
1349  }
1351  if (sgh->payload_engines == NULL) {
1352  return -1;
1353  }
1354  memset(sgh->payload_engines, 0x00, (cnt * sizeof(PrefilterEngine)));
1355 
1356  PrefilterEngine *e = sgh->payload_engines;
1357  for (el = sgh->init->payload_engines ; el != NULL; el = el->next) {
1358  e->local_id = el->id;
1359  e->cb.Prefilter = el->Prefilter;
1360  e->ctx.pkt.mask = el->pkt_mask;
1361  // TODO right now we represent the hook in a u8 in the prefilter engine for space
1362  // reasons.
1363  BUG_ON(el->pkt_hook >= 8);
1364  e->ctx.pkt.hook = (uint8_t)el->pkt_hook;
1365  e->pectx = el->pectx;
1366  el->pectx = NULL; // e now owns the ctx
1367  e->gid = el->gid;
1368  if (el->next == NULL) {
1369  e->is_last = true;
1370  }
1371  e++;
1372  }
1373  }
1374  if (sgh->init->tx_engines != NULL) {
1375  uint32_t cnt = 0;
1376  for (el = sgh->init->tx_engines ; el != NULL; el = el->next) {
1377  cnt++;
1378  }
1379  sgh->tx_engines = SCMallocAligned(cnt * sizeof(PrefilterEngine), CLS);
1380  if (sgh->tx_engines == NULL) {
1381  return -1;
1382  }
1383  memset(sgh->tx_engines, 0x00, (cnt * sizeof(PrefilterEngine)));
1384 
1385  uint16_t local_id = 0;
1386  PrefilterEngine *e = sgh->tx_engines;
1387  for (el = sgh->init->tx_engines ; el != NULL; el = el->next) {
1388  e->local_id = local_id++;
1389  e->alproto = el->alproto;
1390  e->ctx.app.tx_min_progress = el->tx_min_progress;
1391  e->ctx.app.sub_state = el->sub_state;
1392  e->run_always = el->run_always;
1393  e->cb.PrefilterTx = el->PrefilterTx;
1394  e->pectx = el->pectx;
1395  el->pectx = NULL; // e now owns the ctx
1396  e->gid = el->gid;
1397  e++;
1398  }
1399 
1400  /* sort by tx_min_progress, then alproto, then local_id */
1401  qsort(sgh->tx_engines, local_id, sizeof(PrefilterEngine),
1402  PrefilterSetupRuleGroupSortHelper);
1403  sgh->tx_engines[local_id - 1].is_last = true;
1404  sgh->tx_engines[local_id - 1].is_last_for_progress = true;
1405 
1406  PrefilterEngine *engine;
1407  /* per alproto to set is_last_for_progress per alproto because the inspect
1408  * loop skips over engines that are not the correct alproto */
1409  for (AppProto a = ALPROTO_FAILED + 1; a < g_alproto_max; a++) {
1410  /* loop over sub-states. Protocols not supporting sub-states
1411  * will just use 0. */
1412  const uint8_t max_sub_state = AppLayerParserGetMaxSubState(a);
1413  for (uint8_t sub = 0; sub <= max_sub_state; sub++) {
1414  int last_tx_progress = 0;
1415  bool last_tx_progress_set = false;
1416  PrefilterEngine *prev_engine = NULL;
1417  engine = sgh->tx_engines;
1418  do {
1419  if (engine->ctx.app.sub_state == sub) {
1420  if (engine->ctx.app.tx_min_progress != -1)
1421  BUG_ON(engine->ctx.app.tx_min_progress < last_tx_progress);
1422  if (engine->alproto == a) {
1423  if (last_tx_progress_set &&
1424  engine->ctx.app.tx_min_progress > last_tx_progress) {
1425  if (prev_engine) {
1426  prev_engine->is_last_for_progress = true;
1427  }
1428  }
1429 
1430  last_tx_progress_set = true;
1431  prev_engine = engine;
1432  if (!engine->is_last) {
1433  PrefilterEngine *next_engine = engine + 1;
1434  engine->is_last_for_progress =
1435  (next_engine->ctx.app.sub_state != sub);
1436  }
1437 
1438  } else {
1439  if (prev_engine) {
1440  prev_engine->is_last_for_progress = true;
1441  }
1442  }
1443  last_tx_progress = engine->ctx.app.tx_min_progress;
1444  }
1445  if (engine->is_last)
1446  break;
1447  engine++;
1448  } while (1);
1449  }
1450  }
1451 #ifdef DEBUG
1452  SCLogDebug("sgh %p", sgh);
1453  engine = sgh->tx_engines;
1454  do {
1455  SCLogDebug("engine: gid %u alproto %s sub_state %u tx_min_progress %d is_last %s "
1456  "is_last_for_progress %s",
1457  engine->gid, AppProtoToString(engine->alproto), engine->ctx.app.sub_state,
1458  engine->ctx.app.tx_min_progress, engine->is_last ? "true" : "false",
1459  engine->is_last_for_progress ? "true" : "false");
1460  if (engine->is_last)
1461  break;
1462  engine++;
1463  } while (1);
1464 #endif
1465  }
1466  if (sgh->init->frame_engines != NULL) {
1467  uint32_t cnt = 0;
1468  for (el = sgh->init->frame_engines; el != NULL; el = el->next) {
1469  cnt++;
1470  }
1472  if (sgh->frame_engines == NULL) {
1473  return -1;
1474  }
1475  memset(sgh->frame_engines, 0x00, (cnt * sizeof(PrefilterEngine)));
1476 
1477  PrefilterEngine *e = sgh->frame_engines;
1478  for (el = sgh->init->frame_engines; el != NULL; el = el->next) {
1479  e->local_id = el->id;
1480  e->ctx.frame_type = el->frame_type;
1481  e->cb.PrefilterFrame = el->PrefilterFrame;
1482  e->alproto = el->alproto;
1483  e->pectx = el->pectx;
1484  el->pectx = NULL; // e now owns the ctx
1485  e->gid = el->gid;
1486  if (el->next == NULL) {
1487  e->is_last = true;
1488  }
1489  e++;
1490  }
1491  }
1492 
1493  if (sgh->init->post_rule_match_engines != NULL) {
1494  uint32_t cnt = 0;
1495  for (el = sgh->init->post_rule_match_engines; el != NULL; el = el->next) {
1496  cnt++;
1497  }
1499  if (sgh->post_rule_match_engines == NULL) {
1500  return -1;
1501  }
1502  memset(sgh->post_rule_match_engines, 0x00, (cnt * sizeof(PrefilterEngine)));
1503 
1504  uint16_t local_id = 0;
1506  for (el = sgh->init->post_rule_match_engines; el != NULL; el = el->next) {
1507  e->local_id = local_id++;
1509  e->pectx = el->pectx;
1510  el->pectx = NULL; // e now owns the ctx
1511  e->gid = el->gid;
1512  e->is_last = (el->next == NULL);
1513  e++;
1514  }
1515  SCLogDebug("sgh %p max local_id %u", sgh, local_id);
1516  }
1517 
1518  return 0;
1519 }
1520 
1521 /* hash table for assigning a unique id to each engine type. */
1522 
1523 static uint32_t PrefilterStoreHashFunc(HashListTable *ht, void *data, uint16_t datalen)
1524 {
1525  PrefilterStore *ctx = data;
1526 
1527  uint32_t hash = (uint32_t)strlen(ctx->name);
1528 
1529  for (size_t u = 0; u < strlen(ctx->name); u++) {
1530  hash += ctx->name[u];
1531  }
1532 
1533  hash %= ht->array_size;
1534  return hash;
1535 }
1536 
1537 static char PrefilterStoreCompareFunc(void *data1, uint16_t len1,
1538  void *data2, uint16_t len2)
1539 {
1540  PrefilterStore *ctx1 = data1;
1541  PrefilterStore *ctx2 = data2;
1542  return (strcmp(ctx1->name, ctx2->name) == 0);
1543 }
1544 
1545 static void PrefilterStoreFreeFunc(void *ptr)
1546 {
1547  SCFree(ptr);
1548 }
1549 
1551 {
1552  if (de_ctx->prefilter_hash_table != NULL) {
1554  }
1555 }
1556 
1558 {
1560 
1562  PrefilterStoreHashFunc,
1563  PrefilterStoreCompareFunc,
1564  PrefilterStoreFreeFunc);
1566 }
1567 
1568 static int PrefilterStoreGetId(DetectEngineCtx *de_ctx,
1569  const char *name, void (*FreeFunc)(void *))
1570 {
1571  PrefilterStore ctx = { name, FreeFunc, 0 };
1572 
1574 
1575  SCLogDebug("looking up %s", name);
1576 
1578  if (rctx != NULL) {
1579  return rctx->id;
1580  }
1581 
1582  PrefilterStore *actx = SCCalloc(1, sizeof(*actx));
1583  if (actx == NULL) {
1584  return -1;
1585  }
1586 
1587  actx->name = name;
1588  actx->FreeFunc = FreeFunc;
1589  actx->id = de_ctx->prefilter_id++;
1590  SCLogDebug("prefilter engine %s has profile id %u", actx->name, actx->id);
1591 
1592  int ret = HashListTableAdd(de_ctx->prefilter_hash_table, actx, 0);
1593  if (ret != 0) {
1594  SCFree(actx);
1595  return -1;
1596  }
1597 
1598  int r = actx->id;
1599  return r;
1600 }
1601 
1602 /** \warning slow */
1603 static const PrefilterStore *PrefilterStoreGetStore(const DetectEngineCtx *de_ctx,
1604  const uint32_t id)
1605 {
1606 
1607  const PrefilterStore *store = NULL;
1608  if (de_ctx->prefilter_hash_table != NULL) {
1610  for ( ; hb != NULL; hb = HashListTableGetListNext(hb)) {
1612  if (ctx->id == id) {
1613  store = ctx;
1614  break;
1615  }
1616  }
1617  }
1618  return store;
1619 }
1620 
1621 #include "util-print.h"
1622 
1623 typedef struct PrefilterMpmCtx {
1624  int list_id;
1625  union {
1628  };
1629  const MpmCtx *mpm_ctx;
1632 
1633 /** \brief Generic Mpm prefilter callback for simple InspectionSingleBufferGetDataPtr
1634  *
1635  * \param det_ctx detection engine thread ctx
1636  * \param p packet to inspect
1637  * \param f flow to inspect
1638  * \param txv tx to inspect
1639  * \param pectx inspection context
1640  */
1641 static void PrefilterMpmTxSingle(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
1642  Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
1643 {
1644  SCEnter();
1645 
1646  const PrefilterMpmCtx *ctx = (const PrefilterMpmCtx *)pectx;
1647  const MpmCtx *mpm_ctx = ctx->mpm_ctx;
1648  SCLogDebug("running on list %d", ctx->list_id);
1649 
1651  det_ctx, ctx->transforms, f, flags, txv, ctx->list_id, ctx->GetDataSingle);
1652  if (buffer == NULL)
1653  return;
1654 
1655  const uint32_t data_len = buffer->inspect_len;
1656  const uint8_t *data = buffer->inspect;
1657 
1658  SCLogDebug("mpm'ing buffer:");
1659  // PrintRawDataFp(stdout, data, data_len);
1660 
1661  if (data != NULL && data_len >= mpm_ctx->minlen) {
1662  (void)mpm_table[mpm_ctx->mpm_type].Search(
1663  mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, data, data_len);
1664  PREFILTER_PROFILING_ADD_BYTES(det_ctx, data_len);
1665  }
1666 }
1667 
1668 /** \brief Generic Mpm prefilter callback
1669  *
1670  * \param det_ctx detection engine thread ctx
1671  * \param p packet to inspect
1672  * \param f flow to inspect
1673  * \param txv tx to inspect
1674  * \param pectx inspection context
1675  */
1676 static void PrefilterMpm(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f,
1677  void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
1678 {
1679  SCEnter();
1680 
1681  const PrefilterMpmCtx *ctx = (const PrefilterMpmCtx *)pectx;
1682  const MpmCtx *mpm_ctx = ctx->mpm_ctx;
1683  SCLogDebug("running on list %d", ctx->list_id);
1684 
1685  InspectionBuffer *buffer = ctx->GetData(det_ctx, ctx->transforms, f, flags, txv, ctx->list_id);
1686  if (buffer == NULL)
1687  return;
1688 
1689  const uint32_t data_len = buffer->inspect_len;
1690  const uint8_t *data = buffer->inspect;
1691 
1692  SCLogDebug("mpm'ing buffer:");
1693  //PrintRawDataFp(stdout, data, data_len);
1694 
1695  if (data != NULL && data_len >= mpm_ctx->minlen) {
1696  (void)mpm_table[mpm_ctx->mpm_type].Search(
1697  mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, data, data_len);
1698  PREFILTER_PROFILING_ADD_BYTES(det_ctx, data_len);
1699  }
1700 }
1701 
1702 static void PrefilterGenericMpmFree(void *ptr)
1703 {
1704  SCFree(ptr);
1705 }
1706 
1708  const DetectBufferMpmRegistry *mpm_reg, int list_id)
1709 {
1710  SCEnter();
1711  PrefilterMpmCtx *pectx = SCCalloc(1, sizeof(*pectx));
1712  if (pectx == NULL)
1713  return -1;
1714  pectx->list_id = list_id;
1715  pectx->GetData = mpm_reg->app_v2.GetData;
1716  pectx->mpm_ctx = mpm_ctx;
1717  pectx->transforms = &mpm_reg->transforms;
1718 
1719  SCLogDebug("mpm_reg %s sub_state %u", mpm_reg->name, mpm_reg->app_v2.sub_state);
1720  int r = PrefilterAppendTxEngineSubState(de_ctx, sgh, PrefilterMpm, mpm_reg->app_v2.alproto,
1721  mpm_reg->app_v2.sub_state, mpm_reg->app_v2.tx_min_progress, pectx,
1722  PrefilterGenericMpmFree, mpm_reg->pname);
1723  if (r != 0) {
1724  SCFree(pectx);
1725  }
1726  return r;
1727 }
1728 
1730  const DetectBufferMpmRegistry *mpm_reg, int list_id)
1731 {
1732  SCEnter();
1733  PrefilterMpmCtx *pectx = SCCalloc(1, sizeof(*pectx));
1734  if (pectx == NULL)
1735  return -1;
1736  pectx->list_id = list_id;
1737  pectx->GetDataSingle = mpm_reg->app_v2.GetDataSingle;
1738  pectx->mpm_ctx = mpm_ctx;
1739  pectx->transforms = &mpm_reg->transforms;
1740 
1741  SCLogDebug("mpm_reg %s sub_state %u", mpm_reg->name, mpm_reg->app_v2.sub_state);
1742  int r = PrefilterAppendTxEngineSubState(de_ctx, sgh, PrefilterMpmTxSingle,
1743  mpm_reg->app_v2.alproto, mpm_reg->app_v2.sub_state, mpm_reg->app_v2.tx_min_progress,
1744  pectx, PrefilterGenericMpmFree, mpm_reg->pname);
1745  if (r != 0) {
1746  SCFree(pectx);
1747  }
1748  return r;
1749 }
1750 
1751 static void PrefilterMultiGenericMpmFree(void *ptr)
1752 {
1753  // PrefilterMpmListId
1754  SCFree(ptr);
1755 }
1756 
1757 static void PrefilterMultiMpm(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f,
1758  void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
1759 {
1760  SCEnter();
1761 
1762  const PrefilterMpmListId *ctx = (const PrefilterMpmListId *)pectx;
1763  const MpmCtx *mpm_ctx = ctx->mpm_ctx;
1764  SCLogDebug("running on list %d", ctx->list_id);
1765  uint32_t local_id = 0;
1766 
1767  do {
1768  // loop until we get a NULL
1770  det_ctx, ctx->transforms, f, flags, txv, ctx->list_id, local_id, ctx->GetData);
1771  if (buffer == NULL)
1772  break;
1773 
1774  if (buffer->inspect_len >= mpm_ctx->minlen) {
1775  (void)mpm_table[mpm_ctx->mpm_type].Search(
1776  mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, buffer->inspect, buffer->inspect_len);
1777  PREFILTER_PROFILING_ADD_BYTES(det_ctx, buffer->inspect_len);
1778  }
1779 
1780  local_id++;
1781  } while (1);
1782 }
1783 
1785  const DetectBufferMpmRegistry *mpm_reg, int list_id)
1786 {
1787  SCEnter();
1788  PrefilterMpmListId *pectx = SCCalloc(1, sizeof(*pectx));
1789  if (pectx == NULL)
1790  return -1;
1791  pectx->list_id = list_id;
1792  pectx->GetData = mpm_reg->app_v2.GetMultiData;
1793  pectx->mpm_ctx = mpm_ctx;
1794  pectx->transforms = &mpm_reg->transforms;
1795 
1796  SCLogDebug("mpm_reg %s sub_state %u", mpm_reg->name, mpm_reg->app_v2.sub_state);
1797  int r = PrefilterAppendTxEngineSubState(de_ctx, sgh, PrefilterMultiMpm, mpm_reg->app_v2.alproto,
1798  mpm_reg->app_v2.sub_state, mpm_reg->app_v2.tx_min_progress, pectx,
1799  PrefilterMultiGenericMpmFree, mpm_reg->pname);
1800  if (r != 0) {
1801  SCFree(pectx);
1802  }
1803  return r;
1804 }
1805 
1806 /* generic mpm for pkt engines */
1807 
1808 typedef struct PrefilterMpmPktCtx {
1809  int list_id;
1811  const MpmCtx *mpm_ctx;
1814 
1815 /** \brief Generic Mpm prefilter callback
1816  *
1817  * \param det_ctx detection engine thread ctx
1818  * \param p packet to inspect
1819  * \param f flow to inspect
1820  * \param txv tx to inspect
1821  * \param pectx inspection context
1822  */
1823 static void PrefilterMpmPkt(DetectEngineThreadCtx *det_ctx,
1824  Packet *p, const void *pectx)
1825 {
1826  SCEnter();
1827 
1828  const PrefilterMpmPktCtx *ctx = (const PrefilterMpmPktCtx *)pectx;
1829  const MpmCtx *mpm_ctx = ctx->mpm_ctx;
1830  SCLogDebug("running on list %d", ctx->list_id);
1831 
1832  InspectionBuffer *buffer = ctx->GetData(det_ctx, ctx->transforms,
1833  p, ctx->list_id);
1834  if (buffer == NULL)
1835  return;
1836 
1837  const uint32_t data_len = buffer->inspect_len;
1838  const uint8_t *data = buffer->inspect;
1839 
1840  SCLogDebug("mpm'ing buffer:");
1841  //PrintRawDataFp(stdout, data, data_len);
1842 
1843  if (data != NULL && data_len >= mpm_ctx->minlen) {
1844  (void)mpm_table[mpm_ctx->mpm_type].Search(
1845  mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, data, data_len);
1846  PREFILTER_PROFILING_ADD_BYTES(det_ctx, data_len);
1847  }
1848 }
1849 
1850 static void PrefilterMpmPktFree(void *ptr)
1851 {
1852  SCFree(ptr);
1853 }
1854 
1856  const DetectBufferMpmRegistry *mpm_reg, int list_id)
1857 {
1858  SCEnter();
1859  PrefilterMpmPktCtx *pectx = SCCalloc(1, sizeof(*pectx));
1860  if (pectx == NULL)
1861  return -1;
1862  pectx->list_id = list_id;
1863  pectx->GetData = mpm_reg->pkt_v1.GetData;
1864  pectx->mpm_ctx = mpm_ctx;
1865  pectx->transforms = &mpm_reg->transforms;
1866 
1867  enum SignatureHookPkt hook = SIGNATURE_HOOK_PKT_NOT_SET; // TODO review
1868  int r = PrefilterAppendEngine(
1869  de_ctx, sgh, PrefilterMpmPkt, 0, hook, pectx, PrefilterMpmPktFree, mpm_reg->pname);
1870  if (r != 0) {
1871  SCFree(pectx);
1872  }
1873  return r;
1874 }
1875 
1876 #define QUEUE_STEP 16
1879  DetectEngineThreadCtx *det_ctx, const Signature *s, const int type, const uint32_t value)
1880 {
1881  if (det_ctx->post_rule_work_queue.q == NULL) {
1882  det_ctx->post_rule_work_queue.q =
1884  if (det_ctx->post_rule_work_queue.q == NULL) {
1886  return;
1887  }
1889  } else if (det_ctx->post_rule_work_queue.len == det_ctx->post_rule_work_queue.size) {
1890  void *ptr = SCRealloc(
1891  det_ctx->post_rule_work_queue.q, (det_ctx->post_rule_work_queue.size + QUEUE_STEP) *
1892  sizeof(PostRuleMatchWorkQueueItem));
1893  if (ptr == NULL) {
1895  return;
1896  }
1897  det_ctx->post_rule_work_queue.q = ptr;
1898  det_ctx->post_rule_work_queue.size += QUEUE_STEP;
1899  }
1901  det_ctx->post_rule_work_queue.q[det_ctx->post_rule_work_queue.len].value = value;
1902 #ifdef DEBUG
1903  det_ctx->post_rule_work_queue.q[det_ctx->post_rule_work_queue.len].id = s->iid;
1904 #endif
1905  det_ctx->post_rule_work_queue.len++;
1906  SCLogDebug("det_ctx->post_rule_work_queue.len %u", det_ctx->post_rule_work_queue.len);
1907 }
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:56
PrefilterGenericMpmPktRegister
int PrefilterGenericMpmPktRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:1855
detect-engine-uint.h
PrefilterEngineList_::frame_type
uint8_t frame_type
Definition: detect.h:1618
SigGroupHead_::tx_engines
PrefilterEngine * tx_engines
Definition: detect.h:1736
DetectEngineAppInspectionEngine_
Definition: detect.h:420
DetectGetMultiData
InspectionBuffer * DetectGetMultiData(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, const int list_id, uint32_t index, InspectionMultiBufferGetDataPtr GetBuf)
Definition: detect-engine.c:2357
Packet_::proto
uint8_t proto
Definition: decode.h:538
util-hash-string.h
PrefilterAppendTxEngineSubState
int PrefilterAppendTxEngineSubState(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterTxFn PrefilterTxFunc, AppProto alproto, uint8_t sub_state, const int8_t tx_min_progress, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Definition: detect-engine-prefilter.c:381
DetectTransaction_::tx_data_ptr
struct AppLayerTxData * tx_data_ptr
Definition: detect-engine-prefilter.h:34
PrefilterEngineList_::Prefilter
PrefilterPktFn Prefilter
Definition: detect.h:1630
MpmCtx_::mpm_type
uint8_t mpm_type
Definition: util-mpm.h:113
detect-engine.h
PrefilterNonPFDataSig::sid
uint32_t sid
Definition: detect-engine-prefilter.c:576
PrefilterEngineList_::sub_state
uint8_t sub_state
Definition: detect.h:1622
DetectEngineAppHookToName
const char * DetectEngineAppHookToName(const AppProto p, const uint8_t sub_state, const uint8_t state, const uint8_t direction)
Definition: detect-engine.c:846
PrefilterEngine_::PrefilterPostRule
void(* PrefilterPostRule)(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f)
Definition: detect.h:1687
SIG_FLAG_FW_HOOK_LTE
#define SIG_FLAG_FW_HOOK_LTE
Definition: detect.h:255
DetectGetSingleData
InspectionBuffer * DetectGetSingleData(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, const int list_id, InspectionSingleBufferGetDataPtr GetBuf)
Definition: detect-engine.c:2340
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
PostRuleMatchWorkQueueAppend
void PostRuleMatchWorkQueueAppend(DetectEngineThreadCtx *det_ctx, const Signature *s, const int type, const uint32_t value)
Definition: detect-engine-prefilter.c:1878
AppLayerParserGetStateNameById
const char * AppLayerParserGetStateNameById(uint8_t ipproto, AppProto alproto, const int id, const uint8_t direction)
Definition: app-layer-parser.c:1847
SignatureHook_::sm_list
int sm_list
Definition: detect.h:585
PatternMatchPrepareGroup
int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
Prepare the pattern matcher ctx in a sig group head.
Definition: detect-engine-mpm.c:2394
PrefilterMpmPktCtx
struct PrefilterMpmPktCtx PrefilterMpmPktCtx
PrefilterStore_::FreeFunc
void(* FreeFunc)(void *)
Definition: detect-engine-prefilter.h:53
PostRuleMatchWorkQueue::len
uint32_t len
Definition: detect.h:1299
PostRuleMatchWorkQueueItem::sm_type
int sm_type
Definition: detect.h:1288
PREFILTER_PROFILING_END
#define PREFILTER_PROFILING_END(ctx, profile_id)
Definition: util-profiling.h:276
PrefilterStore_
Definition: detect-engine-prefilter.h:51
CLS
#define CLS
Definition: suricata-common.h:77
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:1724
PostRuleMatchWorkQueueItem
Definition: detect.h:1287
PrefilterNonPFData::size
uint32_t size
Definition: detect-engine-prefilter.c:596
DetectEngineTransforms
Definition: detect.h:395
PrefilterEngineList_::id
uint16_t id
Definition: detect.h:1610
PROF_DETECT_PF_PAYLOAD
@ PROF_DETECT_PF_PAYLOAD
Definition: suricata-common.h:477
Signature_::app_progress_hook
uint8_t app_progress_hook
Definition: detect.h:729
BIT_U16
#define BIT_U16(n)
Definition: suricata-common.h:430
SignatureInitData_::prefilter_sm
SigMatch * prefilter_sm
Definition: detect.h:642
PcapPacketCntGet
uint64_t PcapPacketCntGet(const Packet *p)
Definition: decode.c:1193
DetectEngineAppHookToSmlist
int DetectEngineAppHookToSmlist(const AppProto p, const uint8_t sub_state, const uint8_t state, const uint8_t direction)
get the sm_list for a app hook
Definition: detect-engine.c:885
Signature_::alproto
AppProto alproto
Definition: detect.h:697
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
QUEUE_STEP
#define QUEUE_STEP
Definition: detect-engine-prefilter.c:1876
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
DetectPort_::port
uint16_t port
Definition: detect.h:224
SignatureHook_::app
struct SignatureHook_::@87::@88 app
DetectBufferMpmRegistry_::app_v2
struct DetectBufferMpmRegistry_::@90::@92 app_v2
name
const char * name
Definition: detect-engine-proto.c:48
PrefilterSingleMpmRegister
int PrefilterSingleMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:1729
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:87
PrefilterMpmCtx::GetData
InspectionBufferGetDataPtr GetData
Definition: detect-engine-prefilter.c:1626
InspectionBuffer
Definition: detect-engine-inspect-buffer.h:34
SignatureHook_::t
union SignatureHook_::@87 t
PrefilterAppendEngine
int PrefilterAppendEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterPktFn PrefilterFunc, SignatureMask mask, enum SignatureHookPkt hook, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Definition: detect-engine-prefilter.c:310
Packet_::flags
uint32_t flags
Definition: decode.h:562
type
uint8_t type
Definition: decode-sctp.h:0
Frame
Definition: app-layer-frames.h:45
Flow_
Flow data structure.
Definition: flow.h:360
PREFILTER_PROFILING_START
#define PREFILTER_PROFILING_START(det_ctx)
Definition: util-profiling.h:260
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1429
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its normalized string equivalent.
Definition: app-layer-protos.c:53
ctx
struct Thresholds ctx
PrefilterEngineList_::name
const char * name
Definition: detect.h:1646
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:995
SIGNATURE_HOOK_PKT_NOT_SET
@ SIGNATURE_HOOK_PKT_NOT_SET
Definition: detect.h:548
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:287
DETECT_UINT_EQ
#define DETECT_UINT_EQ
Definition: detect-engine-uint.h:35
PrefilterNonPFData
Definition: detect-engine-prefilter.c:595
InspectionBufferGetPktDataPtr
InspectionBuffer *(* InspectionBufferGetPktDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Packet *p, const int list_id)
Definition: detect.h:487
PrefilterEngine_::cb
union PrefilterEngine_::@105 cb
PrefilterDeinit
void PrefilterDeinit(DetectEngineCtx *de_ctx)
Definition: detect-engine-prefilter.c:1550
TxNonPFData::engine_name
const char * engine_name
Definition: detect-engine-prefilter.c:755
HashTable_
Definition: util-hash.h:35
DetectEngineSetEvent
void DetectEngineSetEvent(DetectEngineThreadCtx *det_ctx, uint8_t e)
Definition: detect-engine.c:5328
Packet_::sig_mask
SignatureMask sig_mask
Definition: decode.h:553
Frames
Definition: app-layer-frames.h:60
DetectBufferMpmRegistry_
one time registration of keywords at start up
Definition: detect.h:791
DetectPort_::next
struct DetectPort_ * next
Definition: detect.h:237
PrefilterNonPFDataTx
Definition: detect-engine-prefilter.c:600
PrefilterMpmPktCtx
Definition: detect-engine-prefilter.c:1808
detect-engine-frame.h
p
Packet * p
Definition: fuzz_dataset.c:30
SigGroupHead_::payload_engines
PrefilterEngine * payload_engines
Definition: detect.h:1735
DetectEngineCtx_::prefilter_setting
enum DetectEnginePrefilterSetting prefilter_setting
Definition: detect.h:1134
DetectBufferType_
Definition: detect.h:454
PKT_NOPAYLOAD_INSPECTION
#define PKT_NOPAYLOAD_INSPECTION
Definition: decode.h:1297
PrefilterNonPFData::array
struct PrefilterNonPFDataSig array[]
Definition: detect-engine-prefilter.c:597
PostRuleMatchWorkQueue::size
uint32_t size
Definition: detect.h:1300
PACKET_PROFILING_DETECT_END
#define PACKET_PROFILING_DETECT_END(p, id)
Definition: util-profiling.h:221
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:245
TxNonPFData::sig_list
int sig_list
Definition: detect-engine-prefilter.c:747
PrefilterEngine_::local_id
uint16_t local_id
Definition: detect.h:1652
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:547
PrefilterEngineList_::Free
void(* Free)(void *pectx)
Definition: detect.h:1639
StringHashCompareFunc
char StringHashCompareFunc(void *data1, uint16_t datalen1, void *data2, uint16_t datalen2)
Definition: util-hash-string.c:38
SIG_FLAG_TOCLIENT
#define SIG_FLAG_TOCLIENT
Definition: detect.h:275
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:427
DetectBufferMpmRegistry_::transforms
DetectEngineTransforms transforms
Definition: detect.h:804
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:621
Signature_::dsize_low
uint16_t dsize_low
Definition: detect.h:699
DetectPort_::port2
uint16_t port2
Definition: detect.h:225
DetectEngineCtx_::non_pf_engine_names
HashTable * non_pf_engine_names
Definition: detect.h:1212
detect-engine-prefilter.h
PrefilterMultiGenericMpmRegister
int PrefilterMultiGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:1784
PrefilterNonPFDataSig::foo
uint8_t foo
Definition: detect-engine-prefilter.c:590
PrefilterStore_::id
uint32_t id
Definition: detect-engine-prefilter.h:54
DetectBufferTypeGetByName
int DetectBufferTypeGetByName(const char *name)
Definition: detect-engine.c:1453
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:114
HashTable_::array_size
uint32_t array_size
Definition: util-hash.h:37
DetectBufferMpmRegistry_::pkt_v1
struct DetectBufferMpmRegistry_::@90::@93 pkt_v1
DETECT_PREFILTER_AUTO
@ DETECT_PREFILTER_AUTO
Definition: detect.h:927
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:1672
PROF_DETECT_PF_SORT1
@ PROF_DETECT_PF_SORT1
Definition: suricata-common.h:480
DetectEngineCtx_::prefilter_id
uint32_t prefilter_id
Definition: detect.h:1165
FRAME_ANY_TYPE
#define FRAME_ANY_TYPE
Definition: app-layer-frames.h:30
TxNonPFData::run_always
bool run_always
Definition: detect-engine-prefilter.c:752
PrefilterEngineList_::next
struct PrefilterEngineList_ * next
Definition: detect.h:1636
SigTableElmt_::SetupPrefilter
int(* SetupPrefilter)(DetectEngineCtx *de_ctx, struct SigGroupHead_ *sgh)
Definition: detect.h:1524
SIGNATURE_HOOK_TYPE_APP
@ SIGNATURE_HOOK_TYPE_APP
Definition: detect.h:558
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:484
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:55
PrefilterMpmListId
Definition: detect-engine-mpm.h:130
DetectEngineCtx_::prefilter_hash_table
HashListTable * prefilter_hash_table
Definition: detect.h:1166
SIG_FLAG_TOSERVER
#define SIG_FLAG_TOSERVER
Definition: detect.h:274
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
DetectBufferMpmRegistry_::pname
char pname[DETECT_PROFILE_NAME_LEN]
Definition: detect.h:793
PrefilterEngineList_::pkt_hook
enum SignatureHookPkt pkt_hook
Definition: detect.h:1624
PrefilterEngineList_::alproto
AppProto alproto
Definition: detect.h:1613
TxNonPFData::progress
uint8_t progress
Definition: detect-engine-prefilter.c:746
SigGroupHeadInitData_::sig_cnt
SigIntId sig_cnt
Definition: detect.h:1717
AppLayerTxData
Definition: app-layer-parser.h:172
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
g_alproto_max
AppProto g_alproto_max
Definition: app-layer-protos.c:32
PrefilterEngineList_::run_always
bool run_always
Definition: detect.h:1644
Prefilter
void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, const uint8_t flags, const SignatureMask mask)
Definition: detect-engine-prefilter.c:244
DetectEngineThreadCtx_
Definition: detect.h:1316
PrefilterEngine_
Definition: detect.h:1651
SigGroupHeadInitData_::tx_engines
PrefilterEngineList * tx_engines
Definition: detect.h:1712
DetectTransaction_::detect_progress
uint8_t detect_progress
Definition: detect-engine-prefilter.h:39
SignatureInitData_::mpm_sm
SigMatch * mpm_sm
Definition: detect.h:640
DetectEngineGetMaxSigId
#define DetectEngineGetMaxSigId(de_ctx)
Definition: detect-engine.h:91
PROF_DETECT_PF_PKT
@ PROF_DETECT_PF_PKT
Definition: suricata-common.h:476
PrefilterEngineList_::PrefilterFrame
PrefilterFrameFn PrefilterFrame
Definition: detect.h:1632
PrefilterEngine_::ctx
union PrefilterEngine_::@104 ctx
PrefilterEngineList_::pectx
void * pectx
Definition: detect.h:1628
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
detect-engine-mpm.h
PrefilterEngineList_::PrefilterTx
PrefilterTxFn PrefilterTx
Definition: detect.h:1631
DetectEngineCtx_::sm_types_prefilter
bool * sm_types_prefilter
Definition: detect.h:1181
TxNonPFData
Definition: detect-engine-prefilter.c:742
SignatureHookPkt
SignatureHookPkt
Definition: detect.h:547
PrefilterEngineList_::gid
uint32_t gid
Definition: detect.h:1648
PrefilterMpmPktCtx::GetData
InspectionBufferGetPktDataPtr GetData
Definition: detect-engine-prefilter.c:1810
PKT_DETECT_HAS_STREAMDATA
#define PKT_DETECT_HAS_STREAMDATA
Definition: decode.h:1350
InspectionSingleBufferGetDataPtr
bool(* InspectionSingleBufferGetDataPtr)(const void *txv, const uint8_t flow_flags, const uint8_t **buf, uint32_t *buf_len)
Definition: detect-engine-helper.h:45
FLOW_PKT_TOCLIENT_FIRST
#define FLOW_PKT_TOCLIENT_FIRST
Definition: flow.h:241
PrefilterMpmCtx
struct PrefilterMpmCtx PrefilterMpmCtx
NONPF_PKT_STATS_INCR
#define NONPF_PKT_STATS_INCR(s)
Definition: detect-engine-prefilter.c:629
DetectEngineCtx_::frame_inspect_engines
DetectEngineFrameInspectionEngine * frame_inspect_engines
Definition: detect.h:1161
PrefilterGenericMpmRegister
int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
Definition: detect-engine-prefilter.c:1707
PrefilterFrameFn
void(* PrefilterFrameFn)(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, const struct Frames *frames, const struct Frame *frame)
Definition: detect.h:1602
HashTableAdd
int HashTableAdd(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:132
PrefilterNonPFDataTx::array
uint32_t array[]
Definition: detect-engine-prefilter.c:602
SigGroupHead_::init
SigGroupHeadInitData * init
Definition: detect.h:1741
SignatureHook_::pkt
struct SignatureHook_::@87::@89 pkt
PrefilterMpmListId::transforms
const DetectEngineTransforms * transforms
Definition: detect-engine-mpm.h:134
app-layer-parser.h
MpmCtx_::minlen
uint16_t minlen
Definition: util-mpm.h:122
Packet_::pkt_hooks
uint16_t pkt_hooks
Definition: decode.h:556
PrefilterNonPFDataSig::type
uint8_t type
Definition: detect-engine-prefilter.c:587
SignatureInitData_::hook
SignatureHook hook
Definition: detect.h:604
SigGroupHeadInitData_::direction
uint32_t direction
Definition: detect.h:1702
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:331
PrefilterEngine_::pkt
struct PrefilterEngine_::@104::@106 pkt
util-profiling.h
DetectTransaction_::tx_id
const uint64_t tx_id
Definition: detect-engine-prefilter.h:33
SigIntId
#define SigIntId
Definition: detect-engine-state.h:38
SCReturn
#define SCReturn
Definition: util-debug.h:286
PrefilterEngine_::alproto
AppProto alproto
Definition: detect.h:1655
Signature_::flags
uint32_t flags
Definition: detect.h:693
PrefilterMpmListId::mpm_ctx
const MpmCtx * mpm_ctx
Definition: detect-engine-mpm.h:132
Packet_
Definition: decode.h:516
SCFreeAligned
#define SCFreeAligned(p)
Definition: util-mem.h:77
Flow_::type
uint8_t type
Definition: flow.h:367
DetectBufferType_::packet
bool packet
Definition: detect.h:460
DetectEngineFrameInspectionEngine
Definition: detect.h:517
DetectEngineBufferTypeGetById
const DetectBufferType * DetectEngineBufferTypeGetById(const DetectEngineCtx *de_ctx, const int id)
Definition: detect-engine.c:1473
PrefilterEngine_::PrefilterFrame
PrefilterFrameFn PrefilterFrame
Definition: detect.h:1686
PrefilterEngine_::frame_type
uint8_t frame_type
Definition: detect.h:1668
DetectBufferType_::name
char name[64]
Definition: detect.h:455
Signature_::init_data
SignatureInitData * init_data
Definition: detect.h:775
DetectTransaction_::tx_type
const uint8_t tx_type
Definition: detect-engine-prefilter.h:48
HashListTable_
Definition: util-hashlist.h:37
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:1606
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:200
SigGroupHead_::frame_engines
PrefilterEngine * frame_engines
Definition: detect.h:1737
PrefilterMpmCtx::list_id
int list_id
Definition: detect-engine-prefilter.c:1624
DetectEngineThreadCtx_::mtc
MpmThreadCtx mtc
Definition: detect.h:1425
Flow_::next
struct Flow_ * next
Definition: flow.h:407
PrefilterMpmPktCtx::list_id
int list_id
Definition: detect-engine-prefilter.c:1809
PrefilterAppendPayloadEngine
int PrefilterAppendPayloadEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterPktFn PrefilterFunc, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Definition: detect-engine-prefilter.c:349
PrefilterEngineList_::tx_min_progress
int8_t tx_min_progress
Definition: detect.h:1616
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
SIG_FLAG_MPM_NEG
#define SIG_FLAG_MPM_NEG
Definition: detect.h:260
SigGroupHeadInitData_::pkt_engines
PrefilterEngineList * pkt_engines
Definition: detect.h:1710
SigGroupHead_::post_rule_match_engines
PrefilterEngine * post_rule_match_engines
Definition: detect.h:1738
DetectBufferType_::frame
bool frame
Definition: detect.h:461
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
PREFILTER_PROFILING_ADD_BYTES
#define PREFILTER_PROFILING_ADD_BYTES(det_ctx, bytes)
Definition: util-profiling.h:286
Packet_::flow
struct Flow_ * flow
Definition: decode.h:564
PrefilterNonPFDataSig::type
uint32_t type
Definition: detect-engine-prefilter.c:577
tail
Host * tail
Definition: host.h:2
flags
uint8_t flags
Definition: decode-gre.h:0
PrefilterNonPFDataTx::size
uint32_t size
Definition: detect-engine-prefilter.c:601
suricata-common.h
SigGroupHeadInitData_::frame_engines
PrefilterEngineList * frame_engines
Definition: detect.h:1713
SigGroupHeadInitData_::payload_engines
PrefilterEngineList * payload_engines
Definition: detect.h:1711
PrefilterNonPFDataSig::sig_mask
SignatureMask sig_mask
Definition: detect-engine-prefilter.c:583
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:88
SigGroupHeadInitData_::match_array
Signature ** match_array
Definition: detect.h:1720
PROF_DETECT_PF_RECORD
@ PROF_DETECT_PF_RECORD
Definition: suricata-common.h:479
DetectBufferMpmRegistry_::name
const char * name
Definition: detect.h:792
SCMallocAligned
#define SCMallocAligned(size, align)
Definition: util-mem.h:68
DetectEnginePrefilterSetting
DetectEnginePrefilterSetting
Definition: detect.h:925
SignatureHook_::type
enum SignatureHookType type
Definition: detect.h:584
DetectTransaction_
Definition: detect-engine-prefilter.h:31
PrefilterEngineList_::PrefilterPostRule
void(* PrefilterPostRule)(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f)
Definition: detect.h:1633
PrefilterEngineList_
Definition: detect.h:1609
PrefilterCleanupRuleGroup
void PrefilterCleanupRuleGroup(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Definition: detect-engine-prefilter.c:531
PostRuleMatchWorkQueue::q
PostRuleMatchWorkQueueItem * q
Definition: detect.h:1298
PrefilterEngine_::gid
uint32_t gid
Definition: detect.h:1692
PrefilterNonPFDataSig::app
struct PrefilterNonPFDataSig::@53::@57 app
SCStrdup
#define SCStrdup(s)
Definition: util-mem.h:56
FatalError
#define FatalError(...)
Definition: util-debug.h:517
SIGNATURE_HOOK_TYPE_PKT
@ SIGNATURE_HOOK_TYPE_PKT
Definition: detect.h:557
PrefilterMpmPktCtx::transforms
const DetectEngineTransforms * transforms
Definition: detect-engine-prefilter.c:1812
PrefilterPktFn
void(* PrefilterPktFn)(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
Definition: detect.h:1601
PrefilterMpmCtx
Definition: detect-engine-prefilter.c:1623
PrefilterMpmListId::GetData
InspectionMultiBufferGetDataPtr GetData
Definition: detect-engine-mpm.h:133
util-validate.h
DetectTransaction_::tx_ptr
void * tx_ptr
Definition: detect-engine-prefilter.h:32
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect-engine-inspect-buffer.h:37
SignatureInitData_::buffers
SignatureInitDataBuffer * buffers
Definition: detect.h:671
DetectEngineCtx_::app_inspect_engines
DetectEngineAppInspectionEngine * app_inspect_engines
Definition: detect.h:1157
PrefilterEngine_::pectx
void * pectx
Definition: detect.h:1681
PrefilterAppendPostRuleEngine
int PrefilterAppendPostRuleEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, void(*PrefilterPostRuleFunc)(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p, Flow *f), void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Definition: detect-engine-prefilter.c:462
Signature_::dp
DetectPort * dp
Definition: detect.h:747
PrefilterInit
void PrefilterInit(DetectEngineCtx *de_ctx)
Definition: detect-engine-prefilter.c:1557
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect-engine-inspect-buffer.h:35
PACKET_PROFILING_DETECT_START
#define PACKET_PROFILING_DETECT_START(p, id)
Definition: util-profiling.h:214
str
#define str(s)
Definition: suricata-common.h:322
PrefilterMpmCtx::transforms
const DetectEngineTransforms * transforms
Definition: detect-engine-prefilter.c:1630
DETECT_TBLSIZE
int DETECT_TBLSIZE
Definition: detect-engine-register.c:263
TxNonPFData::dir
int dir
Definition: detect-engine-prefilter.c:745
Signature_::iid
SigIntId iid
Definition: detect.h:704
TxNonPFData::sigs_cnt
uint32_t sigs_cnt
Definition: detect-engine-prefilter.c:753
PrefilterStore_::name
const char * name
Definition: detect-engine-prefilter.h:52
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SigGroupHeadInitData_::post_rule_match_engines
PrefilterEngineList * post_rule_match_engines
Definition: detect.h:1714
Signature_::id
uint32_t id
Definition: detect.h:741
HashListTableBucket_
Definition: util-hashlist.h:28
PrefilterMpmPktCtx::mpm_ctx
const MpmCtx * mpm_ctx
Definition: detect-engine-prefilter.c:1811
PrefilterNonPFDataSig
Definition: detect-engine-prefilter.c:575
SignatureInitDataBuffer_::id
uint32_t id
Definition: detect.h:534
Signature_
Signature container.
Definition: detect.h:692
PrefilterEngineList_::pkt_mask
SignatureMask pkt_mask
Definition: detect.h:1620
PrefilterMpmListId::list_id
int list_id
Definition: detect-engine-mpm.h:131
DetectBufferType_::run_always
bool run_always
Definition: detect.h:464
TxNonPFData::alproto
AppProto alproto
Definition: detect-engine-prefilter.c:743
HashTableInit
HashTable * HashTableInit(uint32_t size, uint32_t(*Hash)(struct HashTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hash.c:35
PrefilterAppendTxEngine
int PrefilterAppendTxEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterTxFn PrefilterTxFunc, AppProto alproto, const int8_t tx_min_progress, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
Definition: detect-engine-prefilter.c:419
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
ALPROTO_FAILED
@ ALPROTO_FAILED
Definition: app-layer-protos.h:33
PostRuleMatchWorkQueueItem::value
uint32_t value
Definition: detect.h:1289
Signature_::dsize_mode
uint8_t dsize_mode
Definition: detect.h:701
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:47
PrefilterSetupRuleGroup
int PrefilterSetupRuleGroup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
Definition: detect-engine-prefilter.c:1289
SIGNATURE_HOOK_PKT_FLOW_START
@ SIGNATURE_HOOK_PKT_FLOW_START
Definition: detect.h:549
PrefilterEngine_::is_last
bool is_last
Definition: detect.h:1671
suricata.h
InspectionBufferGetDataPtr
InspectionBuffer *(* InspectionBufferGetDataPtr)(struct DetectEngineThreadCtx_ *det_ctx, const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv, const int list_id)
Definition: detect-engine-helper.h:39
PrefilterEngine_::run_always
bool run_always
Definition: detect.h:1677
PrefilterPostRuleMatch
void PrefilterPostRuleMatch(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, Flow *f)
invoke post-rule match "prefilter" engines
Definition: detect-engine-prefilter.c:221
DetectGetInnerTx
void * DetectGetInnerTx(void *tx_ptr, AppProto alproto, AppProto engine_alproto, uint8_t flow_flags)
Definition: detect.c:1266
AppLayerParserGetMaxSubState
uint8_t AppLayerParserGetMaxSubState(const AppProto alproto)
Definition: app-layer-parser.c:1349
PrefilterNonPFDataSig::pkt
struct PrefilterNonPFDataSig::@53::@55 pkt
likely
#define likely(expr)
Definition: util-optimize.h:32
PrefilterEngine_::app
struct PrefilterEngine_::@104::@107 app
PrefilterMpmCtx::GetDataSingle
InspectionSingleBufferGetDataPtr GetDataSingle
Definition: detect-engine-prefilter.c:1627
PrefilterNonPFDataSig::value
uint16_t value
Definition: detect-engine-prefilter.c:578
PrefilterMpm
struct PrefilterMpm PrefilterMpm
SigGroupHead_::pkt_engines
PrefilterEngine * pkt_engines
Definition: detect.h:1734
AppLayerParserSupportsSubStates
bool AppLayerParserSupportsSubStates(const AppProto alproto)
Definition: app-layer-parser.c:1356
PrefilterEngine_::Prefilter
PrefilterPktFn Prefilter
Definition: detect.h:1684
DetectTransaction_::tx_progress
const uint8_t tx_progress
Definition: detect-engine-prefilter.h:43
PrefilterEngine_::PrefilterTx
PrefilterTxFn PrefilterTx
Definition: detect.h:1685
MpmCtx_
Definition: util-mpm.h:111
TxNonPFData::sub_state
uint8_t sub_state
Definition: detect-engine-prefilter.c:744
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:456
Packet_::dp
Port dp
Definition: decode.h:531
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
PrefilterNonPFDataSig::frame
struct PrefilterNonPFDataSig::@53::@56 frame
PrefilterMpm
Definition: detect-dns-response.c:40
SignatureInitData_::buffer_index
uint32_t buffer_index
Definition: detect.h:672
PrefilterFreeEnginesList
void PrefilterFreeEnginesList(PrefilterEngineList *list)
Definition: detect-engine-prefilter.c:503
FLOW_PKT_TOSERVER_FIRST
#define FLOW_PKT_TOSERVER_FIRST
Definition: flow.h:240
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:109
SIG_FLAG_PREFILTER
#define SIG_FLAG_PREFILTER
Definition: detect.h:281
PrefilterMpmCtx::mpm_ctx
const MpmCtx * mpm_ctx
Definition: detect-engine-prefilter.c:1629
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:95
DetectEngineThreadCtx_::post_rule_work_queue
PostRuleMatchWorkQueue post_rule_work_queue
Definition: detect.h:1427
SIG_FLAG_DSIZE
#define SIG_FLAG_DSIZE
Definition: detect.h:251
StringHashDjb2
uint32_t StringHashDjb2(const uint8_t *data, uint32_t datalen)
Definition: util-hash-string.c:22
SignatureMask
#define SignatureMask
Definition: decode.h:100
Signature_::mask
SignatureMask mask
Definition: detect.h:703
DETECT_EVENT_POST_MATCH_QUEUE_FAILED
@ DETECT_EVENT_POST_MATCH_QUEUE_FAILED
Definition: detect.h:1565
PrefilterRuleStore_::rule_id_array
SigIntId * rule_id_array
Definition: util-prefilter.h:38
PrefilterPktNonPFStatsDump
void PrefilterPktNonPFStatsDump(void)
Definition: detect-engine-prefilter.c:632
f
Flow f
Definition: fuzz_dataset.c:32
TxNonPFData::sigs
struct PrefilterNonPFDataSig * sigs
Definition: detect-engine-prefilter.c:754