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