suricata
detect.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2022 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  * Basic detection engine
24  */
25 
26 #include "suricata-common.h"
27 #include "suricata.h"
28 #include "conf.h"
29 
30 #include "decode.h"
31 #include "packet.h"
32 #include "flow.h"
33 #include "stream-tcp.h"
34 #include "app-layer.h"
35 #include "app-layer-parser.h"
36 #include "app-layer-frames.h"
37 
38 #include "detect.h"
39 #include "detect-dsize.h"
40 #include "detect-engine.h"
41 #include "detect-engine-build.h"
42 #include "detect-engine-frame.h"
43 #include "detect-engine-profile.h"
44 
45 #include "detect-engine-alert.h"
46 #include "detect-engine-siggroup.h"
47 #include "detect-engine-address.h"
48 #include "detect-engine-proto.h"
49 #include "detect-engine-port.h"
50 #include "detect-engine-mpm.h"
51 #include "detect-engine-iponly.h"
54 #include "detect-engine-state.h"
55 #include "detect-engine-analyzer.h"
56 
57 #include "detect-engine-payload.h"
58 #include "detect-engine-event.h"
59 
60 #include "detect-filestore.h"
61 #include "detect-flowvar.h"
62 #include "detect-replace.h"
63 
64 #include "util-validate.h"
65 #include "util-detect.h"
66 #include "util-profiling.h"
67 
68 #include "action-globals.h"
69 
70 typedef struct DetectRunScratchpad {
72  const uint8_t flow_flags; /* flow/state flags: STREAM_* */
73  const bool app_decoder_events;
74  const SigGroupHead *sgh;
77 
78 /* prototypes */
79 static DetectRunScratchpad DetectRunSetup(const DetectEngineCtx *de_ctx,
80  DetectEngineThreadCtx *det_ctx, Packet * const p, Flow * const pflow);
81 static void DetectRunInspectIPOnly(ThreadVars *tv, const DetectEngineCtx *de_ctx,
82  DetectEngineThreadCtx *det_ctx, Flow * const pflow, Packet * const p);
83 static inline void DetectRunGetRuleGroup(const DetectEngineCtx *de_ctx,
84  Packet * const p, Flow * const pflow, DetectRunScratchpad *scratch);
85 static inline void DetectRunPrefilterPkt(ThreadVars *tv,
87  DetectRunScratchpad *scratch);
88 static inline void DetectRulePacketRules(ThreadVars * const tv,
89  DetectEngineCtx * const de_ctx, DetectEngineThreadCtx * const det_ctx,
90  Packet * const p, Flow * const pflow, const DetectRunScratchpad *scratch);
91 static void DetectRunTx(ThreadVars *tv, DetectEngineCtx *de_ctx,
92  DetectEngineThreadCtx *det_ctx, Packet *p,
93  Flow *f, DetectRunScratchpad *scratch);
94 static void DetectRunFrames(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
95  Packet *p, Flow *f, DetectRunScratchpad *scratch);
96 static inline void DetectRunPostRules(ThreadVars *tv, DetectEngineCtx *de_ctx,
97  DetectEngineThreadCtx *det_ctx, Packet * const p, Flow * const pflow,
98  DetectRunScratchpad *scratch);
99 static void DetectRunCleanup(DetectEngineThreadCtx *det_ctx,
100  Packet *p, Flow * const pflow);
101 
102 /** \internal
103  */
104 static void DetectRun(ThreadVars *th_v,
106  Packet *p)
107 {
108  SCEnter();
109  SCLogDebug("p->pcap_cnt %" PRIu64 " direction %s flow %p", p->pcap_cnt,
110  p->flow ? (FlowGetPacketDirection(p->flow, p) == TOSERVER ? "toserver" : "toclient")
111  : "noflow",
112  p->flow);
113 
114  /* bail early if packet should not be inspected */
115  if (p->flags & PKT_NOPACKET_INSPECTION) {
116  /* nothing to do */
117  SCReturn;
118  }
119 
120  /* Load the Packet's flow early, even though it might not be needed.
121  * Mark as a constant pointer, although the flow itself can change. */
122  Flow * const pflow = p->flow;
123 
124  DetectRunScratchpad scratch = DetectRunSetup(de_ctx, det_ctx, p, pflow);
125 
126  /* run the IPonly engine */
127  DetectRunInspectIPOnly(th_v, de_ctx, det_ctx, pflow, p);
128 
129  /* get our rule group */
130  DetectRunGetRuleGroup(de_ctx, p, pflow, &scratch);
131  /* if we didn't get a sig group head, we
132  * have nothing to do.... */
133  if (scratch.sgh == NULL) {
134  SCLogDebug("no sgh for this packet, nothing to match against");
135  goto end;
136  }
137 
138  /* run the prefilters for packets */
139  DetectRunPrefilterPkt(th_v, de_ctx, det_ctx, p, &scratch);
140 
142  /* inspect the rules against the packet */
143  DetectRulePacketRules(th_v, de_ctx, det_ctx, p, pflow, &scratch);
145 
146  /* run tx/state inspection. Don't call for ICMP error msgs. */
147  if (pflow && pflow->alstate && likely(pflow->proto == p->proto)) {
148  if (p->proto == IPPROTO_TCP) {
149  const TcpSession *ssn = p->flow->protoctx;
150  if (ssn && (ssn->flags & STREAMTCP_FLAG_APP_LAYER_DISABLED) == 0) {
151  // PACKET_PROFILING_DETECT_START(p, PROF_DETECT_TX);
152  DetectRunFrames(th_v, de_ctx, det_ctx, p, pflow, &scratch);
153  // PACKET_PROFILING_DETECT_END(p, PROF_DETECT_TX);
154  }
155  } else if (p->proto == IPPROTO_UDP) {
156  DetectRunFrames(th_v, de_ctx, det_ctx, p, pflow, &scratch);
157  }
158 
160  DetectRunTx(th_v, de_ctx, det_ctx, p, pflow, &scratch);
162  }
163 
164 end:
165  DetectRunPostRules(th_v, de_ctx, det_ctx, p, pflow, &scratch);
166 
167  DetectRunCleanup(det_ctx, p, pflow);
168  SCReturn;
169 }
170 
171 static void DetectRunPostMatch(ThreadVars *tv,
172  DetectEngineThreadCtx *det_ctx, Packet *p,
173  const Signature *s)
174 {
175  /* run the packet match functions */
177  if (smd != NULL) {
179 
180  SCLogDebug("running match functions, sm %p", smd);
181 
182  while (1) {
184  (void)sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx);
185  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
186  if (smd->is_last)
187  break;
188  smd++;
189  }
190  }
191 }
192 
193 /**
194  * \brief Get the SigGroupHead for a packet.
195  *
196  * \param de_ctx detection engine context
197  * \param p packet
198  *
199  * \retval sgh the SigGroupHead or NULL if non applies to the packet
200  */
202  const Packet *p)
203 {
204  SCEnter();
205 
206  int f;
207  SigGroupHead *sgh = NULL;
208 
209  /* if the packet proto is 0 (not set), we're inspecting it against
210  * the decoder events sgh we have. */
211  if (p->proto == 0 && p->events.cnt > 0) {
212  SCReturnPtr(de_ctx->decoder_event_sgh, "SigGroupHead");
213  } else if (p->proto == 0) {
214  if (!(PKT_IS_IPV4(p) || PKT_IS_IPV6(p))) {
215  /* not IP, so nothing to do */
216  SCReturnPtr(NULL, "SigGroupHead");
217  }
218  }
219 
220  /* select the flow_gh */
221  if (p->flowflags & FLOW_PKT_TOCLIENT)
222  f = 0;
223  else
224  f = 1;
225 
226  int proto = IP_GET_IPPROTO(p);
227  if (proto == IPPROTO_TCP) {
228  DetectPort *list = de_ctx->flow_gh[f].tcp;
229  SCLogDebug("tcp toserver %p, tcp toclient %p: going to use %p",
231  uint16_t port = f ? p->dp : p->sp;
232  SCLogDebug("tcp port %u -> %u:%u", port, p->sp, p->dp);
233  DetectPort *sghport = DetectPortLookupGroup(list, port);
234  if (sghport != NULL)
235  sgh = sghport->sh;
236  SCLogDebug("TCP list %p, port %u, direction %s, sghport %p, sgh %p",
237  list, port, f ? "toserver" : "toclient", sghport, sgh);
238  } else if (proto == IPPROTO_UDP) {
239  DetectPort *list = de_ctx->flow_gh[f].udp;
240  uint16_t port = f ? p->dp : p->sp;
241  DetectPort *sghport = DetectPortLookupGroup(list, port);
242  if (sghport != NULL)
243  sgh = sghport->sh;
244  SCLogDebug("UDP list %p, port %u, direction %s, sghport %p, sgh %p",
245  list, port, f ? "toserver" : "toclient", sghport, sgh);
246  } else {
247  sgh = de_ctx->flow_gh[f].sgh[proto];
248  }
249 
250  SCReturnPtr(sgh, "SigGroupHead");
251 }
252 
253 static inline void DetectPrefilterMergeSort(DetectEngineCtx *de_ctx,
254  DetectEngineThreadCtx *det_ctx)
255 {
256  SigIntId mpm, nonmpm;
257  SigIntId *mpm_ptr = det_ctx->pmq.rule_id_array;
258  SigIntId *nonmpm_ptr = det_ctx->non_pf_id_array;
259  uint32_t m_cnt = det_ctx->pmq.rule_id_array_cnt;
260  uint32_t n_cnt = det_ctx->non_pf_id_cnt;
261  SigIntId *final_ptr;
262  uint32_t final_cnt;
263  SigIntId id;
264  SigIntId previous_id = (SigIntId)-1;
265  Signature **sig_array = de_ctx->sig_array;
266  Signature **match_array = det_ctx->match_array;
267  Signature *s;
268 
269  SCLogDebug("PMQ rule id array count %d", det_ctx->pmq.rule_id_array_cnt);
270 
271  /* Load first values. */
272  if (likely(m_cnt)) {
273  mpm = *mpm_ptr;
274  } else {
275  /* mpm list is empty */
276  final_ptr = nonmpm_ptr;
277  final_cnt = n_cnt;
278  goto final;
279  }
280  if (likely(n_cnt)) {
281  nonmpm = *nonmpm_ptr;
282  } else {
283  /* non-mpm list is empty. */
284  final_ptr = mpm_ptr;
285  final_cnt = m_cnt;
286  goto final;
287  }
288  while (1) {
289  if (mpm < nonmpm) {
290  /* Take from mpm list */
291  id = mpm;
292 
293  s = sig_array[id];
294  /* As the mpm list can contain duplicates, check for that here. */
295  if (likely(id != previous_id)) {
296  *match_array++ = s;
297  previous_id = id;
298  }
299  if (unlikely(--m_cnt == 0)) {
300  /* mpm list is now empty */
301  final_ptr = nonmpm_ptr;
302  final_cnt = n_cnt;
303  goto final;
304  }
305  mpm_ptr++;
306  mpm = *mpm_ptr;
307  } else if (mpm > nonmpm) {
308  id = nonmpm;
309 
310  s = sig_array[id];
311  /* As the mpm list can contain duplicates, check for that here. */
312  if (likely(id != previous_id)) {
313  *match_array++ = s;
314  previous_id = id;
315  }
316  if (unlikely(--n_cnt == 0)) {
317  final_ptr = mpm_ptr;
318  final_cnt = m_cnt;
319  goto final;
320  }
321  nonmpm_ptr++;
322  nonmpm = *nonmpm_ptr;
323 
324  } else { /* implied mpm == nonmpm */
325  /* special case: if on both lists, it's a negated mpm pattern */
326 
327  /* mpm list may have dups, so skip past them here */
328  while (--m_cnt != 0) {
329  mpm_ptr++;
330  mpm = *mpm_ptr;
331  if (mpm != nonmpm)
332  break;
333  }
334  /* if mpm is done, update nonmpm_ptrs and jump to final */
335  if (unlikely(m_cnt == 0)) {
336  n_cnt--;
337 
338  /* mpm list is now empty */
339  final_ptr = ++nonmpm_ptr;
340  final_cnt = n_cnt;
341  goto final;
342  }
343  /* otherwise, if nonmpm is done jump to final for mpm
344  * mpm ptrs alrady updated */
345  if (unlikely(--n_cnt == 0)) {
346  final_ptr = mpm_ptr;
347  final_cnt = m_cnt;
348  goto final;
349  }
350 
351  /* not at end of the lists, update nonmpm. Mpm already
352  * updated in while loop above. */
353  nonmpm_ptr++;
354  nonmpm = *nonmpm_ptr;
355  }
356  }
357 
358  final: /* Only one list remaining. Just walk that list. */
359 
360  while (final_cnt-- > 0) {
361  id = *final_ptr++;
362  s = sig_array[id];
363 
364  /* As the mpm list can contain duplicates, check for that here. */
365  if (likely(id != previous_id)) {
366  *match_array++ = s;
367  previous_id = id;
368  }
369  }
370 
371  det_ctx->match_array_cnt = match_array - det_ctx->match_array;
372  DEBUG_VALIDATE_BUG_ON((det_ctx->pmq.rule_id_array_cnt + det_ctx->non_pf_id_cnt) < det_ctx->match_array_cnt);
373  PMQ_RESET(&det_ctx->pmq);
374 }
375 
376 /** \internal
377  * \brief build non-prefilter list based on the rule group list we've set.
378  */
379 static inline void DetectPrefilterBuildNonPrefilterList(
380  DetectEngineThreadCtx *det_ctx, const SignatureMask mask, const AppProto alproto)
381 {
382  for (uint32_t x = 0; x < det_ctx->non_pf_store_cnt; x++) {
383  /* only if the mask matches this rule can possibly match,
384  * so build the non_mpm array only for match candidates */
385  const SignatureMask rule_mask = det_ctx->non_pf_store_ptr[x].mask;
386  const AppProto rule_alproto = det_ctx->non_pf_store_ptr[x].alproto;
387  if ((rule_mask & mask) == rule_mask &&
388  (rule_alproto == 0 || AppProtoEquals(rule_alproto, alproto))) {
389  det_ctx->non_pf_id_array[det_ctx->non_pf_id_cnt++] = det_ctx->non_pf_store_ptr[x].id;
390  }
391  }
392 }
393 
394 /** \internal
395  * \brief select non-mpm list
396  * Based on the packet properties, select the non-mpm list to use
397  * \todo move non_pf_store* into scratchpad */
398 static inline void
399 DetectPrefilterSetNonPrefilterList(const Packet *p, DetectEngineThreadCtx *det_ctx, DetectRunScratchpad *scratch)
400 {
401  if ((p->proto == IPPROTO_TCP) && (p->tcph != NULL) && (p->tcph->th_flags & TH_SYN)) {
402  det_ctx->non_pf_store_ptr = scratch->sgh->non_pf_syn_store_array;
403  det_ctx->non_pf_store_cnt = scratch->sgh->non_pf_syn_store_cnt;
404  } else {
405  det_ctx->non_pf_store_ptr = scratch->sgh->non_pf_other_store_array;
406  det_ctx->non_pf_store_cnt = scratch->sgh->non_pf_other_store_cnt;
407  }
408  SCLogDebug("sgh non_pf ptr %p cnt %u (syn %p/%u, other %p/%u)",
409  det_ctx->non_pf_store_ptr, det_ctx->non_pf_store_cnt,
410  scratch->sgh->non_pf_syn_store_array, scratch->sgh->non_pf_syn_store_cnt,
412 }
413 
414 /** \internal
415  * \brief update flow's file tracking flags based on the detection engine
416  * A set of flags is prepared that is sent to the File API. The
417  File API may reject one or more based on the global force settings.
418  */
419 static inline void
420 DetectPostInspectFileFlagsUpdate(Flow *f, const SigGroupHead *sgh, uint8_t direction)
421 {
422  uint16_t flow_file_flags = FLOWFILE_INIT;
423 
424  if (sgh == NULL) {
425  SCLogDebug("requesting disabling all file features for flow");
426  flow_file_flags = FLOWFILE_NONE;
427  } else {
428  if (sgh->filestore_cnt == 0) {
429  SCLogDebug("requesting disabling filestore for flow");
430  flow_file_flags |= (FLOWFILE_NO_STORE_TS|FLOWFILE_NO_STORE_TC);
431  }
432 #ifdef HAVE_MAGIC
433  if (!(sgh->flags & SIG_GROUP_HEAD_HAVEFILEMAGIC)) {
434  SCLogDebug("requesting disabling magic for flow");
435  flow_file_flags |= (FLOWFILE_NO_MAGIC_TS|FLOWFILE_NO_MAGIC_TC);
436  }
437 #endif
438  if (!(sgh->flags & SIG_GROUP_HEAD_HAVEFILEMD5)) {
439  SCLogDebug("requesting disabling md5 for flow");
440  flow_file_flags |= (FLOWFILE_NO_MD5_TS|FLOWFILE_NO_MD5_TC);
441  }
442  if (!(sgh->flags & SIG_GROUP_HEAD_HAVEFILESHA1)) {
443  SCLogDebug("requesting disabling sha1 for flow");
444  flow_file_flags |= (FLOWFILE_NO_SHA1_TS|FLOWFILE_NO_SHA1_TC);
445  }
446  if (!(sgh->flags & SIG_GROUP_HEAD_HAVEFILESHA256)) {
447  SCLogDebug("requesting disabling sha256 for flow");
448  flow_file_flags |= (FLOWFILE_NO_SHA256_TS|FLOWFILE_NO_SHA256_TC);
449  }
450  if (!(sgh->flags & SIG_GROUP_HEAD_HAVEFILESIZE)) {
451  SCLogDebug("requesting disabling filesize for flow");
452  flow_file_flags |= (FLOWFILE_NO_SIZE_TS|FLOWFILE_NO_SIZE_TC);
453  }
454  }
455  if (flow_file_flags != 0) {
456  FileUpdateFlowFileFlags(f, flow_file_flags, direction);
457  }
458 }
459 
460 static inline void
461 DetectRunPostGetFirstRuleGroup(const Packet *p, Flow *pflow, const SigGroupHead *sgh)
462 {
463  if ((p->flowflags & FLOW_PKT_TOSERVER) && !(pflow->flags & FLOW_SGH_TOSERVER)) {
464  /* first time we see this toserver sgh, store it */
465  pflow->sgh_toserver = sgh;
466  pflow->flags |= FLOW_SGH_TOSERVER;
467 
468  if (p->proto == IPPROTO_TCP && (sgh == NULL || !(sgh->flags & SIG_GROUP_HEAD_HAVERAWSTREAM))) {
469  if (pflow->protoctx != NULL) {
470  TcpSession *ssn = pflow->protoctx;
471  SCLogDebug("STREAMTCP_STREAM_FLAG_DISABLE_RAW ssn.client");
473  }
474  }
475 
476  DetectPostInspectFileFlagsUpdate(pflow,
477  pflow->sgh_toserver, STREAM_TOSERVER);
478 
479  } else if ((p->flowflags & FLOW_PKT_TOCLIENT) && !(pflow->flags & FLOW_SGH_TOCLIENT)) {
480  pflow->sgh_toclient = sgh;
481  pflow->flags |= FLOW_SGH_TOCLIENT;
482 
483  if (p->proto == IPPROTO_TCP && (sgh == NULL || !(sgh->flags & SIG_GROUP_HEAD_HAVERAWSTREAM))) {
484  if (pflow->protoctx != NULL) {
485  TcpSession *ssn = pflow->protoctx;
486  SCLogDebug("STREAMTCP_STREAM_FLAG_DISABLE_RAW ssn.server");
488  }
489  }
490 
491  DetectPostInspectFileFlagsUpdate(pflow,
492  pflow->sgh_toclient, STREAM_TOCLIENT);
493  }
494 }
495 
496 static inline void DetectRunGetRuleGroup(
497  const DetectEngineCtx *de_ctx,
498  Packet * const p, Flow * const pflow,
499  DetectRunScratchpad *scratch)
500 {
501  const SigGroupHead *sgh = NULL;
502 
503  if (pflow) {
504  bool use_flow_sgh = false;
505  /* Get the stored sgh from the flow (if any). Make sure we're not using
506  * the sgh for icmp error packets part of the same stream. */
507  if (IP_GET_IPPROTO(p) == pflow->proto) { /* filter out icmp */
509  if ((p->flowflags & FLOW_PKT_TOSERVER) && (pflow->flags & FLOW_SGH_TOSERVER)) {
510  sgh = pflow->sgh_toserver;
511  SCLogDebug("sgh = pflow->sgh_toserver; => %p", sgh);
512  use_flow_sgh = true;
513  } else if ((p->flowflags & FLOW_PKT_TOCLIENT) && (pflow->flags & FLOW_SGH_TOCLIENT)) {
514  sgh = pflow->sgh_toclient;
515  SCLogDebug("sgh = pflow->sgh_toclient; => %p", sgh);
516  use_flow_sgh = true;
517  }
519  }
520 
521  if (!(use_flow_sgh)) {
525 
526  /* HACK: prevent the wrong sgh (or NULL) from being stored in the
527  * flow's sgh pointers */
529  ; /* no-op */
530  } else {
531  /* store the found sgh (or NULL) in the flow to save us
532  * from looking it up again for the next packet.
533  * Also run other tasks */
534  DetectRunPostGetFirstRuleGroup(p, pflow, sgh);
535  }
536  }
537  } else { /* p->flags & PKT_HAS_FLOW */
538  /* no flow */
539 
543  }
544 
545  scratch->sgh = sgh;
546 }
547 
548 static void DetectRunInspectIPOnly(ThreadVars *tv, const DetectEngineCtx *de_ctx,
549  DetectEngineThreadCtx *det_ctx,
550  Flow * const pflow, Packet * const p)
551 {
552  if (pflow) {
553  /* set the iponly stuff */
554  if (pflow->flags & FLOW_TOCLIENT_IPONLY_SET)
556  if (pflow->flags & FLOW_TOSERVER_IPONLY_SET)
558 
561  {
562  SCLogDebug("testing against \"ip-only\" signatures");
563 
565  IPOnlyMatchPacket(tv, de_ctx, det_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p);
567 
568  /* save in the flow that we scanned this direction... */
569  FlowSetIPOnlyFlag(pflow, p->flowflags & FLOW_PKT_TOSERVER ? 1 : 0);
570  }
571  } else { /* p->flags & PKT_HAS_FLOW */
572  /* no flow */
573 
574  /* Even without flow we should match the packet src/dst */
576  IPOnlyMatchPacket(tv, de_ctx, det_ctx, &de_ctx->io_ctx,
577  &det_ctx->io_ctx, p);
579  }
580 }
581 
582 /* returns 0 if no match, 1 if match */
583 static inline int DetectRunInspectRuleHeader(
584  const Packet *p,
585  const Flow *f,
586  const Signature *s,
587  const uint32_t sflags,
588  const uint8_t s_proto_flags)
589 {
590  /* check if this signature has a requirement for flowvars of some type
591  * and if so, if we actually have any in the flow. If not, the sig
592  * can't match and we skip it. */
593  if ((p->flags & PKT_HAS_FLOW) && (sflags & SIG_FLAG_REQUIRE_FLOWVAR)) {
594  DEBUG_VALIDATE_BUG_ON(f == NULL);
595 
596  int m = f->flowvar ? 1 : 0;
597 
598  /* no flowvars? skip this sig */
599  if (m == 0) {
600  SCLogDebug("skipping sig as the flow has no flowvars and sig "
601  "has SIG_FLAG_REQUIRE_FLOWVAR flag set.");
602  return 0;
603  }
604  }
605 
606  if ((s_proto_flags & DETECT_PROTO_IPV4) && !PKT_IS_IPV4(p)) {
607  SCLogDebug("ip version didn't match");
608  return 0;
609  }
610  if ((s_proto_flags & DETECT_PROTO_IPV6) && !PKT_IS_IPV6(p)) {
611  SCLogDebug("ip version didn't match");
612  return 0;
613  }
614 
615  if (DetectProtoContainsProto(&s->proto, IP_GET_IPPROTO(p)) == 0) {
616  SCLogDebug("proto didn't match");
617  return 0;
618  }
619 
620  /* check the source & dst port in the sig */
621  if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP || p->proto == IPPROTO_SCTP) {
622  if (!(sflags & SIG_FLAG_DP_ANY)) {
623  if (p->flags & PKT_IS_FRAGMENT)
624  return 0;
625  DetectPort *dport = DetectPortLookupGroup(s->dp,p->dp);
626  if (dport == NULL) {
627  SCLogDebug("dport didn't match.");
628  return 0;
629  }
630  }
631  if (!(sflags & SIG_FLAG_SP_ANY)) {
632  if (p->flags & PKT_IS_FRAGMENT)
633  return 0;
634  DetectPort *sport = DetectPortLookupGroup(s->sp,p->sp);
635  if (sport == NULL) {
636  SCLogDebug("sport didn't match.");
637  return 0;
638  }
639  }
640  } else if ((sflags & (SIG_FLAG_DP_ANY|SIG_FLAG_SP_ANY)) != (SIG_FLAG_DP_ANY|SIG_FLAG_SP_ANY)) {
641  SCLogDebug("port-less protocol and sig needs ports");
642  return 0;
643  }
644 
645  /* check the destination address */
646  if (!(sflags & SIG_FLAG_DST_ANY)) {
647  if (PKT_IS_IPV4(p)) {
649  return 0;
650  } else if (PKT_IS_IPV6(p)) {
652  return 0;
653  }
654  }
655  /* check the source address */
656  if (!(sflags & SIG_FLAG_SRC_ANY)) {
657  if (PKT_IS_IPV4(p)) {
659  return 0;
660  } else if (PKT_IS_IPV6(p)) {
662  return 0;
663  }
664  }
665 
666  return 1;
667 }
668 
669 /** \internal
670  * \brief run packet/stream prefilter engines
671  */
672 static inline void DetectRunPrefilterPkt(
673  ThreadVars *tv,
675  DetectEngineThreadCtx *det_ctx,
676  Packet *p,
677  DetectRunScratchpad *scratch
678 )
679 {
680  DetectPrefilterSetNonPrefilterList(p, det_ctx, scratch);
681 
682  /* create our prefilter mask */
683  PacketCreateMask(p, &scratch->pkt_mask, scratch->alproto, scratch->app_decoder_events);
684 
685  /* build and prefilter non_pf list against the mask of the packet */
687  det_ctx->non_pf_id_cnt = 0;
688  if (likely(det_ctx->non_pf_store_cnt > 0)) {
689  DetectPrefilterBuildNonPrefilterList(det_ctx, scratch->pkt_mask, scratch->alproto);
690  }
692 
693  /* run the prefilter engines */
694  Prefilter(det_ctx, scratch->sgh, p, scratch->flow_flags);
695  /* create match list if we have non-pf and/or pf */
696  if (det_ctx->non_pf_store_cnt || det_ctx->pmq.rule_id_array_cnt) {
697 #ifdef PROFILING
698  if (tv) {
699  StatsAddUI64(tv, det_ctx->counter_mpm_list, (uint64_t)det_ctx->pmq.rule_id_array_cnt);
700  }
701 #endif
703  DetectPrefilterMergeSort(de_ctx, det_ctx);
705  }
706 
707 #ifdef PROFILING
708  if (tv) {
710  (uint64_t)det_ctx->non_pf_store_cnt);
711  /* non mpm sigs after mask prefilter */
713  (uint64_t)det_ctx->non_pf_id_cnt);
714  }
715 #endif
716 }
717 
718 static inline void DetectRulePacketRules(
719  ThreadVars * const tv,
720  DetectEngineCtx * const de_ctx,
721  DetectEngineThreadCtx * const det_ctx,
722  Packet * const p,
723  Flow * const pflow,
724  const DetectRunScratchpad *scratch
725 )
726 {
727  const Signature *s = NULL;
728  const Signature *next_s = NULL;
729 
730  /* inspect the sigs against the packet */
731  /* Prefetch the next signature. */
732  SigIntId match_cnt = det_ctx->match_array_cnt;
733 #ifdef PROFILING
734  if (tv) {
736  (uint64_t)match_cnt);
737  }
738 #endif
739  Signature **match_array = det_ctx->match_array;
740 
741  SGH_PROFILING_RECORD(det_ctx, scratch->sgh);
742 #ifdef PROFILING
743  if (match_cnt >= de_ctx->profile_match_logging_threshold)
744  RulesDumpMatchArray(det_ctx, scratch->sgh, p);
745 #endif
746 
747  uint32_t sflags, next_sflags = 0;
748  if (match_cnt) {
749  next_s = *match_array++;
750  next_sflags = next_s->flags;
751  }
752  while (match_cnt--) {
754  uint8_t alert_flags = 0;
755 #ifdef PROFILING
756  bool smatch = false; /* signature match */
757 #endif
758  s = next_s;
759  sflags = next_sflags;
760  if (match_cnt) {
761  next_s = *match_array++;
762  next_sflags = next_s->flags;
763  }
764  const uint8_t s_proto_flags = s->proto.flags;
765 
766  SCLogDebug("inspecting signature id %"PRIu32"", s->id);
767 
768  if (s->app_inspect != NULL) {
769  goto next; // handle sig in DetectRunTx
770  }
771  if (s->frame_inspect != NULL) {
772  goto next; // handle sig in DetectRunFrame
773  }
774 
775  /* don't run mask check for stateful rules.
776  * There we depend on prefilter */
777  if ((s->mask & scratch->pkt_mask) != s->mask) {
778  SCLogDebug("mask mismatch %x & %x != %x", s->mask, scratch->pkt_mask, s->mask);
779  goto next;
780  }
781 
782  if (SigDsizePrefilter(p, s, sflags))
783  goto next;
784 
785  /* if the sig has alproto and the session as well they should match */
786  if (likely(sflags & SIG_FLAG_APPLAYER)) {
787  if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, scratch->alproto)) {
788  SCLogDebug("alproto mismatch");
789  goto next;
790  }
791  }
792 
793  if (DetectRunInspectRuleHeader(p, pflow, s, sflags, s_proto_flags) == 0) {
794  goto next;
795  }
796 
797  if (DetectEnginePktInspectionRun(tv, det_ctx, s, pflow, p, &alert_flags) == false) {
798  goto next;
799  }
800 
801 #ifdef PROFILING
802  smatch = true;
803 #endif
804  DetectRunPostMatch(tv, det_ctx, p, s);
805 
806  AlertQueueAppend(det_ctx, s, p, 0, alert_flags);
807 next:
808  DetectVarProcessList(det_ctx, pflow, p);
809  DetectReplaceFree(det_ctx);
810  RULE_PROFILING_END(det_ctx, s, smatch, p);
811 
812  det_ctx->flags = 0;
813  continue;
814  }
815 }
816 
817 static DetectRunScratchpad DetectRunSetup(
818  const DetectEngineCtx *de_ctx,
819  DetectEngineThreadCtx *det_ctx,
820  Packet * const p, Flow * const pflow)
821 {
822  AppProto alproto = ALPROTO_UNKNOWN;
823  uint8_t flow_flags = 0; /* flow/state flags */
824  bool app_decoder_events = false;
825 
827 
828 #ifdef UNITTESTS
829  p->alerts.cnt = 0;
830  p->alerts.discarded = 0;
831  p->alerts.suppressed = 0;
832 #endif
833  det_ctx->filestore_cnt = 0;
834  det_ctx->base64_decoded_len = 0;
835  det_ctx->raw_stream_progress = 0;
836  det_ctx->match_array_cnt = 0;
837 
838  det_ctx->alert_queue_size = 0;
839  p->alerts.drop.action = 0;
840 
841 #ifdef DEBUG
842  if (p->flags & PKT_STREAM_ADD) {
843  det_ctx->pkt_stream_add_cnt++;
844  }
845 #endif
846 
847  /* grab the protocol state we will detect on */
848  if (p->flags & PKT_HAS_FLOW) {
849  DEBUG_VALIDATE_BUG_ON(pflow == NULL);
850 
851  if (p->flowflags & FLOW_PKT_TOSERVER) {
852  flow_flags = STREAM_TOSERVER;
853  SCLogDebug("flag STREAM_TOSERVER set");
854  } else if (p->flowflags & FLOW_PKT_TOCLIENT) {
855  flow_flags = STREAM_TOCLIENT;
856  SCLogDebug("flag STREAM_TOCLIENT set");
857  }
858  SCLogDebug("p->flowflags 0x%02x", p->flowflags);
859 
860  if (p->flags & PKT_STREAM_EOF) {
861  flow_flags |= STREAM_EOF;
862  SCLogDebug("STREAM_EOF set");
863  }
864 
865  /* store tenant_id in the flow so that we can use it
866  * for creating pseudo packets */
867  if (p->tenant_id > 0 && pflow->tenant_id == 0) {
868  pflow->tenant_id = p->tenant_id;
869  }
870 
871  /* live ruleswap check for flow updates */
872  if (pflow->de_ctx_version == 0) {
873  /* first time this flow is inspected, set id */
874  pflow->de_ctx_version = de_ctx->version;
875  } else if (pflow->de_ctx_version != de_ctx->version) {
876  /* first time we inspect flow with this de_ctx, reset */
877  pflow->flags &= ~FLOW_SGH_TOSERVER;
878  pflow->flags &= ~FLOW_SGH_TOCLIENT;
879  pflow->sgh_toserver = NULL;
880  pflow->sgh_toclient = NULL;
881 
882  pflow->de_ctx_version = de_ctx->version;
883  GenericVarFree(pflow->flowvar);
884  pflow->flowvar = NULL;
885 
887  }
888 
889  /* Retrieve the app layer state and protocol and the tcp reassembled
890  * stream chunks. */
891  if ((p->proto == IPPROTO_TCP && (p->flags & PKT_STREAM_EST)) ||
892  (p->proto == IPPROTO_UDP) ||
894  {
895  /* update flow flags with knowledge on disruptions */
896  flow_flags = FlowGetDisruptionFlags(pflow, flow_flags);
897  alproto = FlowGetAppProtocol(pflow);
898  if (p->proto == IPPROTO_TCP && pflow->protoctx &&
901  flow_flags |= STREAM_FLUSH;
902  }
903  SCLogDebug("alproto %u", alproto);
904  } else {
905  SCLogDebug("packet doesn't have established flag set (proto %d)", p->proto);
906  }
907 
908  app_decoder_events = AppLayerParserHasDecoderEvents(pflow->alparser);
909  }
910 
911  DetectRunScratchpad pad = { alproto, flow_flags, app_decoder_events, NULL, 0 };
913  return pad;
914 }
915 
916 static inline void DetectRunPostRules(
917  ThreadVars *tv,
919  DetectEngineThreadCtx *det_ctx,
920  Packet * const p,
921  Flow * const pflow,
922  DetectRunScratchpad *scratch)
923 {
924  /* see if we need to increment the inspect_id and reset the de_state */
925  if (pflow && pflow->alstate) {
928  scratch->flow_flags, (scratch->sgh == NULL));
930  }
931 
932  /* so now let's iterate the alerts and remove the ones after a pass rule
933  * matched (if any). This is done inside PacketAlertFinalize() */
934  /* PR: installed "tag" keywords are handled after the threshold inspection */
935 
937  PacketAlertFinalize(de_ctx, det_ctx, p);
938  if (p->alerts.cnt > 0) {
939  StatsAddUI64(tv, det_ctx->counter_alerts, (uint64_t)p->alerts.cnt);
940  }
941  if (p->alerts.discarded > 0) {
942  StatsAddUI64(tv, det_ctx->counter_alerts_overflow, (uint64_t)p->alerts.discarded);
943  }
944  if (p->alerts.suppressed > 0) {
945  StatsAddUI64(tv, det_ctx->counter_alerts_suppressed, (uint64_t)p->alerts.suppressed);
946  }
948 }
949 
950 static void DetectRunCleanup(DetectEngineThreadCtx *det_ctx,
951  Packet *p, Flow * const pflow)
952 {
954  InspectionBufferClean(det_ctx);
955 
956  if (pflow != NULL) {
957  /* update inspected tracker for raw reassembly */
958  if (p->proto == IPPROTO_TCP && pflow->protoctx != NULL &&
961  det_ctx->raw_stream_progress);
962  }
963  }
965  SCReturn;
966 }
967 
969 {
971  det_ctx->tx_candidates = SCCalloc(size, sizeof(RuleMatchCandidateTx));
972  if (det_ctx->tx_candidates == NULL) {
973  FatalError(SC_ERR_MEM_ALLOC, "failed to allocate %"PRIu64" bytes",
974  (uint64_t)(size * sizeof(RuleMatchCandidateTx)));
975  }
976  det_ctx->tx_candidates_size = size;
977  SCLogDebug("array initialized to %u elements (%"PRIu64" bytes)",
978  size, (uint64_t)(size * sizeof(RuleMatchCandidateTx)));
979 }
980 
982 {
983  SCFree(det_ctx->tx_candidates);
984  det_ctx->tx_candidates_size = 0;
985 }
986 
987 /* if size >= cur_space */
988 static inline bool RuleMatchCandidateTxArrayHasSpace(const DetectEngineThreadCtx *det_ctx,
989  const uint32_t need)
990 {
991  if (det_ctx->tx_candidates_size >= need)
992  return 1;
993  return 0;
994 }
995 
996 /* realloc */
997 static int RuleMatchCandidateTxArrayExpand(DetectEngineThreadCtx *det_ctx, const uint32_t needed)
998 {
999  const uint32_t old_size = det_ctx->tx_candidates_size;
1000  uint32_t new_size = needed;
1001  void *ptmp = SCRealloc(det_ctx->tx_candidates, (new_size * sizeof(RuleMatchCandidateTx)));
1002  if (ptmp == NULL) {
1003  FatalError(SC_ERR_MEM_ALLOC, "failed to expand to %"PRIu64" bytes",
1004  (uint64_t)(new_size * sizeof(RuleMatchCandidateTx)));
1005  // TODO can this be handled more gracefully?
1006  }
1007  det_ctx->tx_candidates = ptmp;
1008  det_ctx->tx_candidates_size = new_size;
1009  SCLogDebug("array expanded from %u to %u elements (%"PRIu64" bytes -> %"PRIu64" bytes)",
1010  old_size, new_size, (uint64_t)(old_size * sizeof(RuleMatchCandidateTx)),
1011  (uint64_t)(new_size * sizeof(RuleMatchCandidateTx))); (void)old_size;
1012  return 1;
1013 }
1014 
1015 /** \internal
1016  * \brief sort helper for sorting match candidates by id: ascending
1017  *
1018  * The id field is set from Signature::num, so we sort the candidates to match the signature
1019  * sort order (ascending), where candidates that have flags go first.
1020  */
1021 static int
1022 DetectRunTxSortHelper(const void *a, const void *b)
1023 {
1024  const RuleMatchCandidateTx *s0 = a;
1025  const RuleMatchCandidateTx *s1 = b;
1026  if (s1->id == s0->id) {
1027  if (s1->flags && !s0->flags)
1028  return 1;
1029  else if (!s1->flags && s0->flags)
1030  return -1;
1031  return 0;
1032  } else
1033  return s0->id > s1->id ? 1 : -1;
1034 }
1035 
1036 #if 0
1037 #define TRACE_SID_TXS(sid,txs,...) \
1038  do { \
1039  char _trace_buf[2048]; \
1040  snprintf(_trace_buf, sizeof(_trace_buf), __VA_ARGS__); \
1041  SCLogNotice("%p/%"PRIu64"/%u: %s", txs->tx_ptr, txs->tx_id, sid, _trace_buf); \
1042  } while(0)
1043 #else
1044 #define TRACE_SID_TXS(sid,txs,...)
1045 #endif
1046 
1047 /** \internal
1048  * \brief inspect a rule against a transaction
1049  *
1050  * Inspect a rule. New detection or continued stateful
1051  * detection.
1052  *
1053  * \param stored_flags pointer to stored flags or NULL.
1054  * If stored_flags is set it means we're continueing
1055  * inspection from an earlier run.
1056  *
1057  * \retval bool true sig matched, false didn't match
1058  */
1059 static bool DetectRunTxInspectRule(ThreadVars *tv,
1061  DetectEngineThreadCtx *det_ctx,
1062  Packet *p,
1063  Flow *f,
1064  const uint8_t in_flow_flags, // direction, EOF, etc
1065  void *alstate,
1066  DetectTransaction *tx,
1067  const Signature *s,
1068  uint32_t *stored_flags,
1069  RuleMatchCandidateTx *can,
1070  DetectRunScratchpad *scratch)
1071 {
1072  uint8_t flow_flags = in_flow_flags;
1073  const int direction = (flow_flags & STREAM_TOSERVER) ? 0 : 1;
1074  uint32_t inspect_flags = stored_flags ? *stored_flags : 0;
1075  int total_matches = 0;
1076  uint16_t file_no_match = 0;
1077  bool retval = false;
1078  bool mpm_before_progress = false; // is mpm engine before progress?
1079  bool mpm_in_progress = false; // is mpm engine in a buffer we will revisit?
1080 
1081  /* see if we want to pass on the FLUSH flag */
1082  if ((s->flags & SIG_FLAG_FLUSH) == 0)
1083  flow_flags &=~ STREAM_FLUSH;
1084 
1085  TRACE_SID_TXS(s->id, tx, "starting %s", direction ? "toclient" : "toserver");
1086  TRACE_SID_TXS(s->id, tx, "FLUSH? %s", (flow_flags & STREAM_FLUSH)?"true":"false");
1087 
1088  /* for a new inspection we inspect pkt header and packet matches */
1089  if (likely(stored_flags == NULL)) {
1090  TRACE_SID_TXS(s->id, tx, "first inspect, run packet matches");
1091  if (DetectRunInspectRuleHeader(p, f, s, s->flags, s->proto.flags) == 0) {
1092  TRACE_SID_TXS(s->id, tx, "DetectRunInspectRuleHeader() no match");
1093  return false;
1094  }
1095  if (DetectEnginePktInspectionRun(tv, det_ctx, s, f, p, NULL) == false) {
1096  TRACE_SID_TXS(s->id, tx, "DetectEnginePktInspectionRun no match");
1097  return false;
1098  }
1099  /* stream mpm and negated mpm sigs can end up here with wrong proto */
1100  if (!(AppProtoEquals(s->alproto, f->alproto) || s->alproto == ALPROTO_UNKNOWN)) {
1101  TRACE_SID_TXS(s->id, tx, "alproto mismatch");
1102  return false;
1103  }
1104  }
1105 
1106  const DetectEngineAppInspectionEngine *engine = s->app_inspect;
1107  while (engine != NULL) { // TODO could be do {} while as s->app_inspect cannot be null
1108  TRACE_SID_TXS(s->id, tx, "engine %p inspect_flags %x", engine, inspect_flags);
1109  if (!(inspect_flags & BIT_U32(engine->id)) &&
1110  direction == engine->dir)
1111  {
1112  const bool skip_engine = (engine->alproto != 0 && engine->alproto != f->alproto);
1113  /* special case: file_data on 'alert tcp' will have engines
1114  * in the list that are not for us. */
1115  if (unlikely(skip_engine)) {
1116  engine = engine->next;
1117  continue;
1118  }
1119 
1120  /* engines are sorted per progress, except that the one with
1121  * mpm/prefilter enabled is first */
1122  if (tx->tx_progress < engine->progress) {
1123  SCLogDebug("tx progress %d < engine progress %d",
1124  tx->tx_progress, engine->progress);
1125  break;
1126  }
1127  if (engine->mpm) {
1128  if (tx->tx_progress > engine->progress) {
1129  TRACE_SID_TXS(s->id, tx,
1130  "engine->mpm: t->tx_progress %u > engine->progress %u, so set "
1131  "mpm_before_progress",
1132  tx->tx_progress, engine->progress);
1133  mpm_before_progress = true;
1134  } else if (tx->tx_progress == engine->progress) {
1135  TRACE_SID_TXS(s->id, tx,
1136  "engine->mpm: t->tx_progress %u == engine->progress %u, so set "
1137  "mpm_in_progress",
1138  tx->tx_progress, engine->progress);
1139  mpm_in_progress = true;
1140  }
1141  }
1142 
1143  /* run callback: but bypass stream callback if we can */
1144  uint8_t match;
1145  if (unlikely(engine->stream && can->stream_stored)) {
1146  match = can->stream_result;
1147  TRACE_SID_TXS(s->id, tx, "stream skipped, stored result %d used instead", match);
1148  } else {
1149  KEYWORD_PROFILING_SET_LIST(det_ctx, engine->sm_list);
1150  DEBUG_VALIDATE_BUG_ON(engine->v2.Callback == NULL);
1151  match = engine->v2.Callback(
1152  de_ctx, det_ctx, engine, s, f, flow_flags, alstate, tx->tx_ptr, tx->tx_id);
1153  TRACE_SID_TXS(s->id, tx, "engine %p match %d", engine, match);
1154  if (engine->stream) {
1155  can->stream_stored = true;
1156  can->stream_result = match;
1157  TRACE_SID_TXS(s->id, tx, "stream ran, store result %d for next tx (if any)", match);
1158  }
1159  }
1160  if (match == DETECT_ENGINE_INSPECT_SIG_MATCH) {
1161  inspect_flags |= BIT_U32(engine->id);
1162  engine = engine->next;
1163  total_matches++;
1164  continue;
1165  } else if (match == DETECT_ENGINE_INSPECT_SIG_MATCH_MORE_FILES) {
1166  /* if the file engine matched, but indicated more
1167  * files are still in progress, we don't set inspect
1168  * flags as these would end inspection for this tx */
1169  engine = engine->next;
1170  total_matches++;
1171  continue;
1172  } else if (match == DETECT_ENGINE_INSPECT_SIG_CANT_MATCH) {
1173  inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
1174  inspect_flags |= BIT_U32(engine->id);
1175  } else if (match == DETECT_ENGINE_INSPECT_SIG_CANT_MATCH_FILES) {
1176  inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
1177  inspect_flags |= BIT_U32(engine->id);
1178  file_no_match = 1;
1179  }
1180  /* implied DETECT_ENGINE_INSPECT_SIG_NO_MATCH */
1181  if (engine->mpm && mpm_before_progress) {
1182  inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
1183  inspect_flags |= BIT_U32(engine->id);
1184  }
1185  break;
1186  }
1187  engine = engine->next;
1188  }
1189  TRACE_SID_TXS(s->id, tx, "inspect_flags %x, total_matches %u, engine %p",
1190  inspect_flags, total_matches, engine);
1191 
1192  if (engine == NULL && total_matches) {
1193  inspect_flags |= DE_STATE_FLAG_FULL_INSPECT;
1194  TRACE_SID_TXS(s->id, tx, "MATCH");
1195  retval = true;
1196  }
1197 
1198  if (stored_flags) {
1199  *stored_flags = inspect_flags;
1200  TRACE_SID_TXS(s->id, tx, "continue inspect flags %08x", inspect_flags);
1201  } else {
1202  // store... or? If tx is done we might not want to come back to this tx
1203 
1204  // also... if mpmid tracking is enabled, we won't do a sig again for this tx...
1205  TRACE_SID_TXS(s->id, tx, "start inspect flags %08x", inspect_flags);
1206  if (inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH) {
1207  if (file_no_match) {
1208  /* if we have a mismatch on a file sig, we need to keep state.
1209  * We may get another file on the same tx (for http and smtp
1210  * at least), so for a new file we need to re-eval the sig.
1211  * Thoughts / TODO:
1212  * - not for some protos that have 1 file per tx (e.g. nfs)
1213  * - maybe we only need this for file sigs that mix with
1214  * other matches? E.g. 'POST + filename', is different than
1215  * just 'filename'.
1216  */
1217  DetectRunStoreStateTx(scratch->sgh, f, tx->tx_ptr, tx->tx_id, s,
1218  inspect_flags, flow_flags, file_no_match);
1219  }
1220  } else if ((inspect_flags & DE_STATE_FLAG_FULL_INSPECT) && mpm_before_progress) {
1221  TRACE_SID_TXS(s->id, tx, "no need to store match sig, "
1222  "mpm won't trigger for it anymore");
1223 
1224  if (inspect_flags & DE_STATE_FLAG_FILE_INSPECT) {
1225  TRACE_SID_TXS(s->id, tx, "except that for new files, "
1226  "we may have to revisit anyway");
1227  DetectRunStoreStateTx(scratch->sgh, f, tx->tx_ptr, tx->tx_id, s,
1228  inspect_flags, flow_flags, file_no_match);
1229  }
1230  } else if ((inspect_flags & DE_STATE_FLAG_FULL_INSPECT) == 0 && mpm_in_progress) {
1231  TRACE_SID_TXS(s->id, tx, "no need to store no-match sig, "
1232  "mpm will revisit it");
1233  } else {
1234  TRACE_SID_TXS(s->id, tx, "storing state: flags %08x", inspect_flags);
1235  DetectRunStoreStateTx(scratch->sgh, f, tx->tx_ptr, tx->tx_id, s,
1236  inspect_flags, flow_flags, file_no_match);
1237  }
1238  }
1239 
1240  return retval;
1241 }
1242 
1243 /** \internal
1244  * \brief get a DetectTransaction object
1245  * \retval struct filled with relevant info or all nulls/0s
1246  */
1247 static DetectTransaction GetDetectTx(const uint8_t ipproto, const AppProto alproto,
1248  void *alstate, const uint64_t tx_id, void *tx_ptr, const int tx_end_state,
1249  const uint8_t flow_flags)
1250 {
1251  uint64_t detect_flags;
1252  AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx_ptr);
1253  if (likely(txd != NULL)) {
1254  detect_flags = (flow_flags & STREAM_TOSERVER) ? txd->detect_flags_ts : txd->detect_flags_tc;
1255  } else {
1256  detect_flags = 0;
1257  }
1258  if (detect_flags & APP_LAYER_TX_INSPECTED_FLAG) {
1259  SCLogDebug("%"PRIu64" tx already fully inspected for %s. Flags %016"PRIx64,
1260  tx_id, flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
1261  detect_flags);
1262  DetectTransaction no_tx = { NULL, 0, NULL, NULL, 0, 0, 0, 0, 0, };
1263  return no_tx;
1264  }
1265 
1266  const int tx_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx_ptr, flow_flags);
1267  const int dir_int = (flow_flags & STREAM_TOSERVER) ? 0 : 1;
1268  DetectEngineState *tx_de_state = txd->de_state;
1269  DetectEngineStateDirection *tx_dir_state = tx_de_state ? &tx_de_state->dir_state[dir_int] : NULL;
1270  uint64_t prefilter_flags = detect_flags & APP_LAYER_TX_PREFILTER_MASK;
1272 
1273  DetectTransaction tx = {
1274  .tx_ptr = tx_ptr,
1275  .tx_id = tx_id,
1276  .tx_data_ptr = (struct AppLayerTxData *)txd,
1277  .de_state = tx_dir_state,
1278  .detect_flags = detect_flags,
1279  .prefilter_flags = prefilter_flags,
1280  .prefilter_flags_orig = prefilter_flags,
1281  .tx_progress = tx_progress,
1282  .tx_end_state = tx_end_state,
1283  };
1284  return tx;
1285 }
1286 
1287 static inline void StoreDetectFlags(DetectTransaction *tx, const uint8_t flow_flags,
1288  const uint8_t ipproto, const AppProto alproto, const uint64_t detect_flags)
1289 {
1291  if (likely(txd != NULL)) {
1292  if (flow_flags & STREAM_TOSERVER) {
1293  txd->detect_flags_ts = detect_flags;
1294  } else {
1295  txd->detect_flags_tc = detect_flags;
1296  }
1297  }
1298 }
1299 
1300 static void DetectRunTx(ThreadVars *tv,
1302  DetectEngineThreadCtx *det_ctx,
1303  Packet *p,
1304  Flow *f,
1305  DetectRunScratchpad *scratch)
1306 {
1307  const uint8_t flow_flags = scratch->flow_flags;
1308  const SigGroupHead * const sgh = scratch->sgh;
1309  void * const alstate = f->alstate;
1310  const uint8_t ipproto = f->proto;
1311  const AppProto alproto = f->alproto;
1312 
1313  const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
1314  uint64_t tx_id_min = AppLayerParserGetTransactionInspectId(f->alparser, flow_flags);
1315  const int tx_end_state = AppLayerParserGetStateProgressCompletionStatus(alproto, flow_flags);
1316 
1317  AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
1318  AppLayerGetTxIterState state;
1319  memset(&state, 0, sizeof(state));
1320 
1321  while (1) {
1322  AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, tx_id_min, total_txs, &state);
1323  if (ires.tx_ptr == NULL)
1324  break;
1325 
1326  DetectTransaction tx = GetDetectTx(ipproto, alproto,
1327  alstate, ires.tx_id, ires.tx_ptr, tx_end_state, flow_flags);
1328  if (tx.tx_ptr == NULL) {
1329  SCLogDebug("%p/%"PRIu64" no transaction to inspect",
1330  tx.tx_ptr, tx_id_min);
1331 
1332  tx_id_min++; // next (if any) run look for +1
1333  goto next;
1334  }
1335  tx_id_min = tx.tx_id + 1; // next look for cur + 1
1336 
1337  bool do_sort = false; // do we need to sort the tx candidate list?
1338  uint32_t array_idx = 0;
1339  uint32_t total_rules = det_ctx->match_array_cnt;
1340  total_rules += (tx.de_state ? tx.de_state->cnt : 0);
1341 
1342  /* run prefilter engines and merge results into a candidates array */
1343  if (sgh->tx_engines) {
1345  DetectRunPrefilterTx(det_ctx, sgh, p, ipproto, flow_flags, alproto,
1346  alstate, &tx);
1348  SCLogDebug("%p/%"PRIu64" rules added from prefilter: %u candidates",
1349  tx.tx_ptr, tx.tx_id, det_ctx->pmq.rule_id_array_cnt);
1350 
1351  total_rules += det_ctx->pmq.rule_id_array_cnt;
1352  if (!(RuleMatchCandidateTxArrayHasSpace(det_ctx, total_rules))) {
1353  RuleMatchCandidateTxArrayExpand(det_ctx, total_rules);
1354  }
1355 
1356  for (uint32_t i = 0; i < det_ctx->pmq.rule_id_array_cnt; i++) {
1357  const Signature *s = de_ctx->sig_array[det_ctx->pmq.rule_id_array[i]];
1358  const SigIntId id = s->num;
1359  det_ctx->tx_candidates[array_idx].s = s;
1360  det_ctx->tx_candidates[array_idx].id = id;
1361  det_ctx->tx_candidates[array_idx].flags = NULL;
1362  det_ctx->tx_candidates[array_idx].stream_reset = 0;
1363  array_idx++;
1364  }
1365  PMQ_RESET(&det_ctx->pmq);
1366  } else {
1367  if (!(RuleMatchCandidateTxArrayHasSpace(det_ctx, total_rules))) {
1368  RuleMatchCandidateTxArrayExpand(det_ctx, total_rules);
1369  }
1370  }
1371 
1372  /* merge 'state' rules from the regular prefilter */
1373  uint32_t x = array_idx;
1374  for (uint32_t i = 0; i < det_ctx->match_array_cnt; i++) {
1375  const Signature *s = det_ctx->match_array[i];
1376  if (s->app_inspect != NULL) {
1377  const SigIntId id = s->num;
1378  det_ctx->tx_candidates[array_idx].s = s;
1379  det_ctx->tx_candidates[array_idx].id = id;
1380  det_ctx->tx_candidates[array_idx].flags = NULL;
1381  det_ctx->tx_candidates[array_idx].stream_reset = 0;
1382  array_idx++;
1383 
1384  SCLogDebug("%p/%"PRIu64" rule %u (%u) added from 'match' list",
1385  tx.tx_ptr, tx.tx_id, s->id, id);
1386  }
1387  }
1388  do_sort = (array_idx > x); // sort if match added anything
1389  SCLogDebug("%p/%" PRIu64 " rules added from 'match' list: %u", tx.tx_ptr, tx.tx_id,
1390  array_idx - x);
1391 
1392  /* merge stored state into results */
1393  if (tx.de_state != NULL) {
1394  const uint32_t old = array_idx;
1395 
1396  /* if tx.de_state->flags has 'new file' set and sig below has
1397  * 'file inspected' flag, reset the file part of the state */
1398  const bool have_new_file = (tx.de_state->flags & DETECT_ENGINE_STATE_FLAG_FILE_NEW);
1399  if (have_new_file) {
1400  SCLogDebug("%p/%"PRIu64" destate: need to consider new file",
1401  tx.tx_ptr, tx.tx_id);
1403  }
1404 
1405  SigIntId state_cnt = 0;
1406  DeStateStore *tx_store = tx.de_state->head;
1407  for (; tx_store != NULL; tx_store = tx_store->next) {
1408  SCLogDebug("tx_store %p", tx_store);
1409 
1410  SigIntId store_cnt = 0;
1411  for (store_cnt = 0;
1412  store_cnt < DE_STATE_CHUNK_SIZE && state_cnt < tx.de_state->cnt;
1413  store_cnt++, state_cnt++)
1414  {
1415  DeStateStoreItem *item = &tx_store->store[store_cnt];
1416  SCLogDebug("rule id %u, inspect_flags %u", item->sid, item->flags);
1417  if (have_new_file && (item->flags & DE_STATE_FLAG_FILE_INSPECT)) {
1418  /* remove part of the state. File inspect engine will now
1419  * be able to run again */
1421  SCLogDebug("rule id %u, post file reset inspect_flags %u", item->sid, item->flags);
1422  }
1423  det_ctx->tx_candidates[array_idx].s = de_ctx->sig_array[item->sid];
1424  det_ctx->tx_candidates[array_idx].id = item->sid;
1425  det_ctx->tx_candidates[array_idx].flags = &item->flags;
1426  det_ctx->tx_candidates[array_idx].stream_reset = 0;
1427  array_idx++;
1428  }
1429  }
1430  do_sort |= (old && old != array_idx); // sort if continue list adds sids
1431  SCLogDebug("%p/%" PRIu64 " rules added from 'continue' list: %u", tx.tx_ptr, tx.tx_id,
1432  array_idx - old);
1433  }
1434  if (do_sort) {
1435  qsort(det_ctx->tx_candidates, array_idx, sizeof(RuleMatchCandidateTx),
1436  DetectRunTxSortHelper);
1437  }
1438 
1439 #ifdef PROFILING
1440  if (array_idx >= de_ctx->profile_match_logging_threshold)
1441  RulesDumpTxMatchArray(det_ctx, scratch->sgh, p, tx.tx_id, array_idx, x);
1442 #endif
1443  det_ctx->tx_id = tx.tx_id;
1444  det_ctx->tx_id_set = true;
1445  det_ctx->p = p;
1446 
1447 #ifdef DEBUG
1448  for (uint32_t i = 0; i < array_idx; i++) {
1449  RuleMatchCandidateTx *can = &det_ctx->tx_candidates[i];
1450  const Signature *s = det_ctx->tx_candidates[i].s;
1451  SCLogDebug("%u: sid %u flags %p", i, s->id, can->flags);
1452  }
1453 #endif
1454  /* run rules: inspect the match candidates */
1455  for (uint32_t i = 0; i < array_idx; i++) {
1456  RuleMatchCandidateTx *can = &det_ctx->tx_candidates[i];
1457  const Signature *s = det_ctx->tx_candidates[i].s;
1458  uint32_t *inspect_flags = det_ctx->tx_candidates[i].flags;
1459 
1460  /* deduplicate: rules_array is sorted, but not deduplicated:
1461  * both mpm and stored state could give us the same sid.
1462  * As they are back to back in that case we can check for it
1463  * here. We select the stored state one as that comes first
1464  * in the array. */
1465  while ((i + 1) < array_idx &&
1466  det_ctx->tx_candidates[i].s == det_ctx->tx_candidates[i + 1].s) {
1467  SCLogDebug("%p/%" PRIu64 " inspecting SKIP NEXT: sid %u (%u), flags %08x",
1468  tx.tx_ptr, tx.tx_id, s->id, s->num, inspect_flags ? *inspect_flags : 0);
1469  i++;
1470  }
1471 
1472  SCLogDebug("%p/%"PRIu64" inspecting: sid %u (%u), flags %08x",
1473  tx.tx_ptr, tx.tx_id, s->id, s->num, inspect_flags ? *inspect_flags : 0);
1474 
1475  if (inspect_flags) {
1477  SCLogDebug("%p/%"PRIu64" inspecting: sid %u (%u), flags %08x ALREADY COMPLETE",
1478  tx.tx_ptr, tx.tx_id, s->id, s->num, *inspect_flags);
1479  continue;
1480  }
1481  }
1482 
1483  if (inspect_flags) {
1484  /* continue previous inspection */
1485  SCLogDebug("%p/%"PRIu64" Continueing sid %u", tx.tx_ptr, tx.tx_id, s->id);
1486  } else {
1487  /* start new inspection */
1488  SCLogDebug("%p/%"PRIu64" Start sid %u", tx.tx_ptr, tx.tx_id, s->id);
1489  }
1490 
1491  /* call individual rule inspection */
1493  const int r = DetectRunTxInspectRule(tv, de_ctx, det_ctx, p, f, flow_flags,
1494  alstate, &tx, s, inspect_flags, can, scratch);
1495  if (r == 1) {
1496  /* match */
1497  DetectRunPostMatch(tv, det_ctx, p, s);
1498 
1499  const uint8_t alert_flags = (PACKET_ALERT_FLAG_STATE_MATCH | PACKET_ALERT_FLAG_TX);
1500  SCLogDebug("%p/%"PRIu64" sig %u (%u) matched", tx.tx_ptr, tx.tx_id, s->id, s->num);
1501  AlertQueueAppend(det_ctx, s, p, tx.tx_id, alert_flags);
1502  }
1503  DetectVarProcessList(det_ctx, p->flow, p);
1504  RULE_PROFILING_END(det_ctx, s, r, p);
1505  }
1506 
1507  det_ctx->tx_id = 0;
1508  det_ctx->tx_id_set = false;
1509  det_ctx->p = NULL;
1510 
1511  /* see if we have any updated state to store in the tx */
1512 
1513  uint64_t new_detect_flags = 0;
1514  /* this side of the tx is done */
1515  if (tx.tx_progress >= tx.tx_end_state) {
1516  new_detect_flags |= APP_LAYER_TX_INSPECTED_FLAG;
1517  SCLogDebug("%p/%"PRIu64" tx is done for direction %s. Flag %016"PRIx64,
1518  tx.tx_ptr, tx.tx_id,
1519  flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
1520  new_detect_flags);
1521  }
1522  if (tx.prefilter_flags != tx.prefilter_flags_orig) {
1523  new_detect_flags |= tx.prefilter_flags;
1525  SCLogDebug("%p/%"PRIu64" updated prefilter flags %016"PRIx64" "
1526  "(was: %016"PRIx64") for direction %s. Flag %016"PRIx64,
1528  flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
1529  new_detect_flags);
1530  }
1531  if (new_detect_flags != 0 &&
1532  (new_detect_flags | tx.detect_flags) != tx.detect_flags)
1533  {
1534  new_detect_flags |= tx.detect_flags;
1536  SCLogDebug("%p/%"PRIu64" Storing new flags %016"PRIx64" (was %016"PRIx64")",
1537  tx.tx_ptr, tx.tx_id, new_detect_flags, tx.detect_flags);
1538 
1539  StoreDetectFlags(&tx, flow_flags, ipproto, alproto, new_detect_flags);
1540  }
1541 next:
1542  InspectionBufferClean(det_ctx);
1543 
1544  if (!ires.has_next)
1545  break;
1546  }
1547 }
1548 
1549 static void DetectRunFrames(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
1550  Packet *p, Flow *f, DetectRunScratchpad *scratch)
1551 {
1552  const SigGroupHead *const sgh = scratch->sgh;
1553  const AppProto alproto = f->alproto;
1554 
1555  FramesContainer *frames_container = AppLayerFramesGetContainer(f);
1556  if (frames_container == NULL) {
1557  return;
1558  }
1559  Frames *frames;
1560  if (PKT_IS_TOSERVER(p)) {
1561  frames = &frames_container->toserver;
1562  } else {
1563  frames = &frames_container->toclient;
1564  }
1565 
1566  for (uint32_t idx = 0; idx < frames->cnt; idx++) {
1567  SCLogDebug("frame %u", idx);
1568  const Frame *frame = FrameGetByIndex(frames, idx);
1569  if (frame == NULL) {
1570  continue;
1571  }
1572 
1573  uint32_t array_idx = 0;
1574  uint32_t total_rules = det_ctx->match_array_cnt;
1575 
1576  /* run prefilter engines and merge results into a candidates array */
1577  if (sgh->frame_engines) {
1578  // PACKET_PROFILING_DETECT_START(p, PROF_DETECT_PF_TX);
1579  DetectRunPrefilterFrame(det_ctx, sgh, p, frames, frame, alproto, idx);
1580  // PACKET_PROFILING_DETECT_END(p, PROF_DETECT_PF_TX);
1581  SCLogDebug("%p/%" PRIi64 " rules added from prefilter: %u candidates", frame, frame->id,
1582  det_ctx->pmq.rule_id_array_cnt);
1583 
1584  total_rules += det_ctx->pmq.rule_id_array_cnt;
1585 
1586  if (!(RuleMatchCandidateTxArrayHasSpace(
1587  det_ctx, total_rules))) { // TODO is it safe to overload?
1588  RuleMatchCandidateTxArrayExpand(det_ctx, total_rules);
1589  }
1590 
1591  for (uint32_t i = 0; i < det_ctx->pmq.rule_id_array_cnt; i++) {
1592  const Signature *s = de_ctx->sig_array[det_ctx->pmq.rule_id_array[i]];
1593  const SigIntId id = s->num;
1594  det_ctx->tx_candidates[array_idx].s = s;
1595  det_ctx->tx_candidates[array_idx].id = id;
1596  det_ctx->tx_candidates[array_idx].flags = NULL;
1597  det_ctx->tx_candidates[array_idx].stream_reset = 0;
1598  array_idx++;
1599  }
1600  PMQ_RESET(&det_ctx->pmq);
1601  }
1602  /* merge 'state' rules from the regular prefilter */
1603  uint32_t x = array_idx;
1604  for (uint32_t i = 0; i < det_ctx->match_array_cnt; i++) {
1605  const Signature *s = det_ctx->match_array[i];
1606  if (s->frame_inspect != NULL) {
1607  const SigIntId id = s->num;
1608  det_ctx->tx_candidates[array_idx].s = s;
1609  det_ctx->tx_candidates[array_idx].id = id;
1610  det_ctx->tx_candidates[array_idx].flags = NULL;
1611  det_ctx->tx_candidates[array_idx].stream_reset = 0;
1612  array_idx++;
1613 
1614  SCLogDebug("%p/%" PRIi64 " rule %u (%u) added from 'match' list", frame, frame->id,
1615  s->id, id);
1616  }
1617  }
1618  SCLogDebug("%p/%" PRIi64 " rules added from 'match' list: %u", frame, frame->id,
1619  array_idx - x);
1620  (void)x;
1621 
1622  /* run rules: inspect the match candidates */
1623  for (uint32_t i = 0; i < array_idx; i++) {
1624  const Signature *s = det_ctx->tx_candidates[i].s;
1625 
1626  SCLogDebug("%p/%" PRIi64 " inspecting: sid %u (%u)", frame, frame->id, s->id, s->num);
1627 
1628  /* start new inspection */
1629  SCLogDebug("%p/%" PRIi64 " Start sid %u", frame, frame->id, s->id);
1630 
1631  /* call individual rule inspection */
1633  int r = DetectRunInspectRuleHeader(p, f, s, s->flags, s->proto.flags);
1634  if (r == 1) {
1635  r = DetectRunFrameInspectRule(tv, det_ctx, s, f, p, frames, frame, idx);
1636  if (r == 1) {
1637  /* match */
1638  DetectRunPostMatch(tv, det_ctx, p, s);
1639 
1640  const uint8_t alert_flags =
1643  det_ctx->frame_id = frame->id;
1644  SCLogDebug(
1645  "%p/%" PRIi64 " sig %u (%u) matched", frame, frame->id, s->id, s->num);
1646  AlertQueueAppend(det_ctx, s, p, frame->tx_id, alert_flags);
1647  }
1648  }
1649  DetectVarProcessList(det_ctx, p->flow, p);
1650  RULE_PROFILING_END(det_ctx, s, r, p);
1651  }
1652  InspectionBufferClean(det_ctx);
1653  }
1654 }
1655 
1656 static DetectEngineThreadCtx *GetTenantById(HashTable *h, uint32_t id)
1657 {
1658  /* technically we need to pass a DetectEngineThreadCtx struct with the
1659  * tentant_id member. But as that member is the first in the struct, we
1660  * can use the id directly. */
1661  return HashTableLookup(h, &id, 0);
1662 }
1663 
1664 static void DetectFlow(ThreadVars *tv,
1666  Packet *p)
1667 {
1668  Flow *const f = p->flow;
1669 
1670  if (p->flags & PKT_NOPACKET_INSPECTION) {
1671  /* hack: if we are in pass the entire flow mode, we need to still
1672  * update the inspect_id forward. So test for the condition here,
1673  * and call the update code if necessary. */
1674  const int pass = ((f->flags & FLOW_NOPACKET_INSPECTION));
1675  if (pass) {
1676  uint8_t flags = STREAM_FLAGS_FOR_PACKET(p);
1678  if (f->alstate) {
1680  }
1681  }
1682  SCLogDebug("p->pcap %"PRIu64": no detection on packet, "
1683  "PKT_NOPACKET_INSPECTION is set", p->pcap_cnt);
1684  return;
1685  }
1686 
1687  /* if flow is set to drop, we enforce that here */
1688  if (f->flags & FLOW_ACTION_DROP) {
1690  SCReturn;
1691  }
1692 
1693  /* see if the packet matches one or more of the sigs */
1694  (void)DetectRun(tv, de_ctx, det_ctx, p);
1695 }
1696 
1697 
1698 static void DetectNoFlow(ThreadVars *tv,
1700  Packet *p)
1701 {
1702  /* No need to perform any detection on this packet, if the the given flag is set.*/
1704  return;
1705  }
1706 
1707  /* see if the packet matches one or more of the sigs */
1708  DetectRun(tv, de_ctx, det_ctx, p);
1709  return;
1710 }
1711 
1712 /** \brief Detection engine thread wrapper.
1713  * \param tv thread vars
1714  * \param p packet to inspect
1715  * \param data thread specific data
1716  * \param pq packet queue
1717  * \retval TM_ECODE_FAILED error
1718  * \retval TM_ECODE_OK ok
1719  */
1720 TmEcode Detect(ThreadVars *tv, Packet *p, void *data)
1721 {
1723 
1724  DetectEngineCtx *de_ctx = NULL;
1725  DetectEngineThreadCtx *det_ctx = (DetectEngineThreadCtx *)data;
1726  if (det_ctx == NULL) {
1727  printf("ERROR: Detect has no thread ctx\n");
1728  goto error;
1729  }
1730 
1731  if (unlikely(SC_ATOMIC_GET(det_ctx->so_far_used_by_detect) == 0)) {
1732  (void)SC_ATOMIC_SET(det_ctx->so_far_used_by_detect, 1);
1733  SCLogDebug("Detect Engine using new det_ctx - %p",
1734  det_ctx);
1735  }
1736 
1737  /* if in MT mode _and_ we have tenants registered, use
1738  * MT logic. */
1739  if (det_ctx->mt_det_ctxs_cnt > 0 && det_ctx->TenantGetId != NULL)
1740  {
1741  uint32_t tenant_id = p->tenant_id;
1742  if (tenant_id == 0)
1743  tenant_id = det_ctx->TenantGetId(det_ctx, p);
1744  if (tenant_id > 0 && tenant_id < det_ctx->mt_det_ctxs_cnt) {
1745  p->tenant_id = tenant_id;
1746  det_ctx = GetTenantById(det_ctx->mt_det_ctxs_hash, tenant_id);
1747  if (det_ctx == NULL)
1748  return TM_ECODE_OK;
1749  de_ctx = det_ctx->de_ctx;
1750  if (de_ctx == NULL)
1751  return TM_ECODE_OK;
1752 
1753  if (unlikely(SC_ATOMIC_GET(det_ctx->so_far_used_by_detect) == 0)) {
1754  (void)SC_ATOMIC_SET(det_ctx->so_far_used_by_detect, 1);
1755  SCLogDebug("MT de_ctx %p det_ctx %p (tenant %u)", de_ctx, det_ctx, tenant_id);
1756  }
1757  } else {
1758  /* use default if no tenants are registered for this packet */
1759  de_ctx = det_ctx->de_ctx;
1760  }
1761  } else {
1762  de_ctx = det_ctx->de_ctx;
1763  }
1764 
1765  if (p->flow) {
1766  DetectFlow(tv, de_ctx, det_ctx, p);
1767  } else {
1768  DetectNoFlow(tv, de_ctx, det_ctx, p);
1769  }
1770  return TM_ECODE_OK;
1771 error:
1772  return TM_ECODE_FAILED;
1773 }
1774 
1775 /** \brief disable file features we don't need
1776  * Called if we have no detection engine.
1777  */
1779 {
1780  DetectPostInspectFileFlagsUpdate(f, NULL /* no sgh */, STREAM_TOSERVER);
1781  DetectPostInspectFileFlagsUpdate(f, NULL /* no sgh */, STREAM_TOCLIENT);
1782 }
1783 
1784 #ifdef UNITTESTS
1785 /**
1786  * \brief wrapper for old tests
1787  */
1790 {
1791  if (p->flow) {
1792  DetectFlow(tv, de_ctx, det_ctx, p);
1793  } else {
1794  DetectNoFlow(tv, de_ctx, det_ctx, p);
1795  }
1796 }
1797 #endif
1798 
1799 /*
1800  * TESTS
1801  */
1802 
1803 #ifdef UNITTESTS
1804 #include "tests/detect.c"
1805 #endif
1806 
DetectEngineAppInspectionEngine_::stream
bool stream
Definition: detect.h:394
SigGroupHead_::non_pf_syn_store_cnt
uint32_t non_pf_syn_store_cnt
Definition: detect.h:1398
PacketCheckAction
bool PacketCheckAction(const Packet *p, const uint8_t a)
Definition: packet.c:48
FLOWFILE_NO_MD5_TS
#define FLOWFILE_NO_MD5_TS
Definition: flow.h:127
DetectEngineThreadCtx_::non_pf_store_ptr
SignatureNonPrefilterStore * non_pf_store_ptr
Definition: detect.h:1122
RulesDumpTxMatchArray
void RulesDumpTxMatchArray(const DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, const Packet *p, const uint64_t tx_id, const uint32_t rule_cnt, const uint32_t pkt_prefilter_cnt)
Definition: detect-engine-profile.c:34
SIG_GROUP_HEAD_HAVEFILEMD5
#define SIG_GROUP_HEAD_HAVEFILEMD5
Definition: detect.h:1268
FLOWFILE_NO_MD5_TC
#define FLOWFILE_NO_MD5_TC
Definition: flow.h:128
SigGroupHead_::tx_engines
PrefilterEngine * tx_engines
Definition: detect.h:1411
DetectEngineAppInspectionEngine_
Definition: detect.h:389
Packet_::proto
uint8_t proto
Definition: decode.h:450
DetectTransaction_::tx_data_ptr
struct AppLayerTxData * tx_data_ptr
Definition: detect-engine-prefilter.h:34
DetectEngineAppInspectionEngine_::mpm
bool mpm
Definition: detect.h:393
RULE_PROFILING_END
#define RULE_PROFILING_END(ctx, r, m, p)
Definition: util-profiling.h:55
DE_STATE_CHUNK_SIZE
#define DE_STATE_CHUNK_SIZE
Definition: detect-engine-state.h:53
RuleMatchCandidateTx::stream_stored
bool stream_stored
Definition: detect.h:1012
FLOWFILE_NO_SIZE_TS
#define FLOWFILE_NO_SIZE_TS
Definition: flow.h:139
DetectEngineThreadCtx_::alert_queue_size
uint16_t alert_queue_size
Definition: detect.h:1101
PROF_DETECT_GETSGH
@ PROF_DETECT_GETSGH
Definition: suricata-common.h:430
FLOWFILE_NO_SIZE_TC
#define FLOWFILE_NO_SIZE_TC
Definition: flow.h:140
detect-engine.h
detect-engine-proto.h
DetectEngineThreadCtx_::match_array_cnt
SigIntId match_array_cnt
Definition: detect.h:1117
Frame::tx_id
uint64_t tx_id
Definition: app-layer-frames.h:50
DetectEngineStateDirection_::flags
uint8_t flags
Definition: detect-engine-state.h:89
detect-dsize.h
Signature_::addr_src_match6
DetectMatchAddressIPv6 * addr_src_match6
Definition: detect.h:571
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1002
PACKET_ALERT_FLAG_TX
#define PACKET_ALERT_FLAG_TX
Definition: decode.h:279
DetectEngineCtx_::decoder_event_sgh
struct SigGroupHead_ * decoder_event_sgh
Definition: detect.h:883
FlowGetPacketDirection
int FlowGetPacketDirection(const Flow *f, const Packet *p)
determine the direction of the packet compared to the flow
Definition: flow.c:312
DetectEngineCtx_::flow_gh
DetectEngineLookupFlow flow_gh[FLOW_STATES]
Definition: detect.h:818
DE_STATE_FLAG_SIG_CANT_MATCH
#define DE_STATE_FLAG_SIG_CANT_MATCH
Definition: detect-engine-state.h:57
DetectEngineThreadCtx_::counter_match_list
uint16_t counter_match_list
Definition: detect.h:1069
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:408
DETECT_PROTO_IPV6
#define DETECT_PROTO_IPV6
Definition: detect-engine-proto.h:34
detect-engine-siggroup.h
IPOnlyMatchPacket
void IPOnlyMatchPacket(ThreadVars *tv, const DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const DetectEngineIPOnlyCtx *io_ctx, DetectEngineIPOnlyThreadCtx *io_tctx, Packet *p)
Match a packet against the IP Only detection engine contexts.
Definition: detect-engine-iponly.c:991
PKT_IS_IPV6
#define PKT_IS_IPV6(p)
Definition: decode.h:246
DetectEngineState_
Definition: detect-engine-state.h:93
Signature_::num
SigIntId num
Definition: detect.h:550
stream-tcp.h
Prefilter
void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, const uint8_t flags)
Definition: detect-engine-prefilter.c:143
PrefilterRuleStore_::rule_id_array_cnt
uint32_t rule_id_array_cnt
Definition: util-prefilter.h:40
detect-engine-event.h
SigGroupHead_
Container for matching data for a signature group.
Definition: detect.h:1392
SIG_GROUP_HEAD_HAVEFILESIZE
#define SIG_GROUP_HEAD_HAVEFILESIZE
Definition: detect.h:1269
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
detect.c
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:387
KEYWORD_PROFILING_SET_LIST
#define KEYWORD_PROFILING_SET_LIST(ctx, list)
Definition: util-profiling.h:66
DetectAddressMatchIPv4
int DetectAddressMatchIPv4(const DetectMatchAddressIPv4 *addrs, uint16_t addrs_cnt, const Address *a)
Match a packets address against a signatures addrs array.
Definition: detect-engine-address.c:1605
Signature_::alproto
AppProto alproto
Definition: detect.h:543
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:296
SignatureNonPrefilterStore_::id
SigIntId id
Definition: detect.h:1001
FLOW_SGH_TOCLIENT
#define FLOW_SGH_TOCLIENT
Definition: flow.h:71
Packet_::pcap_cnt
uint64_t pcap_cnt
Definition: decode.h:594
AppLayerParserSetTransactionInspectId
void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate, void *alstate, const uint8_t flags, bool tag_txs_as_inspected)
Definition: app-layer-parser.c:760
DetectEngineStateDirection_::cnt
SigIntId cnt
Definition: detect-engine-state.h:87
AppLayerGetTxIterator
AppLayerGetTxIteratorFunc AppLayerGetTxIterator(const uint8_t ipproto, const AppProto alproto)
Definition: app-layer-parser.c:704
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
Flow_::proto
uint8_t proto
Definition: flow.h:378
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:80
PacketAlerts_::cnt
uint16_t cnt
Definition: decode.h:289
AppLayerParserGetStateProgress
int AppLayerParserGetStateProgress(uint8_t ipproto, AppProto alproto, void *alstate, uint8_t flags)
get the progress value for a tx/protocol
Definition: app-layer-parser.c:1125
DetectEngineThreadCtx_::tx_id
uint64_t tx_id
Definition: detect.h:1097
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:325
action-globals.h
FLOWFILE_NO_MAGIC_TS
#define FLOWFILE_NO_MAGIC_TS
Definition: flow.h:120
FramesContainer::toserver
Frames toserver
Definition: app-layer-frames.h:71
Packet_::flags
uint32_t flags
Definition: decode.h:463
ICMPV4_DEST_UNREACH_IS_VALID
#define ICMPV4_DEST_UNREACH_IS_VALID(p)
Definition: decode-icmpv4.h:267
Frame
Definition: app-layer-frames.h:40
Flow_
Flow data structure.
Definition: flow.h:356
DetectTransaction_::tx_end_state
const int tx_end_state
Definition: detect-engine-prefilter.h:41
PROF_DETECT_ALERT
@ PROF_DETECT_ALERT
Definition: suricata-common.h:441
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1131
SIG_GROUP_HEAD_HAVEFILESHA1
#define SIG_GROUP_HEAD_HAVEFILESHA1
Definition: detect.h:1270
DetectRunPrefilterFrame
void DetectRunPrefilterFrame(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, const Frames *frames, const Frame *frame, const AppProto alproto, const uint32_t idx)
Definition: detect-engine-frame.c:43
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:784
AppLayerParserGetStateProgressCompletionStatus
int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto, uint8_t direction)
Definition: app-layer-parser.c:1153
DetectRunScratchpad
struct DetectRunScratchpad DetectRunScratchpad
PROF_DETECT_PF_TX
@ PROF_DETECT_PF_TX
Definition: suricata-common.h:436
Frames::cnt
uint16_t cnt
Definition: app-layer-frames.h:57
Frame::id
int64_t id
Definition: app-layer-frames.h:49
DetectEngineThreadCtx_::p
Packet * p
Definition: detect.h:1099
DetectEngineState_::dir_state
DetectEngineStateDirection dir_state[2]
Definition: detect-engine-state.h:94
FrameGetByIndex
Frame * FrameGetByIndex(Frames *frames, const uint32_t idx)
Definition: app-layer-frames.c:64
StreamReassembleRawUpdateProgress
void StreamReassembleRawUpdateProgress(TcpSession *ssn, Packet *p, uint64_t progress)
update stream engine after detection
Definition: stream-tcp-reassemble.c:1463
RuleMatchCandidateTx::id
SigIntId id
Definition: detect.h:1008
PROF_DETECT_CLEANUP
@ PROF_DETECT_CLEANUP
Definition: suricata-common.h:443
SIG_FLAG_DST_ANY
#define SIG_FLAG_DST_ANY
Definition: detect.h:201
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:226
HashTable_
Definition: util-hash.h:35
DetectEngineThreadCtx_::flags
uint16_t flags
Definition: detect.h:1092
Frames
Definition: app-layer-frames.h:56
FramesContainer
Definition: app-layer-frames.h:70
PacketAlerts_::drop
PacketAlert drop
Definition: decode.h:295
APP_LAYER_TX_INSPECTED_FLAG
#define APP_LAYER_TX_INSPECTED_FLAG
Definition: app-layer-parser.h:79
DetectRunScratchpad
Definition: detect.c:70
SIG_GROUP_HEAD_HAVERAWSTREAM
#define SIG_GROUP_HEAD_HAVERAWSTREAM
Definition: detect.h:1264
FLOW_ACTION_DROP
#define FLOW_ACTION_DROP
Definition: flow.h:66
TcpStream_::flags
uint16_t flags
Definition: stream-tcp-private.h:107
FLOWFILE_NONE
#define FLOWFILE_NONE
Definition: flow.h:157
detect-engine-frame.h
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1788
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:594
proto
uint8_t proto
Definition: decode-template.h:0
m
SCMutex m
Definition: flow-hash.h:6
DetectPort_::sh
struct SigGroupHead_ * sh
Definition: detect.h:191
PACKET_PROFILING_DETECT_END
#define PACKET_PROFILING_DETECT_END(p, id)
Definition: util-profiling.h:242
Detect
TmEcode Detect(ThreadVars *tv, Packet *p, void *data)
Detection engine thread wrapper.
Definition: detect.c:1720
FLOW_PKT_TOCLIENT_IPONLY_SET
#define FLOW_PKT_TOCLIENT_IPONLY_SET
Definition: flow.h:230
detect-engine-payload.h
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:459
SIG_FLAG_SRC_ANY
#define SIG_FLAG_SRC_ANY
Definition: detect.h:200
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:85
Flow_::protoctx
void * protoctx
Definition: flow.h:454
SigMatchData_
Data needed for Match()
Definition: detect.h:322
DeStateStoreItem_::sid
SigIntId sid
Definition: detect-engine-state.h:75
RuleMatchCandidateTx::s
const Signature * s
Definition: detect.h:1018
KEYWORD_PROFILING_START
#define KEYWORD_PROFILING_START
Definition: util-profiling.h:70
DetectEngineThreadCtx_::counter_fnonmpm_list
uint16_t counter_fnonmpm_list
Definition: detect.h:1068
SigMatchData_::type
uint16_t type
Definition: detect.h:323
DetectEngineCtx_::version
uint32_t version
Definition: detect.h:879
DetectEngineAppInspectionEngine_::v2
struct DetectEngineAppInspectionEngine_::@84 v2
DisableDetectFlowFileFlags
void DisableDetectFlowFileFlags(Flow *f)
disable file features we don't need Called if we have no detection engine.
Definition: detect.c:1778
AppLayerParserGetTransactionInspectId
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
Definition: app-layer-parser.c:729
Packet_::alerts
PacketAlerts alerts
Definition: decode.h:588
DetectTransaction_::tx_progress
const int tx_progress
Definition: detect-engine-prefilter.h:40
DetectEngineThreadCtx_::counter_nonmpm_list
uint16_t counter_nonmpm_list
Definition: detect.h:1067
detect-engine-prefilter.h
Packet_::events
PacketEngineEvents events
Definition: decode.h:598
Signature_::frame_inspect
DetectEngineFrameInspectionEngine * frame_inspect
Definition: detect.h:590
DetectTransaction_::prefilter_flags_orig
const uint64_t prefilter_flags_orig
Definition: detect-engine-prefilter.h:39
PROF_DETECT_PF_SORT2
@ PROF_DETECT_PF_SORT2
Definition: suricata-common.h:439
pad
uint16_t pad
Definition: source-erf-file.c:61
TcpSession_::flags
uint16_t flags
Definition: stream-tcp-private.h:281
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:84
PacketCreateMask
void PacketCreateMask(Packet *p, SignatureMask *mask, AppProto alproto, bool app_decoder_events)
Definition: detect-engine-build.c:411
SIG_FLAG_APPLAYER
#define SIG_FLAG_APPLAYER
Definition: detect.h:207
KEYWORD_PROFILING_END
#define KEYWORD_PROFILING_END(ctx, type, m)
Definition: util-profiling.h:84
detect-flowvar.h
DetectEngineThreadCtx_::mt_det_ctxs_hash
HashTable * mt_det_ctxs_hash
Definition: detect.h:1039
PacketAlert_::action
uint8_t action
Definition: decode.h:265
DetectEnginePktInspectionRun
bool DetectEnginePktInspectionRun(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f, Packet *p, uint8_t *alert_flags)
Definition: detect-engine.c:1808
Flow_::sgh_toserver
const struct SigGroupHead_ * sgh_toserver
Definition: flow.h:496
PROF_DETECT_TX_UPDATE
@ PROF_DETECT_TX_UPDATE
Definition: suricata-common.h:442
DetectEngineAppInspectionEngine_::id
uint8_t id
Definition: detect.h:392
DetectEngineThreadCtx_::counter_alerts_suppressed
uint16_t counter_alerts_suppressed
Definition: detect.h:1064
DetectRunStoreStateTx
void DetectRunStoreStateTx(const SigGroupHead *sgh, Flow *f, void *tx, uint64_t tx_id, const Signature *s, uint32_t inspect_flags, uint8_t flow_flags, const uint16_t file_no_match)
Definition: detect-engine-state.c:223
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:395
FLOWFILE_INIT
#define FLOWFILE_INIT
Definition: flow.h:117
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:488
DETECT_ENGINE_INSPECT_SIG_CANT_MATCH_FILES
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH_FILES
Definition: detect-engine-state.h:44
FLOWFILE_NO_SHA1_TC
#define FLOWFILE_NO_SHA1_TC
Definition: flow.h:132
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:87
FramesContainer::toclient
Frames toclient
Definition: app-layer-frames.h:72
DetectEngineThreadCtx_::tx_candidates
RuleMatchCandidateTx * tx_candidates
Definition: detect.h:1119
Signature_::addr_src_match4
DetectMatchAddressIPv4 * addr_src_match4
Definition: detect.h:568
decode.h
DetectEngineThreadCtx_::counter_alerts_overflow
uint16_t counter_alerts_overflow
Definition: detect.h:1062
TOSERVER
#define TOSERVER
Definition: flow.h:43
DETECT_ENGINE_THREAD_CTX_FRAME_ID_SET
#define DETECT_ENGINE_THREAD_CTX_FRAME_ID_SET
Definition: detect.h:274
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:17
PKT_IS_TOSERVER
#define PKT_IS_TOSERVER(p)
Definition: decode.h:251
DetectEngineThreadCtx_
Definition: detect.h:1024
DEBUG_VALIDATE_PACKET
#define DEBUG_VALIDATE_PACKET(p)
Definition: util-validate.h:110
DeStateStoreItem_::flags
uint32_t flags
Definition: detect-engine-state.h:74
PKT_STREAM_ADD
#define PKT_STREAM_ADD
Definition: decode.h:997
FLOWFILE_NO_STORE_TS
#define FLOWFILE_NO_STORE_TS
Definition: flow.h:124
BIT_U32
#define BIT_U32(n)
Definition: suricata-common.h:389
DetectEngineThreadCtx_::tx_candidates_size
uint32_t tx_candidates_size
Definition: detect.h:1120
FLOW_PKT_TOSERVER_IPONLY_SET
#define FLOW_PKT_TOSERVER_IPONLY_SET
Definition: flow.h:229
SIG_FLAG_FLUSH
#define SIG_FLAG_FLUSH
Definition: detect.h:220
PKT_IS_FRAGMENT
#define PKT_IS_FRAGMENT
Definition: decode.h:1026
STREAM_FLAGS_FOR_PACKET
#define STREAM_FLAGS_FOR_PACKET(p)
Definition: stream.h:30
SCEnter
#define SCEnter(...)
Definition: util-debug.h:298
PMQ_RESET
#define PMQ_RESET(pmq)
Definition: util-prefilter.h:46
detect-engine-mpm.h
DetectEngineLookupFlow_::sgh
struct SigGroupHead_ * sgh[256]
Definition: detect.h:723
HashTableLookup
void * HashTableLookup(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:194
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
DeStateStore_::next
struct DeStateStore_ * next
Definition: detect-engine-state.h:80
SignatureNonPrefilterStore_::alproto
AppProto alproto
Definition: detect.h:1003
Packet_::sp
Port sp
Definition: decode.h:435
FLOWFILE_NO_SHA256_TS
#define FLOWFILE_NO_SHA256_TS
Definition: flow.h:135
DETECT_ENGINE_INSPECT_SIG_MATCH
#define DETECT_ENGINE_INSPECT_SIG_MATCH
Definition: detect-engine-state.h:39
PKT_DETECT_HAS_STREAMDATA
#define PKT_DETECT_HAS_STREAMDATA
Definition: decode.h:1041
StreamReassembleRawHasDataReady
bool StreamReassembleRawHasDataReady(TcpSession *ssn, Packet *p)
does the stream engine have data to inspect?
Definition: stream-tcp-reassemble.c:1419
detect-engine-port.h
DetectEngineThreadCtx_::non_pf_id_cnt
uint32_t non_pf_id_cnt
Definition: detect.h:1035
DetectPort_
Port structure for detection engine.
Definition: detect.h:180
PacketAlerts_::discarded
uint16_t discarded
Definition: decode.h:290
app-layer-parser.h
Signature_::app_inspect
DetectEngineAppInspectionEngine * app_inspect
Definition: detect.h:588
util-detect.h
detect-engine-profile.h
Flow_::sgh_toclient
const struct SigGroupHead_ * sgh_toclient
Definition: flow.h:493
DetectEngineThreadCtx_::base64_decoded_len
int base64_decoded_len
Definition: detect.h:1165
SIG_FLAG_REQUIRE_FLOWVAR
#define SIG_FLAG_REQUIRE_FLOWVAR
Definition: detect.h:224
RuleMatchCandidateTx::stream_result
uint8_t stream_result
Definition: detect.h:1013
util-profiling.h
DetectTransaction_::tx_id
const uint64_t tx_id
Definition: detect-engine-prefilter.h:33
DetectEngineLookupFlow_::udp
DetectPort * udp
Definition: detect.h:722
DetectEngineThreadCtx_::raw_stream_progress
uint64_t raw_stream_progress
Definition: detect.h:1048
FileUpdateFlowFileFlags
void FileUpdateFlowFileFlags(Flow *f, uint16_t set_file_flags, uint8_t direction)
set a flow's file flags
Definition: util-file.c:1115
SCReturn
#define SCReturn
Definition: util-debug.h:300
Signature_::flags
uint32_t flags
Definition: detect.h:540
AlertQueueAppend
void AlertQueueAppend(DetectEngineThreadCtx *det_ctx, const Signature *s, Packet *p, uint64_t tx_id, uint8_t alert_flags)
Append signature to local packet alert queue for later preprocessing.
Definition: detect-engine-alert.c:283
RuleMatchCandidateTxArrayFree
void RuleMatchCandidateTxArrayFree(DetectEngineThreadCtx *det_ctx)
Definition: detect.c:981
AppLayerGetTxIterState
Definition: app-layer-parser.h:142
DetectTransaction_::prefilter_flags
uint64_t prefilter_flags
Definition: detect-engine-prefilter.h:37
Packet_
Definition: decode.h:428
DetectRunFrameInspectRule
int DetectRunFrameInspectRule(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f, Packet *p, const Frames *frames, const Frame *frame, const uint32_t idx)
Definition: detect-engine-frame.c:134
detect-engine-build.h
AppLayerFramesGetContainer
FramesContainer * AppLayerFramesGetContainer(Flow *f)
Definition: app-layer-parser.c:183
DetectEngineThreadCtx_::frame_id
int64_t frame_id
Definition: detect.h:1098
DetectEngineAppInspectionEngine_::Callback
InspectEngineFuncPtr2 Callback
Definition: detect.h:401
APP_LAYER_TX_PREFILTER_MASK
#define APP_LAYER_TX_PREFILTER_MASK
Definition: app-layer-parser.h:82
detect-engine-alert.h
conf.h
DetectRunScratchpad::pkt_mask
SignatureMask pkt_mask
Definition: detect.c:75
FlowSetIPOnlyFlag
void FlowSetIPOnlyFlag(Flow *f, int direction)
Set the IPOnly scanned flag for 'direction'.
Definition: flow.c:159
FLOW_TOSERVER_IPONLY_SET
#define FLOW_TOSERVER_IPONLY_SET
Definition: flow.h:56
DetectEngineThreadCtx_::filestore_cnt
uint16_t filestore_cnt
Definition: detect.h:1057
PROF_DETECT_IPONLY
@ PROF_DETECT_IPONLY
Definition: suricata-common.h:431
TmEcode
TmEcode
Definition: tm-threads-common.h:83
RULE_PROFILING_START
#define RULE_PROFILING_START(p)
Definition: util-profiling.h:43
PKT_STREAM_EOF
#define PKT_STREAM_EOF
Definition: decode.h:1001
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:314
DetectTransaction_::de_state
DetectEngineStateDirection * de_state
Definition: detect-engine-prefilter.h:35
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
detect-filestore.h
SigTableElmt_::Match
int(* Match)(DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1203
detect-replace.h
RulesDumpMatchArray
void RulesDumpMatchArray(const DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, const Packet *p)
Definition: detect-engine-profile.c:79
Signature_::addr_dst_match6_cnt
uint16_t addr_dst_match6_cnt
Definition: detect.h:565
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:227
SigGroupHead_::frame_engines
PrefilterEngine * frame_engines
Definition: detect.h:1412
Signature_::sp
DetectPort * sp
Definition: detect.h:579
DetectRunScratchpad::sgh
const SigGroupHead * sgh
Definition: detect.c:74
DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
Definition: detect-engine-state.h:40
DETECT_ENGINE_STATE_FLAG_FILE_NEW
#define DETECT_ENGINE_STATE_FLAG_FILE_NEW
Definition: detect-engine-state.h:71
Flow_::flowvar
GenericVar * flowvar
Definition: flow.h:499
RuleMatchCandidateTx::flags
uint32_t * flags
Definition: detect.h:1009
DetectEngineAppInspectionEngine_::alproto
AppProto alproto
Definition: detect.h:390
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
detect-engine-analyzer.h
FLOWFILE_NO_SHA256_TC
#define FLOWFILE_NO_SHA256_TC
Definition: flow.h:136
DetectEngineStateDirection_::head
DeStateStore * head
Definition: detect-engine-state.h:84
DETECT_ENGINE_INSPECT_SIG_MATCH_MORE_FILES
#define DETECT_ENGINE_INSPECT_SIG_MATCH_MORE_FILES
Definition: detect-engine-state.h:50
DetectProto_::flags
uint8_t flags
Definition: detect-engine-proto.h:38
AppLayerTxData
struct AppLayerTxData AppLayerTxData
Definition: detect.h:1300
DETECT_PROTO_IPV4
#define DETECT_PROTO_IPV4
Definition: detect-engine-proto.h:33
app-layer-frames.h
DetectAddressMatchIPv6
int DetectAddressMatchIPv6(const DetectMatchAddressIPv6 *addrs, uint16_t addrs_cnt, const Address *a)
Match a packets address against a signatures addrs array.
Definition: detect-engine-address.c:1638
Packet_::tenant_id
uint32_t tenant_id
Definition: decode.h:630
Packet_::flow
struct Flow_ * flow
Definition: decode.h:465
DetectEngineStateResetTxs
void DetectEngineStateResetTxs(Flow *f)
Reset de state for active tx' To be used on detect engine reload.
Definition: detect-engine-state.c:269
FLOWFILE_NO_MAGIC_TC
#define FLOWFILE_NO_MAGIC_TC
Definition: flow.h:121
TH_SYN
#define TH_SYN
Definition: decode-tcp.h:35
flags
uint8_t flags
Definition: decode-gre.h:0
Signature_::proto
DetectProto proto
Definition: detect.h:557
SigGroupHead_::non_pf_other_store_array
SignatureNonPrefilterStore * non_pf_other_store_array
Definition: detect.h:1399
FLOW_TOCLIENT_IPONLY_SET
#define FLOW_TOCLIENT_IPONLY_SET
Definition: flow.h:58
SigMatchData_::is_last
uint8_t is_last
Definition: detect.h:324
suricata-common.h
SIG_FLAG_SP_ANY
#define SIG_FLAG_SP_ANY
Definition: detect.h:202
APP_LAYER_TX_RESERVED_FLAGS
#define APP_LAYER_TX_RESERVED_FLAGS
Definition: app-layer-parser.h:69
Packet_::tcph
TCPHdr * tcph
Definition: decode.h:553
SigGroupHead_::non_pf_other_store_cnt
uint32_t non_pf_other_store_cnt
Definition: detect.h:1397
packet.h
DeStateStore_
Definition: detect-engine-state.h:78
sigmatch_table
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect-parse.c:76
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
DetectTransaction_
Definition: detect-engine-prefilter.h:31
PROF_DETECT_SETUP
@ PROF_DETECT_SETUP
Definition: suricata-common.h:429
DetectEngineStateDirection_
Definition: detect-engine-state.h:83
DetectEngineCtx_::profile_match_logging_threshold
uint32_t profile_match_logging_threshold
Definition: detect.h:912
AppLayerParserGetTxData
AppLayerTxData * AppLayerParserGetTxData(uint8_t ipproto, AppProto alproto, void *tx)
Definition: app-layer-parser.c:1218
FatalError
#define FatalError(x,...)
Definition: util-debug.h:530
TcpSession_::client
TcpStream client
Definition: stream-tcp-private.h:285
FLOWFILE_NO_STORE_TC
#define FLOWFILE_NO_STORE_TC
Definition: flow.h:125
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
DetectEngineThreadCtx_::non_pf_id_array
SigIntId * non_pf_id_array
Definition: detect.h:1034
DetectEngineAppInspectionEngine_::progress
int16_t progress
Definition: detect.h:397
PKT_IS_ICMPV4
#define PKT_IS_ICMPV4(p)
Definition: decode.h:249
util-validate.h
FlowGetAppProtocol
AppProto FlowGetAppProtocol(const Flow *f)
Definition: flow.c:1143
DetectTransaction_::tx_ptr
void * tx_ptr
Definition: detect-engine-prefilter.h:32
Signature_::addr_src_match6_cnt
uint16_t addr_src_match6_cnt
Definition: detect.h:566
StatsAddUI64
void StatsAddUI64(ThreadVars *tv, uint16_t id, uint64_t x)
Adds a value of type uint64_t to the local counter.
Definition: counters.c:146
FLOWFILE_NO_SHA1_TS
#define FLOWFILE_NO_SHA1_TS
Definition: flow.h:131
PROF_DETECT_RULES
@ PROF_DETECT_RULES
Definition: suricata-common.h:432
DetectRunScratchpad::app_decoder_events
const bool app_decoder_events
Definition: detect.c:73
TcpSession_::server
TcpStream server
Definition: stream-tcp-private.h:284
PROF_DETECT_NONMPMLIST
@ PROF_DETECT_NONMPMLIST
Definition: suricata-common.h:440
Signature_::dp
DetectPort * dp
Definition: detect.h:579
PacketAlerts_::suppressed
uint16_t suppressed
Definition: decode.h:291
PACKET_PROFILING_DETECT_START
#define PACKET_PROFILING_DETECT_START(p, id)
Definition: util-profiling.h:235
PACKET_ALERT_FLAG_FRAME
#define PACKET_ALERT_FLAG_FRAME
Definition: decode.h:283
DetectEngineThreadCtx_::non_pf_store_cnt
uint32_t non_pf_store_cnt
Definition: detect.h:1123
FLOW_SGH_TOSERVER
#define FLOW_SGH_TOSERVER
Definition: flow.h:69
DetectEngineThreadCtx_::counter_alerts
uint16_t counter_alerts
Definition: detect.h:1060
SigGroupHead_::flags
uint32_t flags
Definition: detect.h:1393
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SGH_PROFILING_RECORD
#define SGH_PROFILING_RECORD(det_ctx, sgh)
Definition: util-profiling.h:273
PacketAlertFinalize
void PacketAlertFinalize(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
Check the threshold of the sigs that match, set actions, break on pass action This function iterate t...
Definition: detect-engine-alert.c:358
Signature_::addr_dst_match6
DetectMatchAddressIPv6 * addr_dst_match6
Definition: detect.h:570
Flow_::alstate
void * alstate
Definition: flow.h:489
Signature_::id
uint32_t id
Definition: detect.h:573
DeStateStore_::store
DeStateStoreItem store[DE_STATE_CHUNK_SIZE]
Definition: detect-engine-state.h:79
Flow_::flags
uint32_t flags
Definition: flow.h:434
RuleMatchCandidateTx::stream_reset
uint32_t stream_reset
Definition: detect.h:1015
detect-engine-iponly.h
Signature_
Signature container.
Definition: detect.h:539
IP_GET_IPPROTO
#define IP_GET_IPPROTO(p)
Definition: decode.h:257
InspectionBufferClean
void InspectionBufferClean(DetectEngineThreadCtx *det_ctx)
Definition: detect-engine.c:1342
SignatureMask
#define SignatureMask
Definition: detect.h:272
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
TRACE_SID_TXS
#define TRACE_SID_TXS(sid, txs,...)
Definition: detect.c:1044
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:228
DetectEngineThreadCtx_::tx_id_set
bool tx_id_set
Definition: detect.h:1095
PacketDrop
void PacketDrop(Packet *p, const uint8_t action, enum PacketDropReason r)
issue drop action
Definition: packet.c:32
SC_ERR_MEM_ALLOC
@ SC_ERR_MEM_ALLOC
Definition: util-error.h:31
STREAMTCP_FLAG_APP_LAYER_DISABLED
#define STREAMTCP_FLAG_APP_LAYER_DISABLED
Definition: stream-tcp-private.h:199
DetectRunScratchpad::flow_flags
const uint8_t flow_flags
Definition: detect.c:72
DetectEngineThreadCtx_::de_ctx
DetectEngineCtx * de_ctx
Definition: detect.h:1156
suricata.h
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:799
Packet_::dst
Address dst
Definition: decode.h:433
SigGroupHead_::non_pf_syn_store_array
SignatureNonPrefilterStore * non_pf_syn_store_array
Definition: detect.h:1401
PROF_DETECT_TX
@ PROF_DETECT_TX
Definition: suricata-common.h:433
DetectEngineAppInspectionEngine_::dir
uint8_t dir
Definition: detect.h:391
PKT_NOPACKET_INSPECTION
#define PKT_NOPACKET_INSPECTION
Definition: decode.h:987
SignatureNonPrefilterStore_::mask
SignatureMask mask
Definition: detect.h:1002
DetectRunScratchpad::alproto
const AppProto alproto
Definition: detect.c:71
DE_STATE_FLAG_FULL_INSPECT
#define DE_STATE_FLAG_FULL_INSPECT
Definition: detect-engine-state.h:56
STREAMTCP_STREAM_FLAG_DISABLE_RAW
#define STREAMTCP_STREAM_FLAG_DISABLE_RAW
Definition: stream-tcp-private.h:231
DetectEngineThreadCtx_::mt_det_ctxs_cnt
uint32_t mt_det_ctxs_cnt
Definition: detect.h:1037
AppLayerGetTxIteratorFunc
AppLayerGetTxIterTuple(* AppLayerGetTxIteratorFunc)(const uint8_t ipproto, const AppProto alproto, void *alstate, uint64_t min_tx_id, uint64_t max_tx_id, AppLayerGetTxIterState *state)
tx iterator prototype
Definition: app-layer-parser.h:151
likely
#define likely(expr)
Definition: util-optimize.h:32
IPPROTO_SCTP
#define IPPROTO_SCTP
Definition: decode.h:930
DE_STATE_FLAG_FILE_INSPECT
#define DE_STATE_FLAG_FILE_INSPECT
Definition: detect-engine-state.h:61
FLOW_NOPACKET_INSPECTION
#define FLOW_NOPACKET_INSPECTION
Definition: flow.h:61
DetectEngineCtx_::io_ctx
DetectEngineIPOnlyCtx io_ctx
Definition: detect.h:831
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:376
Signature_::addr_dst_match4
DetectMatchAddressIPv4 * addr_dst_match4
Definition: detect.h:567
FlowGetDisruptionFlags
uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags)
get 'disruption' flags: GAP/DEPTH/PASS
Definition: flow.c:1160
TcpSession_
Definition: stream-tcp-private.h:272
flow.h
Signature_::addr_src_match4_cnt
uint16_t addr_src_match4_cnt
Definition: detect.h:564
SigIntId
#define SigIntId
Definition: suricata-common.h:304
DeStateStoreItem_
Definition: detect-engine-state.h:73
GenericVarFree
void GenericVarFree(GenericVar *gv)
Definition: util-var.c:47
Signature_::addr_dst_match4_cnt
uint16_t addr_dst_match4_cnt
Definition: detect.h:563
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:463
Packet_::dp
Port dp
Definition: decode.h:443
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
SIG_GROUP_HEAD_HAVEFILESHA256
#define SIG_GROUP_HEAD_HAVEFILESHA256
Definition: detect.h:1271
SigGroupHead_::filestore_cnt
uint16_t filestore_cnt
Definition: detect.h:1405
AppLayerParserGetTxCnt
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
Definition: app-layer-parser.c:1139
PKT_IS_IPV4
#define PKT_IS_IPV4(p)
Definition: decode.h:245
PACKET_ALERT_FLAG_STATE_MATCH
#define PACKET_ALERT_FLAG_STATE_MATCH
Definition: decode.h:275
AppLayerParserHasDecoderEvents
bool AppLayerParserHasDecoderEvents(AppLayerParserState *pstate)
Definition: app-layer-parser.c:1500
DetectEngineLookupFlow_::tcp
DetectPort * tcp
Definition: detect.h:721
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:111
DetectTransaction_::detect_flags
const uint64_t detect_flags
Definition: detect-engine-prefilter.h:36
PKT_DROP_REASON_FLOW_DROP
@ PKT_DROP_REASON_FLOW_DROP
Definition: decode.h:396
detect-engine-address.h
Flow_::tenant_id
uint32_t tenant_id
Definition: flow.h:429
Packet_::src
Address src
Definition: decode.h:432
DetectEngineThreadCtx_::counter_mpm_list
uint16_t counter_mpm_list
Definition: detect.h:1066
SigMatchSignaturesGetSgh
const SigGroupHead * SigMatchSignaturesGetSgh(const DetectEngineCtx *de_ctx, const Packet *p)
Get the SigGroupHead for a packet.
Definition: detect.c:201
DetectRunPrefilterTx
void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, const uint8_t ipproto, const uint8_t flow_flags, const AppProto alproto, void *alstate, DetectTransaction *tx)
run prefilter engines on a transaction
Definition: detect-engine-prefilter.c:93
RuleMatchCandidateTxArrayInit
void RuleMatchCandidateTxArrayInit(DetectEngineThreadCtx *det_ctx, uint32_t size)
Definition: detect.c:968
SIG_FLAG_DP_ANY
#define SIG_FLAG_DP_ANY
Definition: detect.h:203
DetectPortLookupGroup
DetectPort * DetectPortLookupGroup(DetectPort *dp, uint16_t port)
Function that find the group matching address in a group head.
Definition: detect-engine-port.c:674
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:999
detect-engine-threshold.h
DetectEngineThreadCtx_::io_ctx
DetectEngineIPOnlyThreadCtx io_ctx
Definition: detect.h:1138
Signature_::mask
SignatureMask mask
Definition: detect.h:549
app-layer.h
RuleMatchCandidateTx
Definition: detect.h:1007
DetectEngineThreadCtx_::TenantGetId
uint32_t(* TenantGetId)(const void *, const Packet *p)
Definition: detect.h:1044
PrefilterRuleStore_::rule_id_array
SigIntId * rule_id_array
Definition: util-prefilter.h:38
PacketEngineEvents_::cnt
uint8_t cnt
Definition: decode.h:308
Flow_::de_ctx_version
uint32_t de_ctx_version
Definition: flow.h:477
DetectProtoContainsProto
int DetectProtoContainsProto(const DetectProto *dp, int proto)
see if a DetectProto contains a certain proto
Definition: detect-engine-proto.c:135
DetectEngineThreadCtx_::match_array
Signature ** match_array
Definition: detect.h:1112