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