suricata
detect.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2025 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  * 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  /**
74  * Either ACTION_DROP (drop:packet) or ACTION_ACCEPT (accept:hook)
75  *
76  * ACTION_DROP means the default policy of drop:packet is applied
77  * ACTION_ACCEPT means the default policy of accept:hook is applied
78  */
79  const uint8_t default_action;
80  const SigGroupHead *sgh;
82 
83 /* prototypes */
84 static DetectRunScratchpad DetectRunSetup(const DetectEngineCtx *de_ctx,
85  DetectEngineThreadCtx *det_ctx, Packet *const p, Flow *const pflow,
86  const uint8_t default_action);
87 static void DetectRunInspectIPOnly(ThreadVars *tv, const DetectEngineCtx *de_ctx,
88  DetectEngineThreadCtx *det_ctx, Flow * const pflow, Packet * const p);
89 static inline void DetectRunGetRuleGroup(const DetectEngineCtx *de_ctx,
90  Packet * const p, Flow * const pflow, DetectRunScratchpad *scratch);
91 static inline void DetectRunPrefilterPkt(ThreadVars *tv, const DetectEngineCtx *de_ctx,
92  DetectEngineThreadCtx *det_ctx, Packet *p, DetectRunScratchpad *scratch);
93 static inline uint8_t DetectRulePacketRules(ThreadVars *const tv,
94  const DetectEngineCtx *const de_ctx, DetectEngineThreadCtx *const det_ctx, Packet *const p,
95  Flow *const pflow, const DetectRunScratchpad *scratch);
96 static void DetectRunTx(ThreadVars *tv, DetectEngineCtx *de_ctx,
97  DetectEngineThreadCtx *det_ctx, Packet *p,
98  Flow *f, DetectRunScratchpad *scratch);
99 static void DetectRunFrames(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
100  Packet *p, Flow *f, DetectRunScratchpad *scratch);
101 static inline void DetectRunPostRules(ThreadVars *tv, const DetectEngineCtx *de_ctx,
102  DetectEngineThreadCtx *det_ctx, Packet *const p, Flow *const pflow,
103  DetectRunScratchpad *scratch);
104 static void DetectRunCleanup(DetectEngineThreadCtx *det_ctx,
105  Packet *p, Flow * const pflow);
106 static inline void DetectRunAppendDefaultAccept(DetectEngineThreadCtx *det_ctx, Packet *p);
107 
108 /** \internal
109  */
110 static void DetectRun(ThreadVars *th_v,
112  Packet *p)
113 {
114  SCEnter();
115  SCLogDebug("pcap_cnt %" PRIu64 " direction %s pkt_src %s", PcapPacketCntGet(p),
116  p->flow ? (FlowGetPacketDirection(p->flow, p) == TOSERVER ? "toserver" : "toclient")
117  : "noflow",
118  PktSrcToString(p->pkt_src));
119 
120  /* Load the Packet's flow early, even though it might not be needed.
121  * Mark as a constant pointer, although the flow itself can change. */
122  Flow * const pflow = p->flow;
123 
124  DetectRunScratchpad scratch = DetectRunSetup(de_ctx, det_ctx, p, pflow, ACTION_DROP);
125 
126  /* run the IPonly engine */
127  DetectRunInspectIPOnly(th_v, de_ctx, det_ctx, pflow, p);
128 
129  /* get our rule group */
130  DetectRunGetRuleGroup(de_ctx, p, pflow, &scratch);
131  /* if we didn't get a sig group head, we
132  * have nothing to do.... */
133  if (scratch.sgh == NULL) {
134  SCLogDebug("no sgh for this packet, nothing to match against");
135  goto end;
136  }
137 
138  /* run the prefilters for packets */
139  DetectRunPrefilterPkt(th_v, de_ctx, det_ctx, p, &scratch);
140 
142  /* inspect the rules against the packet */
143  const uint8_t pkt_policy = DetectRulePacketRules(th_v, de_ctx, det_ctx, p, pflow, &scratch);
145 
146  /* Only FW rules will already have set the action, IDS rules go through PacketAlertFinalize
147  *
148  * If rules told us to drop or accept:packet/accept:flow, we skip app_filter and app_td.
149  *
150  * accept:hook won't have set the pkt_policy, so we simply continue.
151  *
152  * TODO what about app state progression, cleanup and such? */
153  if (pkt_policy & (ACTION_DROP | ACTION_ACCEPT)) {
154  goto end;
155  }
156 
157  /* run tx/state inspection. Don't call for ICMP error msgs. */
158  if (pflow && pflow->alstate && likely(pflow->proto == p->proto)) {
159  if (p->proto == IPPROTO_TCP) {
160  if ((p->flags & PKT_STREAM_EST) == 0) {
161  SCLogDebug("packet %" PRIu64 ": skip tcp non-established", PcapPacketCntGet(p));
162  DetectRunAppendDefaultAccept(det_ctx, p);
163  goto end;
164  }
165  const TcpSession *ssn = p->flow->protoctx;
166  bool setting_nopayload = p->flow->alparser &&
170  // we may be right after disabling app-layer (ssh)
171  if (ssn &&
172  ((ssn->flags & STREAMTCP_FLAG_APP_LAYER_DISABLED) == 0 || setting_nopayload)) {
173  // PACKET_PROFILING_DETECT_START(p, PROF_DETECT_TX);
174  DetectRunFrames(th_v, de_ctx, det_ctx, p, pflow, &scratch);
175  // PACKET_PROFILING_DETECT_END(p, PROF_DETECT_TX);
176  }
177  // no update to transactions
178  if (!PKT_IS_PSEUDOPKT(p) && p->app_update_direction == 0 &&
179  ((PKT_IS_TOSERVER(p) && (p->flow->flags & FLOW_TS_APP_UPDATED) == 0) ||
180  (PKT_IS_TOCLIENT(p) && (p->flow->flags & FLOW_TC_APP_UPDATED) == 0))) {
181  SCLogDebug("packet %" PRIu64 ": no app-layer update", PcapPacketCntGet(p));
182  DetectRunAppendDefaultAccept(det_ctx, p);
183  goto end;
184  }
185  } else if (p->proto == IPPROTO_UDP) {
186  DetectRunFrames(th_v, de_ctx, det_ctx, p, pflow, &scratch);
187  }
188 
190  DetectRunTx(th_v, de_ctx, det_ctx, p, pflow, &scratch);
192  /* see if we need to increment the inspect_id and reset the de_state */
195  pflow, pflow->alparser, pflow->alstate, scratch.flow_flags, (scratch.sgh == NULL));
197  } else {
198  SCLogDebug("packet %" PRIu64 ": no flow / app-layer", PcapPacketCntGet(p));
199  DetectRunAppendDefaultAccept(det_ctx, p);
200  }
201 
202 end:
203  DetectRunPostRules(th_v, de_ctx, det_ctx, p, pflow, &scratch);
204 
205  DetectRunCleanup(det_ctx, p, pflow);
206  SCReturn;
207 }
208 
209 /** \internal
210  */
211 static void DetectRunPacketHook(ThreadVars *th_v, const DetectEngineCtx *de_ctx,
212  DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p)
213 {
214  SCEnter();
215  SCLogDebug("pcap_cnt %" PRIu64 " direction %s pkt_src %s", PcapPacketCntGet(p),
216  p->flow ? (FlowGetPacketDirection(p->flow, p) == TOSERVER ? "toserver" : "toclient")
217  : "noflow",
218  PktSrcToString(p->pkt_src));
219 
220  /* Load the Packet's flow early, even though it might not be needed.
221  * Mark as a constant pointer, although the flow itself can change. */
222  Flow *const pflow = p->flow;
223 
224  DetectRunScratchpad scratch = DetectRunSetup(de_ctx, det_ctx, p, pflow, ACTION_ACCEPT);
225  scratch.sgh = sgh;
226 
227  /* if we didn't get a sig group head, we
228  * have nothing to do.... */
229  if (scratch.sgh == NULL) {
230  SCLogDebug("no sgh for this packet, nothing to match against");
231  goto end;
232  }
233 
234  /* run the prefilters for packets */
235  DetectRunPrefilterPkt(th_v, de_ctx, det_ctx, p, &scratch);
236 
237  // PACKET_PROFILING_DETECT_START(p, PROF_DETECT_RULES); // TODO
238  /* inspect the rules against the packet */
239  const uint8_t pkt_policy = DetectRulePacketRules(th_v, de_ctx, det_ctx, p, pflow, &scratch);
240  // PACKET_PROFILING_DETECT_END(p, PROF_DETECT_RULES);
241  if (pkt_policy & (ACTION_DROP | ACTION_ACCEPT)) {
242  goto end;
243  }
244 
245 end:
246  DetectRunPostRules(th_v, de_ctx, det_ctx, p, pflow, &scratch);
247 
248  DetectRunCleanup(det_ctx, p, pflow);
249  SCReturn;
250 }
251 
252 static void DetectRunPostMatch(ThreadVars *tv,
253  DetectEngineThreadCtx *det_ctx, Packet *p,
254  const Signature *s)
255 {
256  /* run the packet match functions */
258  if (smd != NULL) {
260 
261  SCLogDebug("running match functions, sm %p", smd);
262 
263  while (1) {
265  (void)sigmatch_table[smd->type].Match(det_ctx, p, s, smd->ctx);
266  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
267  if (smd->is_last)
268  break;
269  smd++;
270  }
271  }
272 }
273 
274 /**
275  * \brief Get the SigGroupHead for a packet.
276  *
277  * \param de_ctx detection engine context
278  * \param p packet
279  *
280  * \retval sgh the SigGroupHead or NULL if non applies to the packet
281  */
283  const Packet *p)
284 {
285  SCEnter();
286  SigGroupHead *sgh = NULL;
287 
288  /* use ethernet non-IP sgh if we're ethernet but have no (valid) IP layer on top of it. */
289  if (PacketIsEthernet(p) && p->proto == 0 && de_ctx->eth_non_ip_sgh != NULL) {
290  SCLogDebug("using eth_non_ip_sgh %p", de_ctx->eth_non_ip_sgh);
291  SCReturnPtr(de_ctx->eth_non_ip_sgh, "SigGroupHead");
292  }
293 
294  /* if the packet proto is 0 (not set), we're inspecting it against
295  * the decoder events sgh we have. */
296  if (p->proto == 0 && p->events.cnt > 0) {
297  SCReturnPtr(de_ctx->decoder_event_sgh, "SigGroupHead");
298  } else if (p->proto == 0) {
299  if (!(PacketIsIPv4(p) || PacketIsIPv6(p))) {
300  /* not IP, so nothing to do */
301  SCReturnPtr(NULL, "SigGroupHead");
302  }
303  }
304 
305  /* select the flow_gh */
306  const int dir = (p->flowflags & FLOW_PKT_TOCLIENT) == 0;
307 
308  int proto = PacketGetIPProto(p);
309  if (proto == IPPROTO_TCP) {
310  DetectPort *list = de_ctx->flow_gh[dir].tcp;
311  SCLogDebug("tcp toserver %p, tcp toclient %p: going to use %p", de_ctx->flow_gh[1].tcp,
312  de_ctx->flow_gh[0].tcp, de_ctx->flow_gh[dir].tcp);
313  const uint16_t port = dir ? p->dp : p->sp;
314  SCLogDebug("tcp port %u -> %u:%u", port, p->sp, p->dp);
315  DetectPort *sghport = DetectPortLookupGroup(list, port);
316  if (sghport != NULL)
317  sgh = sghport->sh;
318  SCLogDebug("TCP list %p, port %u, direction %s, sghport %p, sgh %p", list, port,
319  dir ? "toserver" : "toclient", sghport, sgh);
320  } else if (proto == IPPROTO_UDP) {
321  DetectPort *list = de_ctx->flow_gh[dir].udp;
322  uint16_t port = dir ? p->dp : p->sp;
323  DetectPort *sghport = DetectPortLookupGroup(list, port);
324  if (sghport != NULL)
325  sgh = sghport->sh;
326  SCLogDebug("UDP list %p, port %u, direction %s, sghport %p, sgh %p", list, port,
327  dir ? "toserver" : "toclient", sghport, sgh);
328  } else {
329  sgh = de_ctx->flow_gh[dir].sgh[proto];
330  }
331 
332  SCReturnPtr(sgh, "SigGroupHead");
333 }
334 
335 static inline void DetectPrefilterCopyDeDup(
337 {
338  SigIntId *pf_ptr = det_ctx->pmq.rule_id_array;
339  uint32_t final_cnt = det_ctx->pmq.rule_id_array_cnt;
340  Signature **sig_array = de_ctx->sig_array;
341  Signature **match_array = det_ctx->match_array;
342  SigIntId previous_id = (SigIntId)-1;
343  while (final_cnt-- > 0) {
344  SigIntId id = *pf_ptr++;
345  Signature *s = sig_array[id];
346 
347  /* As the prefilter list can contain duplicates, check for that here. */
348  if (likely(id != previous_id)) {
349  *match_array++ = s;
350  previous_id = id;
351  }
352  }
353 
354  det_ctx->match_array_cnt = (uint32_t)(match_array - det_ctx->match_array);
356  PMQ_RESET(&det_ctx->pmq);
357 }
358 
359 /** \internal
360  * \brief update flow's file tracking flags based on the detection engine
361  * A set of flags is prepared that is sent to the File API. The
362  File API may reject one or more based on the global force settings.
363  */
364 static inline void
365 DetectPostInspectFileFlagsUpdate(Flow *f, const SigGroupHead *sgh, uint8_t direction)
366 {
367  uint16_t flow_file_flags = FLOWFILE_INIT;
368 
369  if (sgh == NULL) {
370  SCLogDebug("requesting disabling all file features for flow");
371  flow_file_flags = FLOWFILE_NONE;
372  } else {
373  if (sgh->filestore_cnt == 0) {
374  SCLogDebug("requesting disabling filestore for flow");
375  flow_file_flags |= (FLOWFILE_NO_STORE_TS|FLOWFILE_NO_STORE_TC);
376  }
377 #ifdef HAVE_MAGIC
378  if (!(sgh->flags & SIG_GROUP_HEAD_HAVEFILEMAGIC)) {
379  SCLogDebug("requesting disabling magic for flow");
380  flow_file_flags |= (FLOWFILE_NO_MAGIC_TS|FLOWFILE_NO_MAGIC_TC);
381  }
382 #endif
383  if (!(sgh->flags & SIG_GROUP_HEAD_HAVEFILEMD5)) {
384  SCLogDebug("requesting disabling md5 for flow");
385  flow_file_flags |= (FLOWFILE_NO_MD5_TS|FLOWFILE_NO_MD5_TC);
386  }
387  if (!(sgh->flags & SIG_GROUP_HEAD_HAVEFILESHA1)) {
388  SCLogDebug("requesting disabling sha1 for flow");
389  flow_file_flags |= (FLOWFILE_NO_SHA1_TS|FLOWFILE_NO_SHA1_TC);
390  }
391  if (!(sgh->flags & SIG_GROUP_HEAD_HAVEFILESHA256)) {
392  SCLogDebug("requesting disabling sha256 for flow");
393  flow_file_flags |= (FLOWFILE_NO_SHA256_TS|FLOWFILE_NO_SHA256_TC);
394  }
395  }
396  if (flow_file_flags != 0) {
397  FileUpdateFlowFileFlags(f, flow_file_flags, direction);
398  }
399 }
400 
401 static inline void
402 DetectRunPostGetFirstRuleGroup(const Packet *p, Flow *pflow, const SigGroupHead *sgh)
403 {
404  if ((p->flowflags & FLOW_PKT_TOSERVER) && !(pflow->flags & FLOW_SGH_TOSERVER)) {
405  /* first time we see this toserver sgh, store it */
406  pflow->sgh_toserver = sgh;
407  pflow->flags |= FLOW_SGH_TOSERVER;
408 
409  if (p->proto == IPPROTO_TCP && (sgh == NULL || !(sgh->flags & SIG_GROUP_HEAD_HAVERAWSTREAM))) {
410  if (pflow->protoctx != NULL) {
411  TcpSession *ssn = pflow->protoctx;
412  SCLogDebug("STREAMTCP_STREAM_FLAG_DISABLE_RAW ssn.client");
414  }
415  }
416 
417  DetectPostInspectFileFlagsUpdate(pflow,
418  pflow->sgh_toserver, STREAM_TOSERVER);
419 
420  } else if ((p->flowflags & FLOW_PKT_TOCLIENT) && !(pflow->flags & FLOW_SGH_TOCLIENT)) {
421  pflow->sgh_toclient = sgh;
422  pflow->flags |= FLOW_SGH_TOCLIENT;
423 
424  if (p->proto == IPPROTO_TCP && (sgh == NULL || !(sgh->flags & SIG_GROUP_HEAD_HAVERAWSTREAM))) {
425  if (pflow->protoctx != NULL) {
426  TcpSession *ssn = pflow->protoctx;
427  SCLogDebug("STREAMTCP_STREAM_FLAG_DISABLE_RAW ssn.server");
429  }
430  }
431 
432  DetectPostInspectFileFlagsUpdate(pflow,
433  pflow->sgh_toclient, STREAM_TOCLIENT);
434  }
435 }
436 
437 static inline void DetectRunGetRuleGroup(
438  const DetectEngineCtx *de_ctx,
439  Packet * const p, Flow * const pflow,
440  DetectRunScratchpad *scratch)
441 {
442  const SigGroupHead *sgh = NULL;
443 
444  if (pflow) {
445  bool use_flow_sgh = false;
446  /* Get the stored sgh from the flow (if any). Make sure we're not using
447  * the sgh for icmp error packets part of the same stream. */
448  if (PacketGetIPProto(p) == pflow->proto) { /* filter out icmp */
450  if ((p->flowflags & FLOW_PKT_TOSERVER) && (pflow->flags & FLOW_SGH_TOSERVER)) {
451  sgh = pflow->sgh_toserver;
452  SCLogDebug("sgh = pflow->sgh_toserver; => %p", sgh);
453  use_flow_sgh = true;
454  } else if ((p->flowflags & FLOW_PKT_TOCLIENT) && (pflow->flags & FLOW_SGH_TOCLIENT)) {
455  sgh = pflow->sgh_toclient;
456  SCLogDebug("sgh = pflow->sgh_toclient; => %p", sgh);
457  use_flow_sgh = true;
458  }
460  }
461 
462  if (!(use_flow_sgh)) {
466 
467  /* HACK: prevent the wrong sgh (or NULL) from being stored in the
468  * flow's sgh pointers */
469  if (PacketIsICMPv4(p) && ICMPV4_DEST_UNREACH_IS_VALID(p)) {
470  ; /* no-op */
471  } else {
472  /* store the found sgh (or NULL) in the flow to save us
473  * from looking it up again for the next packet.
474  * Also run other tasks */
475  DetectRunPostGetFirstRuleGroup(p, pflow, sgh);
476  }
477  }
478  } else { /* p->flags & PKT_HAS_FLOW */
479  /* no flow */
480 
484  }
485 
486  scratch->sgh = sgh;
487 }
488 
489 static void DetectRunInspectIPOnly(ThreadVars *tv, const DetectEngineCtx *de_ctx,
490  DetectEngineThreadCtx *det_ctx,
491  Flow * const pflow, Packet * const p)
492 {
493  if (pflow) {
495  SCLogDebug("testing against \"ip-only\" signatures");
496 
498  IPOnlyMatchPacket(tv, de_ctx, det_ctx, &de_ctx->io_ctx, p);
500  }
501  } else { /* p->flags & PKT_HAS_FLOW */
502  /* no flow */
503 
504  /* Even without flow we should match the packet src/dst */
506  IPOnlyMatchPacket(tv, de_ctx, det_ctx, &de_ctx->io_ctx, p);
508  }
509 }
510 
511 /** \internal
512  * \brief inspect the rule header: protocol, ports, etc
513  * \retval bool false if no match, true if match */
514 static inline bool DetectRunInspectRuleHeader(
515  const Packet *p, const Flow *f, const Signature *s, const uint32_t sflags)
516 {
517  /* check if this signature has a requirement for flowvars of some type
518  * and if so, if we actually have any in the flow. If not, the sig
519  * can't match and we skip it. */
520  if ((p->flags & PKT_HAS_FLOW) && (sflags & SIG_FLAG_REQUIRE_FLOWVAR)) {
521  DEBUG_VALIDATE_BUG_ON(f == NULL);
522 
523  /* no flowvars? skip this sig */
524  const bool fv = f->flowvar != NULL;
525  if (!fv) {
526  SCLogDebug("skipping sig as the flow has no flowvars and sig "
527  "has SIG_FLAG_REQUIRE_FLOWVAR flag set.");
528  return false;
529  }
530  }
531 
532  if (!(s->proto == NULL)) {
533  const uint8_t s_proto_flags = s->proto->flags;
534  /* TODO does it make sense to move these flags to s->flags? */
535  if ((s_proto_flags & DETECT_PROTO_IPV4) && !PacketIsIPv4(p)) {
536  SCLogDebug("ip version didn't match");
537  return false;
538  }
539  if ((s_proto_flags & DETECT_PROTO_IPV6) && !PacketIsIPv6(p)) {
540  SCLogDebug("ip version didn't match");
541  return false;
542  }
543  if (DetectProtoContainsProto(s->proto, PacketGetIPProto(p)) == 0) {
544  SCLogDebug("proto didn't match");
545  if (PacketIsEthernet(p) &&
546  (s_proto_flags & (DETECT_PROTO_ETHERNET | DETECT_PROTO_ARP))) {
547  SCLogDebug("checking ether/arp protocol");
548  if ((s_proto_flags & DETECT_PROTO_ARP) && !PacketIsARP(p)) {
549  return false;
550  }
551  SCLogDebug("checking eth protocol: match!");
552  } else {
553  return false;
554  }
555  }
556  }
557 
558  /* check the source & dst port in the sig */
559  if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP || p->proto == IPPROTO_SCTP) {
560  if (!(sflags & SIG_FLAG_DP_ANY)) {
561  if (p->flags & PKT_IS_FRAGMENT)
562  return false;
563  const DetectPort *dport = DetectPortLookupGroup(s->dp, p->dp);
564  if (dport == NULL) {
565  SCLogDebug("dport didn't match.");
566  return false;
567  }
568  }
569  if (!(sflags & SIG_FLAG_SP_ANY)) {
570  if (p->flags & PKT_IS_FRAGMENT)
571  return false;
572  const DetectPort *sport = DetectPortLookupGroup(s->sp, p->sp);
573  if (sport == NULL) {
574  SCLogDebug("sport didn't match.");
575  return false;
576  }
577  }
578  } else if ((sflags & (SIG_FLAG_DP_ANY|SIG_FLAG_SP_ANY)) != (SIG_FLAG_DP_ANY|SIG_FLAG_SP_ANY)) {
579  SCLogDebug("port-less protocol and sig needs ports");
580  return false;
581  }
582 
583  /* check the destination address */
584  if (!(sflags & SIG_FLAG_DST_ANY)) {
585  if (PacketIsIPv4(p)) {
587  return false;
588  } else if (PacketIsIPv6(p)) {
590  return false;
591  }
592  }
593  /* check the source address */
594  if (!(sflags & SIG_FLAG_SRC_ANY)) {
595  if (PacketIsIPv4(p)) {
597  return false;
598  } else if (PacketIsIPv6(p)) {
600  return false;
601  }
602  }
603 
604  return true;
605 }
606 
607 /** \internal
608  * \brief run packet/stream prefilter engines
609  */
610 static inline void DetectRunPrefilterPkt(ThreadVars *tv, const DetectEngineCtx *de_ctx,
611  DetectEngineThreadCtx *det_ctx, Packet *p, DetectRunScratchpad *scratch)
612 {
613  /* create our prefilter mask */
614  PacketCreateMask(p, &p->sig_mask, scratch->alproto, scratch->app_decoder_events);
615  /* run the prefilter engines */
616  Prefilter(det_ctx, scratch->sgh, p, scratch->flow_flags, p->sig_mask);
617  /* create match list if we have non-pf and/or pf */
618  if (det_ctx->pmq.rule_id_array_cnt) {
619 #ifdef PROFILING
620  if (tv) {
622  &tv->stats, det_ctx->counter_mpm_list, (int64_t)det_ctx->pmq.rule_id_array_cnt);
623  }
624 #endif
626  DetectPrefilterCopyDeDup(de_ctx, det_ctx);
628  }
629 }
630 
631 /** \internal
632  * \brief check if the tx whose id is given is the only one
633  * live transaction for the flow in the given direction
634  *
635  * \param f flow
636  * \param txid transaction id
637  * \param dir direction
638  *
639  * \retval bool true if we are sure this tx is the only one live in said direction
640  */
641 static bool IsOnlyTxInDirection(Flow *f, uint64_t txid, uint8_t dir)
642 {
643  uint64_t tx_cnt = AppLayerParserGetTxCnt(f, f->alstate);
644  if (tx_cnt == txid + 1) {
645  // only live tx
646  return true;
647  }
648  if (tx_cnt == txid + 2) {
649  // 2 live txs, one after us
650  void *tx = AppLayerParserGetTx(f->proto, f->alproto, f->alstate, txid + 1);
651  if (tx) {
653  // test if the other tx is unidirectional in the other way
654  if ((dir == STREAM_TOSERVER && (txd->flags & APP_LAYER_TX_SKIP_INSPECT_TS)) ||
655  (dir == STREAM_TOCLIENT && (txd->flags & APP_LAYER_TX_SKIP_INSPECT_TC))) {
656  return true;
657  }
658  }
659  }
660  return false;
661 }
662 
663 static int SortHelper(const void *a, const void *b)
664 {
665  const Signature *sa = *(const Signature **)a;
666  const Signature *sb = *(const Signature **)b;
667  if (sa->iid == sb->iid)
668  return 0;
669  return sa->iid > sb->iid ? 1 : -1;
670 }
671 
672 static inline uint8_t DetectRulePacketRules(ThreadVars *const tv,
673  const DetectEngineCtx *const de_ctx, DetectEngineThreadCtx *const det_ctx, Packet *const p,
674  Flow *const pflow, const DetectRunScratchpad *scratch)
675 {
676  uint8_t action = 0;
677  bool fw_verdict = false;
678  const bool have_fw_rules = EngineModeIsFirewall();
679  const Signature *next_s = NULL;
680 
681  /* inspect the sigs against the packet */
682  /* Prefetch the next signature. */
683  SigIntId match_cnt = det_ctx->match_array_cnt;
684 #ifdef PROFILING
685  if (tv) {
686  StatsCounterAvgAddI64(&tv->stats, det_ctx->counter_match_list, (int64_t)match_cnt);
687  }
688 #endif
689  Signature **match_array = det_ctx->match_array;
690 
691  SGH_PROFILING_RECORD(det_ctx, scratch->sgh);
692 #ifdef PROFILING
693  if (match_cnt >= de_ctx->profile_match_logging_threshold)
694  RulesDumpMatchArray(det_ctx, scratch->sgh, p);
695 #endif
696 
697  bool skip_fw = false;
698  uint32_t sflags, next_sflags = 0;
699  if (match_cnt) {
700  next_s = *match_array++;
701  next_sflags = next_s->flags;
702  }
703  while (match_cnt--) {
705  bool break_out_of_packet_filter = false;
706  uint8_t alert_flags = 0;
707 #ifdef PROFILE_RULES
708  bool smatch = false; /* signature match */
709 #endif
710  const Signature *s = next_s;
711  sflags = next_sflags;
712  if (match_cnt) {
713  next_s = *match_array++;
714  next_sflags = next_s->flags;
715  }
716 
717  SCLogDebug("packet %" PRIu64 ": inspecting signature id %" PRIu32 "", PcapPacketCntGet(p),
718  s->id);
719 
720  /* if we accept:hook'd the `packet_filter` hook, we skip the rest of the firewall rules. */
721  if (s->flags & SIG_FLAG_FIREWALL) {
722  if (skip_fw) {
723  SCLogDebug("skipping firewall rule %u", s->id);
724  goto next;
725  }
726  } else if (have_fw_rules) {
727  /* fw mode, we skip anything after the fw rules if:
728  * - flow pass is set
729  * - packet pass (e.g. exception policy) */
730  if (p->flags & PKT_NOPACKET_INSPECTION ||
731  (pflow != NULL && pflow->flags & (FLOW_ACTION_PASS))) {
732  SCLogDebug("skipping firewall rule %u", s->id);
733  break_out_of_packet_filter = true;
734  goto next;
735  }
736  }
737 
738  if (s->app_inspect != NULL) {
739  goto next; // handle sig in DetectRunTx
740  }
741  if (s->frame_inspect != NULL) {
742  goto next; // handle sig in DetectRunFrame
743  }
744 
745  /* skip pkt sigs for flow end packets */
746  if ((p->flags & PKT_PSEUDO_STREAM_END) != 0 && s->type == SIG_TYPE_PKT)
747  goto next;
748 
749  /* don't run mask check for stateful rules.
750  * There we depend on prefilter */
751  if ((s->mask & p->sig_mask) != s->mask) {
752  SCLogDebug("mask mismatch %x & %x != %x", s->mask, p->sig_mask, s->mask);
753  goto next;
754  }
755 
756  if (SigDsizePrefilter(p, s, sflags))
757  goto next;
758 
759  /* if the sig has alproto and the session as well they should match */
760  if (likely(sflags & SIG_FLAG_APPLAYER)) {
761  if (s->alproto != ALPROTO_UNKNOWN && !AppProtoEquals(s->alproto, scratch->alproto)) {
762  SCLogDebug("alproto mismatch");
763  goto next;
764  }
765  }
766 
767  if (DetectRunInspectRuleHeader(p, pflow, s, sflags) == false) {
768  goto next;
769  }
770 
771  if (!DetectEnginePktInspectionRun(tv, det_ctx, s, pflow, p, &alert_flags)) {
772  goto next;
773  }
774 
775 #ifdef PROFILE_RULES
776  smatch = true;
777 #endif
778  DetectRunPostMatch(tv, det_ctx, p, s);
779 
780  uint64_t txid = PACKET_ALERT_NOTX;
781  if (pflow && pflow->alstate) {
782  uint8_t dir = (p->flowflags & FLOW_PKT_TOCLIENT) ? STREAM_TOCLIENT : STREAM_TOSERVER;
784  if ((s->alproto != ALPROTO_UNKNOWN && pflow->proto == IPPROTO_UDP) ||
785  (de_ctx->guess_applayer && IsOnlyTxInDirection(pflow, txid, dir))) {
786  // if there is a UDP specific app-layer signature,
787  // or only one live transaction
788  // try to use the good tx for the packet direction
789  void *tx_ptr =
790  AppLayerParserGetTx(pflow->proto, pflow->alproto, pflow->alstate, txid);
791  AppLayerTxData *txd =
792  tx_ptr ? AppLayerParserGetTxData(pflow->proto, pflow->alproto, tx_ptr)
793  : NULL;
795  alert_flags |= PACKET_ALERT_FLAG_TX;
796  if (pflow->proto != IPPROTO_UDP) {
797  alert_flags |= PACKET_ALERT_FLAG_TX_GUESSED;
798  }
800  }
801  }
802  }
803  AlertQueueAppend(det_ctx, s, p, txid, alert_flags);
804 
805  if (det_ctx->post_rule_work_queue.len > 0) {
806  /* run post match prefilter engines on work queue */
807  PrefilterPostRuleMatch(det_ctx, scratch->sgh, p, pflow);
808 
809  if (det_ctx->pmq.rule_id_array_cnt > 0) {
810  /* undo "prefetch" */
811  if (next_s)
812  match_array--;
813  SCLogDebug("sig_array_len %u det_ctx->pmq.rule_id_array_cnt %u",
815  const Signature **r = det_ctx->replace;
816  for (uint32_t x = 0; x < match_cnt; x++) {
817  *r++ = match_array[x];
818  SCLogDebug("appended %u", match_array[x]->id);
819  }
820  /* append the prefilter results, then sort it */
821  for (uint32_t x = 0; x < det_ctx->pmq.rule_id_array_cnt; x++) {
822  SCLogDebug("adding iid %u", det_ctx->pmq.rule_id_array[x]);
823  Signature *ts = de_ctx->sig_array[det_ctx->pmq.rule_id_array[x]];
824  SCLogDebug("adding id %u", ts->id);
825  if (ts->app_inspect == NULL) {
826  *r++ = ts;
827  match_cnt++;
828  }
829  }
830  if (match_cnt > 1) {
831  qsort(det_ctx->replace, match_cnt, sizeof(Signature *), SortHelper);
832  }
833  /* rewrite match_array to include the new additions, and deduplicate
834  * while at it. */
835  Signature **m = match_array;
836  Signature *last_sig = NULL;
837  uint32_t skipped = 0;
838  for (uint32_t x = 0; x < match_cnt; x++) {
839  /* de-duplicate */
840  if (last_sig == *m) {
841  skipped++;
842  continue;
843  }
844  last_sig = *m;
845  *m++ = (Signature *)det_ctx->replace[x];
846  }
847  match_cnt -= skipped;
848  /* prefetch next */
849  next_s = *match_array++;
850  next_sflags = next_s->flags;
851  SCLogDebug("%u rules added", det_ctx->pmq.rule_id_array_cnt);
852  det_ctx->post_rule_work_queue.len = 0;
853  PMQ_RESET(&det_ctx->pmq);
854  }
855  }
856 
857  /* firewall logic in the packet:filter table:
858  * 1. firewall rules preceed the packet:td rules in the list
859  * 2. if no rule issues an accept, we drop
860  * 3. drop is immediate
861  * 4. accept:
862  * - hook: skip rest of fw rules, inspect packet:td rules
863  * - packet: immediate accept, no packet:td or app:* inspect
864  * - flow: as packet, but applied to all future packets in the
865  * flow as well
866  */
867  if (s->flags & SIG_FLAG_FIREWALL) {
868  if (s->action & (ACTION_ACCEPT)) {
869  fw_verdict = true;
870 
871  enum ActionScope as = s->action_scope;
872  if (as == ACTION_SCOPE_HOOK) {
873  /* accept:hook: jump to first TD. Implemented as:
874  * skip until the first TD rule.
875  * Don't update action as we're just continuing to the next hook. */
876  skip_fw = true;
877 
878  } else if (as == ACTION_SCOPE_PACKET) {
879  /* accept:packet: break loop, return accept */
880  action |= s->action;
881  break_out_of_packet_filter = true;
882 
883  } else if (as == ACTION_SCOPE_FLOW) {
884  /* accept:flow: break loop, return accept */
885  action |= s->action;
886  break_out_of_packet_filter = true;
887 
888  /* set immediately, as we're in hook "packet_filter" */
889  if (pflow) {
890  pflow->flags |= FLOW_ACTION_ACCEPT;
891  }
892  }
893  } else if (s->action & ACTION_DROP) {
894  /* apply a drop immediately here */
895  fw_verdict = true;
896  action |= s->action;
897  break_out_of_packet_filter = true;
898  }
899  }
900 next:
901  DetectVarProcessList(det_ctx, pflow, p);
902  DetectReplaceFree(det_ctx);
903  RULE_PROFILING_END(det_ctx, s, smatch, p);
904 
905  /* fw accept:packet or accept:flow means we're done here */
906  if (break_out_of_packet_filter)
907  break;
908 
909  continue;
910  }
911 
912  /* if no rule told us to accept, and no rule explicitly dropped, we invoke the default drop
913  * policy
914  */
915  if (have_fw_rules && scratch->default_action == ACTION_DROP) {
916  if (!fw_verdict) {
919  action |= ACTION_DROP;
920  } else {
921  /* apply fw action */
922  p->action |= action;
923  }
924  }
925  return action;
926 }
927 
928 /** \internal
929  * \param default_action either ACTION_DROP (drop:packet) or ACTION_ACCEPT (accept:hook)
930  *
931  * ACTION_DROP means the default policy of drop:packet is applied
932  * ACTION_ACCEPT means the default policy of accept:hook is applied
933  */
934 static DetectRunScratchpad DetectRunSetup(const DetectEngineCtx *de_ctx,
935  DetectEngineThreadCtx *det_ctx, Packet *const p, Flow *const pflow,
936  const uint8_t default_action)
937 {
938  AppProto alproto = ALPROTO_UNKNOWN;
939  uint8_t flow_flags = 0; /* flow/state flags */
940  bool app_decoder_events = false;
941 
943 
944 #ifdef UNITTESTS
945  if (RunmodeIsUnittests()) {
946  p->alerts.cnt = 0;
947  p->alerts.discarded = 0;
948  p->alerts.suppressed = 0;
949  }
950 #endif
951  det_ctx->filestore_cnt = 0;
952  det_ctx->base64_decoded_len = 0;
953  det_ctx->raw_stream_progress = 0;
954  det_ctx->match_array_cnt = 0;
955  det_ctx->json_content_len = 0;
956 
957  det_ctx->alert_queue_size = 0;
958  p->alerts.drop.action = 0;
959 
960 #ifdef DEBUG
961  if (p->flags & PKT_STREAM_ADD) {
962  det_ctx->pkt_stream_add_cnt++;
963  }
964 #endif
965 
966  /* grab the protocol state we will detect on */
967  if (p->flags & PKT_HAS_FLOW) {
968  DEBUG_VALIDATE_BUG_ON(pflow == NULL);
969 
970  if (p->flowflags & FLOW_PKT_TOSERVER) {
971  flow_flags = STREAM_TOSERVER;
972  SCLogDebug("flag STREAM_TOSERVER set");
973  } else if (p->flowflags & FLOW_PKT_TOCLIENT) {
974  flow_flags = STREAM_TOCLIENT;
975  SCLogDebug("flag STREAM_TOCLIENT set");
976  }
977  SCLogDebug("p->flowflags 0x%02x", p->flowflags);
978 
979  if (p->flags & PKT_PSEUDO_STREAM_END) {
980  flow_flags |= STREAM_EOF;
981  SCLogDebug("STREAM_EOF set");
982  }
983 
984  /* store tenant_id in the flow so that we can use it
985  * for creating pseudo packets */
986  if (p->tenant_id > 0 && pflow->tenant_id == 0) {
987  pflow->tenant_id = p->tenant_id;
988  }
989 
990  /* live ruleswap check for flow updates */
991  if (pflow->de_ctx_version == 0) {
992  /* first time this flow is inspected, set id */
993  pflow->de_ctx_version = de_ctx->version;
994  } else if (pflow->de_ctx_version != de_ctx->version) {
995  /* first time we inspect flow with this de_ctx, reset */
996  pflow->flags &= ~FLOW_SGH_TOSERVER;
997  pflow->flags &= ~FLOW_SGH_TOCLIENT;
998  pflow->sgh_toserver = NULL;
999  pflow->sgh_toclient = NULL;
1000 
1001  pflow->de_ctx_version = de_ctx->version;
1002  SCGenericVarFree(pflow->flowvar);
1003  pflow->flowvar = NULL;
1004 
1006  }
1007 
1008  /* Retrieve the app layer state and protocol and the tcp reassembled
1009  * stream chunks. */
1010  if ((p->proto == IPPROTO_TCP && (p->flags & PKT_STREAM_EST)) ||
1011  (p->proto == IPPROTO_UDP) ||
1013  {
1014  /* update flow flags with knowledge on disruptions */
1015  flow_flags = FlowGetDisruptionFlags(pflow, flow_flags);
1016  alproto = FlowGetAppProtocol(pflow);
1017  if (p->proto == IPPROTO_TCP && pflow->protoctx &&
1020  }
1021  SCLogDebug("alproto %u", alproto);
1022  } else {
1023  SCLogDebug("packet doesn't have established flag set (proto %d)", p->proto);
1024  }
1025 
1026  app_decoder_events = AppLayerParserHasDecoderEvents(pflow->alparser);
1027  }
1028 
1029  DetectRunScratchpad pad = { alproto, flow_flags, app_decoder_events, default_action, NULL };
1031  return pad;
1032 }
1033 
1034 static inline void DetectRunPostRules(ThreadVars *tv, const DetectEngineCtx *de_ctx,
1035  DetectEngineThreadCtx *det_ctx, Packet *const p, Flow *const pflow,
1036  DetectRunScratchpad *scratch)
1037 {
1038  /* so now let's iterate the alerts and remove the ones after a pass rule
1039  * matched (if any). This is done inside PacketAlertFinalize() */
1040  /* PR: installed "tag" keywords are handled after the threshold inspection */
1041 
1043  PacketAlertFinalize(de_ctx, det_ctx, p);
1044  if (p->alerts.cnt > 0) {
1045  StatsCounterAddI64(&tv->stats, det_ctx->counter_alerts, (uint64_t)p->alerts.cnt);
1046  }
1047  if (p->alerts.discarded > 0) {
1049  &tv->stats, det_ctx->counter_alerts_overflow, (uint64_t)p->alerts.discarded);
1050  }
1051  if (p->alerts.suppressed > 0) {
1053  &tv->stats, det_ctx->counter_alerts_suppressed, (uint64_t)p->alerts.suppressed);
1054  }
1056 
1057  /* firewall: "fail" closed if we don't have an ACCEPT. This can happen
1058  * if there was no rule group. */
1059  // TODO review packet src types here
1060  if (EngineModeIsFirewall() && !(p->action & ACTION_ACCEPT) && p->pkt_src == PKT_SRC_WIRE &&
1061  scratch->default_action == ACTION_DROP) {
1062  SCLogDebug("packet %" PRIu64 ": droppit as no ACCEPT set %02x (pkt %s)",
1065  }
1066 }
1067 
1068 static void DetectRunCleanup(DetectEngineThreadCtx *det_ctx,
1069  Packet *p, Flow * const pflow)
1070 {
1072  InspectionBufferClean(det_ctx);
1073 
1074  if (pflow != NULL) {
1075  /* update inspected tracker for raw reassembly */
1076  if (p->proto == IPPROTO_TCP && pflow->protoctx != NULL &&
1079  det_ctx->raw_stream_progress);
1080  }
1081  }
1083  SCReturn;
1084 }
1085 
1087 {
1089  det_ctx->tx_candidates = SCCalloc(size, sizeof(RuleMatchCandidateTx));
1090  if (det_ctx->tx_candidates == NULL) {
1091  FatalError("failed to allocate %" PRIu64 " bytes",
1092  (uint64_t)(size * sizeof(RuleMatchCandidateTx)));
1093  }
1094  det_ctx->tx_candidates_size = size;
1095  SCLogDebug("array initialized to %u elements (%"PRIu64" bytes)",
1096  size, (uint64_t)(size * sizeof(RuleMatchCandidateTx)));
1097 }
1098 
1100 {
1101  SCFree(det_ctx->tx_candidates);
1102  det_ctx->tx_candidates_size = 0;
1103 }
1104 
1105 /* if size >= cur_space */
1106 static inline bool RuleMatchCandidateTxArrayHasSpace(const DetectEngineThreadCtx *det_ctx,
1107  const uint32_t need)
1108 {
1109  if (det_ctx->tx_candidates_size >= need)
1110  return 1;
1111  return 0;
1112 }
1113 
1114 /* realloc */
1115 static int RuleMatchCandidateTxArrayExpand(DetectEngineThreadCtx *det_ctx, const uint32_t needed)
1116 {
1117  const uint32_t old_size = det_ctx->tx_candidates_size;
1118  uint32_t new_size = needed;
1119  void *ptmp = SCRealloc(det_ctx->tx_candidates, (new_size * sizeof(RuleMatchCandidateTx)));
1120  if (ptmp == NULL) {
1121  FatalError("failed to expand to %" PRIu64 " bytes",
1122  (uint64_t)(new_size * sizeof(RuleMatchCandidateTx)));
1123  // TODO can this be handled more gracefully?
1124  }
1125  det_ctx->tx_candidates = ptmp;
1126  det_ctx->tx_candidates_size = new_size;
1127  SCLogDebug("array expanded from %u to %u elements (%"PRIu64" bytes -> %"PRIu64" bytes)",
1128  old_size, new_size, (uint64_t)(old_size * sizeof(RuleMatchCandidateTx)),
1129  (uint64_t)(new_size * sizeof(RuleMatchCandidateTx))); (void)old_size;
1130  return 1;
1131 }
1132 
1133 /** \internal
1134  * \brief sort helper for sorting match candidates by id: ascending
1135  *
1136  * The id field is set from Signature::num, so we sort the candidates to match the signature
1137  * sort order (ascending), where candidates that have flags go first.
1138  */
1139 static int
1140 DetectRunTxSortHelper(const void *a, const void *b)
1141 {
1142  const RuleMatchCandidateTx *s0 = a;
1143  const RuleMatchCandidateTx *s1 = b;
1144  if (s1->id == s0->id) {
1145  if (s1->flags && !s0->flags)
1146  return 1;
1147  else if (!s1->flags && s0->flags)
1148  return -1;
1149  return 0;
1150  } else
1151  return s0->id > s1->id ? 1 : -1;
1152 }
1153 
1154 #if 0
1155 #define TRACE_SID_TXS(sid,txs,...) \
1156  do { \
1157  char _trace_buf[2048]; \
1158  snprintf(_trace_buf, sizeof(_trace_buf), __VA_ARGS__); \
1159  SCLogNotice("%p/%"PRIu64"/%u: %s", txs->tx_ptr, txs->tx_id, sid, _trace_buf); \
1160  } while(0)
1161 #else
1162 #define TRACE_SID_TXS(sid,txs,...)
1163 #endif
1164 
1165 // Get inner transaction for engine
1166 void *DetectGetInnerTx(void *tx_ptr, AppProto alproto, AppProto engine_alproto, uint8_t flow_flags)
1167 {
1168  if (unlikely(alproto == ALPROTO_DOH2)) {
1169  if (engine_alproto == ALPROTO_DNS) {
1170  // need to get the dns tx pointer
1171  tx_ptr = SCDoH2GetDnsTx(tx_ptr, flow_flags);
1172  } else if (engine_alproto != ALPROTO_HTTP2 && engine_alproto != ALPROTO_UNKNOWN) {
1173  // incompatible engine->alproto with flow alproto
1174  tx_ptr = NULL;
1175  }
1176  } else if (engine_alproto != alproto && engine_alproto != ALPROTO_UNKNOWN) {
1177  // incompatible engine->alproto with flow alproto
1178  tx_ptr = NULL;
1179  }
1180  return tx_ptr;
1181 }
1182 
1183 /** \internal
1184  * \brief inspect a rule against a transaction
1185  *
1186  * Inspect a rule. New detection or continued stateful
1187  * detection.
1188  *
1189  * \param stored_flags pointer to stored flags or NULL.
1190  * If stored_flags is set it means we're continuing
1191  * inspection from an earlier run.
1192  *
1193  * \retval bool true sig matched, false didn't match
1194  */
1195 static bool DetectRunTxInspectRule(ThreadVars *tv,
1197  DetectEngineThreadCtx *det_ctx,
1198  Packet *p,
1199  Flow *f,
1200  const uint8_t in_flow_flags, // direction, EOF, etc
1201  void *alstate,
1202  DetectTransaction *tx,
1203  const Signature *s,
1204  uint32_t *stored_flags,
1205  RuleMatchCandidateTx *can,
1206  DetectRunScratchpad *scratch)
1207 {
1208  const uint8_t flow_flags = in_flow_flags;
1209  const int direction = (flow_flags & STREAM_TOSERVER) ? 0 : 1;
1210  uint32_t inspect_flags = stored_flags ? *stored_flags : 0;
1211  int total_matches = 0;
1212  uint16_t file_no_match = 0;
1213  bool retval = false;
1214  bool mpm_before_progress = false; // is mpm engine before progress?
1215  bool mpm_in_progress = false; // is mpm engine in a buffer we will revisit?
1216 
1217  TRACE_SID_TXS(s->id, tx, "starting %s", direction ? "toclient" : "toserver");
1218 
1219  /* for a new inspection we inspect pkt header and packet matches */
1220  if (likely(stored_flags == NULL)) {
1221  TRACE_SID_TXS(s->id, tx, "first inspect, run packet matches");
1222  if (DetectRunInspectRuleHeader(p, f, s, s->flags) == false) {
1223  TRACE_SID_TXS(s->id, tx, "DetectRunInspectRuleHeader() no match");
1224  return false;
1225  }
1226  if (!DetectEnginePktInspectionRun(tv, det_ctx, s, f, p, NULL)) {
1227  TRACE_SID_TXS(s->id, tx, "DetectEnginePktInspectionRun no match");
1228  return false;
1229  }
1230  /* stream mpm and negated mpm sigs can end up here with wrong proto */
1231  if (!(AppProtoEquals(s->alproto, f->alproto) || s->alproto == ALPROTO_UNKNOWN)) {
1232  TRACE_SID_TXS(s->id, tx, "alproto mismatch");
1233  return false;
1234  }
1235  }
1236 
1237  const DetectEngineAppInspectionEngine *engine = s->app_inspect;
1238  do {
1239  TRACE_SID_TXS(s->id, tx, "engine %p inspect_flags %x", engine, inspect_flags);
1240  // also if it is not the same direction, but
1241  // this is a transactional signature, and we are toclient
1242  if (!(inspect_flags & BIT_U32(engine->id)) &&
1243  (direction == engine->dir || ((s->flags & SIG_FLAG_TXBOTHDIR) && direction == 1))) {
1244 
1245  void *tx_ptr = DetectGetInnerTx(tx->tx_ptr, f->alproto, engine->alproto, flow_flags);
1246  if (tx_ptr == NULL) {
1247  if (engine->alproto != ALPROTO_UNKNOWN) {
1248  /* special case: file_data on 'alert tcp' will have engines
1249  * in the list that are not for us. */
1250  engine = engine->next;
1251  continue;
1252  } else {
1253  tx_ptr = tx->tx_ptr;
1254  }
1255  }
1256 
1257  /* engines are sorted per progress, except that the one with
1258  * mpm/prefilter enabled is first */
1259  if (tx->tx_progress < engine->progress) {
1260  SCLogDebug("tx progress %d < engine progress %d",
1261  tx->tx_progress, engine->progress);
1262  break;
1263  }
1264  if (engine->mpm) {
1265  if (tx->tx_progress > engine->progress) {
1266  TRACE_SID_TXS(s->id, tx,
1267  "engine->mpm: t->tx_progress %u > engine->progress %u, so set "
1268  "mpm_before_progress",
1269  tx->tx_progress, engine->progress);
1270  mpm_before_progress = true;
1271  } else if (tx->tx_progress == engine->progress) {
1272  TRACE_SID_TXS(s->id, tx,
1273  "engine->mpm: t->tx_progress %u == engine->progress %u, so set "
1274  "mpm_in_progress",
1275  tx->tx_progress, engine->progress);
1276  mpm_in_progress = true;
1277  }
1278  }
1279 
1280  uint8_t engine_flags = flow_flags;
1281  if (direction != engine->dir) {
1282  engine_flags = flow_flags ^ (STREAM_TOCLIENT | STREAM_TOSERVER);
1283  }
1284  /* run callback: but bypass stream callback if we can */
1285  uint8_t match;
1286  if (unlikely(engine->stream && can->stream_stored)) {
1287  match = can->stream_result;
1288  TRACE_SID_TXS(s->id, tx, "stream skipped, stored result %d used instead", match);
1289  } else if (engine->v2.Callback == NULL) {
1290  /* TODO is this the cleanest way to support a non-app sig on a app hook? */
1291 
1292  if (tx->tx_progress > engine->progress) {
1293  mpm_before_progress = true; // TODO needs a new name now
1294  }
1295 
1296  /* we don't have to store a "hook" match, also don't want to keep any state to make
1297  * sure the hook gets invoked again until tx progress progresses. */
1298  if (tx->tx_progress <= engine->progress)
1300 
1301  /* if progress > engine progress, track state to avoid additional matches */
1303  } else {
1304  KEYWORD_PROFILING_SET_LIST(det_ctx, engine->sm_list);
1305  DEBUG_VALIDATE_BUG_ON(engine->v2.Callback == NULL);
1306  match = engine->v2.Callback(
1307  de_ctx, det_ctx, engine, s, f, engine_flags, alstate, tx_ptr, tx->tx_id);
1308  TRACE_SID_TXS(s->id, tx, "engine %p match %d", engine, match);
1309  if (engine->stream) {
1310  can->stream_stored = true;
1311  can->stream_result = match;
1312  TRACE_SID_TXS(s->id, tx, "stream ran, store result %d for next tx (if any)", match);
1313  }
1314  }
1315  if (match == DETECT_ENGINE_INSPECT_SIG_MATCH) {
1316  inspect_flags |= BIT_U32(engine->id);
1317  engine = engine->next;
1318  total_matches++;
1319  continue;
1320  } else if (match == DETECT_ENGINE_INSPECT_SIG_MATCH_MORE_FILES) {
1321  /* if the file engine matched, but indicated more
1322  * files are still in progress, we don't set inspect
1323  * flags as these would end inspection for this tx */
1324  engine = engine->next;
1325  total_matches++;
1326  continue;
1327  } else if (match == DETECT_ENGINE_INSPECT_SIG_CANT_MATCH) {
1328  inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
1329  inspect_flags |= BIT_U32(engine->id);
1330  } else if (match == DETECT_ENGINE_INSPECT_SIG_CANT_MATCH_FILES) {
1331  inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
1332  inspect_flags |= BIT_U32(engine->id);
1333  file_no_match = 1;
1334  }
1335  /* implied DETECT_ENGINE_INSPECT_SIG_NO_MATCH */
1336  if (engine->mpm && mpm_before_progress) {
1337  inspect_flags |= DE_STATE_FLAG_SIG_CANT_MATCH;
1338  inspect_flags |= BIT_U32(engine->id);
1339  }
1340  break;
1341  } else if (!(inspect_flags & BIT_U32(engine->id)) && s->flags & SIG_FLAG_TXBOTHDIR &&
1342  direction != engine->dir) {
1343  // for transactional rules, the engines on the opposite direction
1344  // are ordered by progress on the different side
1345  // so we have a two mixed-up lists, and we skip the elements
1346  if (direction == 0 && engine->next == NULL) {
1347  // do not match yet on request only
1348  break;
1349  }
1350  engine = engine->next;
1351  continue;
1352  }
1353 
1354  engine = engine->next;
1355  } while (engine != NULL);
1356  TRACE_SID_TXS(s->id, tx, "inspect_flags %x, total_matches %u, engine %p",
1357  inspect_flags, total_matches, engine);
1358 
1359  if (engine == NULL && total_matches) {
1360  inspect_flags |= DE_STATE_FLAG_FULL_INSPECT;
1361  TRACE_SID_TXS(s->id, tx, "MATCH");
1362  retval = true;
1363  }
1364 
1365  if (stored_flags) {
1366  *stored_flags = inspect_flags;
1367  TRACE_SID_TXS(s->id, tx, "continue inspect flags %08x", inspect_flags);
1368  } else {
1369  // store... or? If tx is done we might not want to come back to this tx
1370 
1371  // also... if mpmid tracking is enabled, we won't do a sig again for this tx...
1372  TRACE_SID_TXS(s->id, tx, "start inspect flags %08x", inspect_flags);
1373  if (inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH) {
1374  if (file_no_match) {
1375  /* if we have a mismatch on a file sig, we need to keep state.
1376  * We may get another file on the same tx (for http and smtp
1377  * at least), so for a new file we need to re-eval the sig.
1378  * Thoughts / TODO:
1379  * - not for some protos that have 1 file per tx (e.g. nfs)
1380  * - maybe we only need this for file sigs that mix with
1381  * other matches? E.g. 'POST + filename', is different than
1382  * just 'filename'.
1383  */
1384  DetectRunStoreStateTx(scratch->sgh, f, tx->tx_ptr, tx->tx_id, s,
1385  inspect_flags, flow_flags, file_no_match);
1386  }
1387  } else if ((inspect_flags & DE_STATE_FLAG_FULL_INSPECT) && mpm_before_progress) {
1388  TRACE_SID_TXS(s->id, tx, "no need to store match sig, "
1389  "mpm won't trigger for it anymore");
1390 
1391  if (inspect_flags & DE_STATE_FLAG_FILE_INSPECT) {
1392  TRACE_SID_TXS(s->id, tx, "except that for new files, "
1393  "we may have to revisit anyway");
1394  DetectRunStoreStateTx(scratch->sgh, f, tx->tx_ptr, tx->tx_id, s,
1395  inspect_flags, flow_flags, file_no_match);
1396  }
1397  } else if ((inspect_flags & DE_STATE_FLAG_FULL_INSPECT) == 0 && mpm_in_progress) {
1398  TRACE_SID_TXS(s->id, tx, "no need to store no-match sig, "
1399  "mpm will revisit it");
1400  } else if (inspect_flags != 0 || file_no_match != 0) {
1401  TRACE_SID_TXS(s->id, tx, "storing state: flags %08x", inspect_flags);
1402  DetectRunStoreStateTx(scratch->sgh, f, tx->tx_ptr, tx->tx_id, s,
1403  inspect_flags, flow_flags, file_no_match);
1404  }
1405  }
1406 
1407  return retval;
1408 }
1409 
1410 #define NO_TX \
1411  { \
1412  NULL, 0, NULL, NULL, 0, 0, 0, 0, \
1413  }
1414 
1415 /** \internal
1416  * \brief get a DetectTransaction object
1417  * \retval struct filled with relevant info or all nulls/0s
1418  */
1419 static DetectTransaction GetDetectTx(const uint8_t ipproto, const AppProto alproto,
1420  const uint64_t tx_id, void *tx_ptr, const int tx_end_state, const uint8_t flow_flags)
1421 {
1422  AppLayerTxData *txd = AppLayerParserGetTxData(ipproto, alproto, tx_ptr);
1423  const int tx_progress = AppLayerParserGetStateProgress(ipproto, alproto, tx_ptr, flow_flags);
1424  bool updated = (flow_flags & STREAM_TOSERVER) ? txd->updated_ts : txd->updated_tc;
1425  if (!updated && tx_progress < tx_end_state && ((flow_flags & STREAM_EOF) == 0)) {
1426  DetectTransaction no_tx = NO_TX;
1427  return no_tx;
1428  }
1429  const uint8_t inspected_flag =
1430  (flow_flags & STREAM_TOSERVER) ? APP_LAYER_TX_INSPECTED_TS : APP_LAYER_TX_INSPECTED_TC;
1431  if (unlikely(txd->flags & inspected_flag)) {
1432  SCLogDebug("%" PRIu64 " tx already fully inspected for %s. Flags %02x", tx_id,
1433  flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
1434  DetectTransaction no_tx = NO_TX;
1435  return no_tx;
1436  }
1437  const uint8_t skip_flag = (flow_flags & STREAM_TOSERVER) ? APP_LAYER_TX_SKIP_INSPECT_TS
1439  if (unlikely(txd->flags & skip_flag)) {
1440  SCLogDebug("%" PRIu64 " tx should not be inspected in direction %s. Flags %02x", tx_id,
1441  flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", txd->flags);
1442  DetectTransaction no_tx = NO_TX;
1443  return no_tx;
1444  }
1445 
1446  const uint8_t detect_progress =
1447  (flow_flags & STREAM_TOSERVER) ? txd->detect_progress_ts : txd->detect_progress_tc;
1448 
1449  const int dir_int = (flow_flags & STREAM_TOSERVER) ? 0 : 1;
1450  DetectEngineState *tx_de_state = txd->de_state;
1451  DetectEngineStateDirection *tx_dir_state =
1452  tx_de_state ? &tx_de_state->dir_state[dir_int] : NULL;
1453  DetectTransaction tx = {
1454  .tx_ptr = tx_ptr,
1455  .tx_id = tx_id,
1456  .tx_data_ptr = (struct AppLayerTxData *)txd,
1457  .de_state = tx_dir_state,
1458  .detect_progress = detect_progress,
1459  .detect_progress_orig = detect_progress,
1460  .tx_progress = tx_progress,
1461  .tx_end_state = tx_end_state,
1462  };
1463  return tx;
1464 }
1465 
1466 static inline void StoreDetectProgress(
1467  DetectTransaction *tx, const uint8_t flow_flags, const uint8_t progress)
1468 {
1470  if (flow_flags & STREAM_TOSERVER) {
1471  txd->detect_progress_ts = progress;
1472  } else {
1473  txd->detect_progress_tc = progress;
1474  }
1475 }
1476 
1477 // Merge 'state' rules from the regular prefilter
1478 // updates array_idx on the way
1479 static inline void RuleMatchCandidateMergeStateRules(
1480  DetectEngineThreadCtx *det_ctx, uint32_t *array_idx)
1481 {
1482  // Now, we will merge 2 sorted lists :
1483  // the one in det_ctx->tx_candidates
1484  // and the one in det_ctx->match_array
1485  // For match_array, we take only the relevant elements where s->app_inspect != NULL
1486 
1487  // Basically, we iterate at the same time over the 2 lists
1488  // comparing and taking an element from either.
1489 
1490  // Trick is to do so in place in det_ctx->tx_candidates,
1491  // so as to minimize the number of moves in det_ctx->tx_candidates.
1492  // For this, the algorithm traverses the lists in reverse order.
1493  // Otherwise, if the first element of match_array was to be put before
1494  // all tx_candidates, we would need to shift all tx_candidates
1495 
1496  // Retain the number of elements sorted in tx_candidates before merge
1497  uint32_t j = *array_idx;
1498  // First loop only counting the number of elements to add
1499  for (uint32_t i = 0; i < det_ctx->match_array_cnt; i++) {
1500  const Signature *s = det_ctx->match_array[i];
1501  if (s->app_inspect != NULL) {
1502  (*array_idx)++;
1503  }
1504  }
1505  // Future number of elements in tx_candidates after merge
1506  uint32_t k = *array_idx;
1507 
1508  if (k == j) {
1509  // no new element from match_array to merge in tx_candidates
1510  return;
1511  }
1512 
1513  // variable i is for all elements of match_array (even not relevant ones)
1514  // variable j is for elements of tx_candidates before merge
1515  // variable k is for elements of tx_candidates after merge
1516  for (uint32_t i = det_ctx->match_array_cnt; i > 0;) {
1517  const Signature *s = det_ctx->match_array[i - 1];
1518  if (s->app_inspect == NULL) {
1519  // no relevant element, get the next one from match_array
1520  i--;
1521  continue;
1522  }
1523  // we have one element from match_array to merge in tx_candidates
1524  k--;
1525  if (j > 0) {
1526  // j > 0 means there is still at least one element in tx_candidates to merge
1527  const RuleMatchCandidateTx *s0 = &det_ctx->tx_candidates[j - 1];
1528  if (s->iid <= s0->id) {
1529  // get next element from previous tx_candidates
1530  j--;
1531  // take the element from tx_candidates before merge
1532  det_ctx->tx_candidates[k].s = det_ctx->tx_candidates[j].s;
1533  det_ctx->tx_candidates[k].id = det_ctx->tx_candidates[j].id;
1534  det_ctx->tx_candidates[k].flags = det_ctx->tx_candidates[j].flags;
1535  det_ctx->tx_candidates[k].stream_reset = det_ctx->tx_candidates[j].stream_reset;
1536  continue;
1537  }
1538  } // otherwise
1539  // get next element from match_array
1540  i--;
1541  // take the element from match_array
1542  det_ctx->tx_candidates[k].s = s;
1543  det_ctx->tx_candidates[k].id = s->iid;
1544  det_ctx->tx_candidates[k].flags = NULL;
1545  det_ctx->tx_candidates[k].stream_reset = 0;
1546  }
1547  // Even if k > 0 or j > 0, the loop is over. (Note that j == k now)
1548  // The remaining elements in tx_candidates up to k were already sorted
1549  // and come before any other element later in the list
1550 }
1551 
1552 /**
1553  * \internal
1554  * \brief Check and update firewall rules state.
1555  *
1556  * \param skip_fw_hook bool to indicate firewall rules skips
1557  * For state `skip_before_progress` should be skipped.
1558  *
1559  * \param skip_before_progress progress value to skip rules before.
1560  * Only used if `skip_fw_hook` is set.
1561  *
1562  * \param last_for_progress[out] set to true if this is the last rule for a progress value
1563  *
1564  * \param fw_next_progress_missing[out] set to true if the next fw rule does not target the next
1565  * progress value, or there is no fw rule for that value.
1566  *
1567  * \retval 0 no action needed
1568  * \retval 1 rest of rules shouldn't inspected
1569  * \retval -1 skip this rule
1570  */
1571 static int DetectRunTxCheckFirewallPolicy(DetectEngineThreadCtx *det_ctx, Packet *p, Flow *f,
1572  DetectTransaction *tx, const Signature *s, const uint32_t can_idx, const uint32_t can_size,
1573  bool *skip_fw_hook, const uint8_t skip_before_progress, bool *last_for_progress,
1574  bool *fw_next_progress_missing)
1575 {
1576  if (s->flags & SIG_FLAG_FIREWALL) {
1577  /* check if the next sig is on the same progress hook. If not, we need to apply our
1578  * default policy in case the current sig doesn't apply one. If the next sig has a
1579  * progress beyond our progress + 1, it means the next progress has no rules and needs
1580  * the default policy applied. But only after we evaluate the current rule first, as
1581  * that may override it.
1582  * TODO should we do this after dedup below? */
1583 
1584  if (can_idx + 1 < can_size) {
1585  const Signature *next_s = det_ctx->tx_candidates[can_idx + 1].s;
1586  SCLogDebug(
1587  "peek: peeking at sid %u / progress %u", next_s->id, next_s->app_progress_hook);
1588  if (next_s->flags & SIG_FLAG_FIREWALL) {
1589  if (s->app_progress_hook != next_s->app_progress_hook) {
1590  SCLogDebug("peek: next sid progress %u != current progress %u, so current "
1591  "is last for progress",
1592  next_s->app_progress_hook, s->app_progress_hook);
1593  *last_for_progress = true;
1594 
1595  if (next_s->app_progress_hook - s->app_progress_hook > 1) {
1596  SCLogDebug("peek: missing progress, so we'll drop that unless we get a "
1597  "sweeping accept first");
1598  *fw_next_progress_missing = true;
1599  }
1600  }
1601  } else {
1602  SCLogDebug("peek: next sid not a fw rule, so current is last for progress");
1603  *last_for_progress = true;
1604  }
1605  } else {
1606  SCLogDebug("peek: no peek beyond last rule");
1607  if (s->app_progress_hook < tx->tx_progress) {
1608  SCLogDebug("peek: there are no rules to allow the state after this rule");
1609  *fw_next_progress_missing = true;
1610  }
1611  }
1612 
1613  if ((*skip_fw_hook) == true) {
1614  if (s->app_progress_hook <= skip_before_progress) {
1615  return -1;
1616  }
1617  *skip_fw_hook = false;
1618  }
1619  } else {
1620  /* fw mode, we skip anything after the fw rules if:
1621  * - flow pass is set
1622  * - packet pass (e.g. exception policy) */
1623  if (p->flags & PKT_NOPACKET_INSPECTION || (f->flags & (FLOW_ACTION_PASS))) {
1624  SCLogDebug("skipping firewall rule %u", s->id);
1625  return 1;
1626  }
1627  }
1628  return 0;
1629 }
1630 
1631 // TODO move into det_ctx?
1633 static inline void DetectRunAppendDefaultAccept(DetectEngineThreadCtx *det_ctx, Packet *p)
1634 {
1635  if (EngineModeIsFirewall()) {
1636  memset(&default_accept, 0, sizeof(default_accept));
1639  default_accept.iid = UINT32_MAX;
1643  }
1644 }
1645 
1646 /** \internal
1647  * \brief see if the accept rule needs to apply to the packet
1648  */
1649 static inline bool ApplyAcceptToPacket(
1650  const uint64_t total_txs, const DetectTransaction *tx, const Signature *s)
1651 {
1652  if ((s->flags & SIG_FLAG_FIREWALL) == 0) {
1653  return false;
1654  }
1655  if ((s->action & ACTION_ACCEPT) == 0) {
1656  return false;
1657  }
1658 
1659  /* for accept:tx we need:
1660  * - packet will only be accepted if this is set on the last tx
1661  */
1662  if (s->action_scope == ACTION_SCOPE_TX) {
1663  if (total_txs == tx->tx_id + 1) {
1664  return true;
1665  }
1666  }
1667  /* for accept:hook we need a bit more checking:
1668  * - packet will only be accepted if this is set on the last tx
1669  * - the hook accepted should be the last progress available. */
1670  if (s->action_scope == ACTION_SCOPE_HOOK) {
1671  if ((total_txs == tx->tx_id + 1) && /* last tx */
1672  (s->app_progress_hook == tx->tx_progress)) {
1673  return true;
1674  }
1675  }
1676  return false;
1677 }
1678 
1679 /** \internal
1680  * \retval bool true: break_out_of_app_filter, false: don't break out */
1681 static bool ApplyAccept(Packet *p, const uint8_t flow_flags, const Signature *s,
1682  DetectTransaction *tx, const int tx_end_state, const bool fw_next_progress_missing,
1683  bool *tx_fw_verdict, bool *skip_fw_hook, uint8_t *skip_before_progress)
1684 {
1685  *tx_fw_verdict = true;
1686 
1687  const enum ActionScope as = s->action_scope;
1688  /* accept:hook: jump to first rule of next state.
1689  * Implemented as skip until the first rule of next state. */
1690  if (as == ACTION_SCOPE_HOOK) {
1691  *skip_fw_hook = true;
1692  *skip_before_progress = s->app_progress_hook;
1693 
1694  /* if there is no fw rule for the next progress value,
1695  * we invoke the default drop policy. */
1696  if (fw_next_progress_missing) {
1697  SCLogDebug("%" PRIu64 ": %s default drop for progress", PcapPacketCntGet(p),
1698  flow_flags & STREAM_TOSERVER ? "toserver" : "toclient");
1700  p->flow->flags |= FLOW_ACTION_DROP;
1701  return true;
1702  }
1703  return false;
1704  } else if (as == ACTION_SCOPE_TX) {
1706  *skip_fw_hook = true;
1707  *skip_before_progress = (uint8_t)tx_end_state + 1; // skip all hooks
1708  SCLogDebug(
1709  "accept:tx applied, skip_fw_hook, skip_before_progress %u", *skip_before_progress);
1710  return false;
1711  } else if (as == ACTION_SCOPE_PACKET) {
1712  return true;
1713  } else if (as == ACTION_SCOPE_FLOW) {
1714  return true;
1715  }
1716  return false;
1717 }
1718 
1719 static void DetectRunTx(ThreadVars *tv,
1721  DetectEngineThreadCtx *det_ctx,
1722  Packet *p,
1723  Flow *f,
1724  DetectRunScratchpad *scratch)
1725 {
1726  const uint8_t flow_flags = scratch->flow_flags;
1727  const SigGroupHead * const sgh = scratch->sgh;
1728  void * const alstate = f->alstate;
1729  const uint8_t ipproto = f->proto;
1730  const AppProto alproto = f->alproto;
1731 
1732  const uint64_t total_txs = AppLayerParserGetTxCnt(f, alstate);
1733  uint64_t tx_id_min = AppLayerParserGetTransactionInspectId(f->alparser, flow_flags);
1734  const int tx_end_state = AppLayerParserGetStateProgressCompletionStatus(alproto, flow_flags);
1735 
1736  AppLayerGetTxIteratorFunc IterFunc = AppLayerGetTxIterator(ipproto, alproto);
1737  AppLayerGetTxIterState state = { 0 };
1738 
1739  uint32_t fw_verdicted = 0;
1740  uint32_t tx_inspected = 0;
1741  const bool have_fw_rules = EngineModeIsFirewall();
1742 
1743  SCLogDebug("packet %" PRIu64, PcapPacketCntGet(p));
1744 
1745  while (1) {
1746  AppLayerGetTxIterTuple ires = IterFunc(ipproto, alproto, alstate, tx_id_min, total_txs, &state);
1747  if (ires.tx_ptr == NULL)
1748  break;
1749 
1750  DetectTransaction tx =
1751  GetDetectTx(ipproto, alproto, ires.tx_id, ires.tx_ptr, tx_end_state, flow_flags);
1752  if (tx.tx_ptr == NULL) {
1753  SCLogDebug("%p/%"PRIu64" no transaction to inspect",
1754  tx.tx_ptr, tx_id_min);
1755 
1756  tx_id_min++; // next (if any) run look for +1
1757  goto next;
1758  }
1759  tx_id_min = tx.tx_id + 1; // next look for cur + 1
1760  tx_inspected++;
1761 
1762  SCLogDebug("%p/%" PRIu64 " txd flags %02x", tx.tx_ptr, tx_id_min, tx.tx_data_ptr->flags);
1763 
1764  det_ctx->tx_id = tx.tx_id;
1765  det_ctx->tx_id_set = true;
1766  det_ctx->p = p;
1767 
1768  bool do_sort = false; // do we need to sort the tx candidate list?
1769  uint32_t array_idx = 0;
1770  uint32_t total_rules = det_ctx->match_array_cnt;
1771  total_rules += (tx.de_state ? tx.de_state->cnt : 0);
1772 
1773  /* run prefilter engines and merge results into a candidates array */
1774  if (sgh->tx_engines) {
1776  DetectRunPrefilterTx(det_ctx, sgh, p, ipproto, flow_flags, alproto,
1777  alstate, &tx);
1779  SCLogDebug("%p/%"PRIu64" rules added from prefilter: %u candidates",
1780  tx.tx_ptr, tx.tx_id, det_ctx->pmq.rule_id_array_cnt);
1781 
1782  total_rules += det_ctx->pmq.rule_id_array_cnt;
1783  if (!(RuleMatchCandidateTxArrayHasSpace(det_ctx, total_rules))) {
1784  RuleMatchCandidateTxArrayExpand(det_ctx, total_rules);
1785  }
1786 
1787  for (uint32_t i = 0; i < det_ctx->pmq.rule_id_array_cnt; i++) {
1788  const Signature *s = de_ctx->sig_array[det_ctx->pmq.rule_id_array[i]];
1789  const SigIntId id = s->iid;
1790  det_ctx->tx_candidates[array_idx].s = s;
1791  det_ctx->tx_candidates[array_idx].id = id;
1792  det_ctx->tx_candidates[array_idx].flags = NULL;
1793  det_ctx->tx_candidates[array_idx].stream_reset = 0;
1794  array_idx++;
1795  }
1796  PMQ_RESET(&det_ctx->pmq);
1797  } else {
1798  if (!(RuleMatchCandidateTxArrayHasSpace(det_ctx, total_rules))) {
1799  RuleMatchCandidateTxArrayExpand(det_ctx, total_rules);
1800  }
1801  }
1802 
1803  /* merge 'state' rules from the regular prefilter */
1804 #ifdef PROFILING
1805  uint32_t x = array_idx;
1806 #endif
1807  RuleMatchCandidateMergeStateRules(det_ctx, &array_idx);
1808 
1809  /* merge stored state into results */
1810  if (tx.de_state != NULL) {
1811  const uint32_t old = array_idx;
1812 
1813  /* if tx.de_state->flags has 'new file' set and sig below has
1814  * 'file inspected' flag, reset the file part of the state */
1815  const bool have_new_file = (tx.de_state->flags & DETECT_ENGINE_STATE_FLAG_FILE_NEW);
1816  if (have_new_file) {
1817  SCLogDebug("%p/%"PRIu64" destate: need to consider new file",
1818  tx.tx_ptr, tx.tx_id);
1820  }
1821 
1822  SigIntId state_cnt = 0;
1823  DeStateStore *tx_store = tx.de_state->head;
1824  for (; tx_store != NULL; tx_store = tx_store->next) {
1825  SCLogDebug("tx_store %p", tx_store);
1826 
1827  SigIntId store_cnt = 0;
1828  for (store_cnt = 0;
1829  store_cnt < DE_STATE_CHUNK_SIZE && state_cnt < tx.de_state->cnt;
1830  store_cnt++, state_cnt++)
1831  {
1832  DeStateStoreItem *item = &tx_store->store[store_cnt];
1833  SCLogDebug("rule id %u, inspect_flags %u", item->sid, item->flags);
1834  if (have_new_file && (item->flags & DE_STATE_FLAG_FILE_INSPECT)) {
1835  /* remove part of the state. File inspect engine will now
1836  * be able to run again */
1838  SCLogDebug("rule id %u, post file reset inspect_flags %u", item->sid, item->flags);
1839  }
1840  det_ctx->tx_candidates[array_idx].s = de_ctx->sig_array[item->sid];
1841  det_ctx->tx_candidates[array_idx].id = item->sid;
1842  det_ctx->tx_candidates[array_idx].flags = &item->flags;
1843  det_ctx->tx_candidates[array_idx].stream_reset = 0;
1844  array_idx++;
1845  }
1846  }
1847  do_sort |= (old && old != array_idx); // sort if continue list adds sids
1848  SCLogDebug("%p/%" PRIu64 " rules added from 'continue' list: %u", tx.tx_ptr, tx.tx_id,
1849  array_idx - old);
1850  }
1851  if (do_sort) {
1852  qsort(det_ctx->tx_candidates, array_idx, sizeof(RuleMatchCandidateTx),
1853  DetectRunTxSortHelper);
1854  }
1855 
1856 #ifdef PROFILING
1857  if (array_idx >= de_ctx->profile_match_logging_threshold)
1858  RulesDumpTxMatchArray(det_ctx, scratch->sgh, p, tx.tx_id, array_idx, x);
1859 #endif
1860 
1861 #ifdef DEBUG
1862  for (uint32_t i = 0; i < array_idx; i++) {
1863  RuleMatchCandidateTx *can = &det_ctx->tx_candidates[i];
1864  const Signature *s = det_ctx->tx_candidates[i].s;
1865  SCLogDebug("%u: sid %u flags %p", i, s->id, can->flags);
1866  }
1867 #endif
1868  bool skip_fw_hook = false;
1869  uint8_t skip_before_progress = 0;
1870  bool fw_next_progress_missing = false;
1871 
1872  /* if there are no rules / rule candidates, make sure we don't
1873  * invoke the default drop */
1874  if (have_fw_rules && array_idx == 0 && (tx.tx_data_ptr->flags & APP_LAYER_TX_ACCEPT)) {
1875  fw_verdicted++;
1876 
1877  /* current tx is the last we have, append a blank accept:packet */
1878  if (total_txs == tx.tx_id + 1) {
1879  DetectRunAppendDefaultAccept(det_ctx, p);
1880  return;
1881  }
1882  goto next;
1883  }
1884 
1885  bool tx_fw_verdict = false;
1886  /* run rules: inspect the match candidates */
1887  for (uint32_t i = 0; i < array_idx; i++) {
1888  RuleMatchCandidateTx *can = &det_ctx->tx_candidates[i];
1889  const Signature *s = det_ctx->tx_candidates[i].s;
1890  uint32_t *inspect_flags = det_ctx->tx_candidates[i].flags;
1891  bool break_out_of_app_filter = false;
1892 
1893  SCLogDebug("%" PRIu64 ": sid:%u: %s tx %u/%u/%u sig %u", PcapPacketCntGet(p), s->id,
1894  flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", tx.tx_progress,
1896 
1897  /* deduplicate: rules_array is sorted, but not deduplicated:
1898  * both mpm and stored state could give us the same sid.
1899  * As they are back to back in that case we can check for it
1900  * here. We select the stored state one as that comes first
1901  * in the array. */
1902  while ((i + 1) < array_idx &&
1903  det_ctx->tx_candidates[i].s == det_ctx->tx_candidates[i + 1].s) {
1904  SCLogDebug("%p/%" PRIu64 " inspecting SKIP NEXT: sid %u (%u), flags %08x",
1905  tx.tx_ptr, tx.tx_id, s->id, s->iid, inspect_flags ? *inspect_flags : 0);
1906  i++;
1907  }
1908 
1909  /* skip fw rules if we're in accept:tx mode */
1910  if (have_fw_rules && (tx.tx_data_ptr->flags & APP_LAYER_TX_ACCEPT)) {
1911  /* append a blank accept:packet action for the APP_LAYER_TX_ACCEPT,
1912  * if this is the last tx */
1913  if (!tx_fw_verdict) {
1914  const bool accept_tx_applies_to_packet = total_txs == tx.tx_id + 1;
1915  if (accept_tx_applies_to_packet) {
1916  SCLogDebug("accept:(tx|hook): should be applied to the packet");
1917  DetectRunAppendDefaultAccept(det_ctx, p);
1918  }
1919  }
1920  tx_fw_verdict = true;
1921 
1922  if (s->flags & SIG_FLAG_FIREWALL) {
1923  SCLogDebug("APP_LAYER_TX_ACCEPT, so skip rule");
1924  continue;
1925  }
1926 
1927  /* threat detect rules will be inspected */
1928  }
1929 
1930  SCLogDebug("%p/%" PRIu64 " inspecting: sid %u (%u), flags %08x", tx.tx_ptr, tx.tx_id,
1931  s->id, s->iid, inspect_flags ? *inspect_flags : 0);
1932 
1933  if (inspect_flags) {
1934  if (*inspect_flags & DE_STATE_FLAG_FULL_INSPECT) {
1935  SCLogDebug("%p/%" PRIu64
1936  " inspecting: sid %u (%u), flags %08x DE_STATE_FLAG_FULL_INSPECT",
1937  tx.tx_ptr, tx.tx_id, s->id, s->iid, *inspect_flags);
1938 
1939  /* if we're still in the same progress state as an earlier full
1940  * match, we need to apply the same accept */
1941  if (have_fw_rules && (s->flags & SIG_FLAG_FIREWALL) &&
1942  (s->action & ACTION_ACCEPT) && s->app_progress_hook == tx.tx_progress) {
1943  const bool fw_accept_to_packet = ApplyAcceptToPacket(total_txs, &tx, s);
1944  break_out_of_app_filter = ApplyAccept(p, flow_flags, s, &tx, tx_end_state,
1945  fw_next_progress_missing, &tx_fw_verdict, &skip_fw_hook,
1946  &skip_before_progress);
1947  if (fw_accept_to_packet)
1948  DetectRunAppendDefaultAccept(det_ctx, p);
1949  if (break_out_of_app_filter)
1950  break;
1951  }
1952  continue;
1953  }
1954  if (*inspect_flags & DE_STATE_FLAG_SIG_CANT_MATCH) {
1955  SCLogDebug("%p/%" PRIu64
1956  " inspecting: sid %u (%u), flags %08x DE_STATE_FLAG_SIG_CANT_MATCH",
1957  tx.tx_ptr, tx.tx_id, s->id, s->iid, *inspect_flags);
1958  continue;
1959  }
1960  }
1961 
1962  if (inspect_flags) {
1963  /* continue previous inspection */
1964  SCLogDebug("%p/%" PRIu64 " Continuing sid %u", tx.tx_ptr, tx.tx_id, s->id);
1965  } else {
1966  /* start new inspection */
1967  SCLogDebug("%p/%"PRIu64" Start sid %u", tx.tx_ptr, tx.tx_id, s->id);
1968  }
1969 
1970  bool last_for_progress = false;
1971  if (have_fw_rules) {
1972  int fw_r = DetectRunTxCheckFirewallPolicy(det_ctx, p, f, &tx, s, i, array_idx,
1973  &skip_fw_hook, skip_before_progress, &last_for_progress,
1974  &fw_next_progress_missing);
1975  if (fw_r == -1)
1976  continue;
1977  if (fw_r == 1)
1978  break;
1979  }
1980 
1981  /* call individual rule inspection */
1983  const int r = DetectRunTxInspectRule(tv, de_ctx, det_ctx, p, f, flow_flags,
1984  alstate, &tx, s, inspect_flags, can, scratch);
1985  if (r == 1) {
1986  /* match */
1987  DetectRunPostMatch(tv, det_ctx, p, s);
1988 
1989  /* see if we need to apply tx/hook accept to the packet. This can be needed when
1990  * we've completed the inspection so far for an incomplete tx, and an accept:tx or
1991  * accept:hook is the last match.*/
1992  const bool fw_accept_to_packet = ApplyAcceptToPacket(total_txs, &tx, s);
1993 
1994  uint8_t alert_flags = (PACKET_ALERT_FLAG_STATE_MATCH | PACKET_ALERT_FLAG_TX);
1995  if (fw_accept_to_packet) {
1996  SCLogDebug("accept:(tx|hook): should be applied to the packet");
1998  }
1999 
2000  SCLogDebug(
2001  "%p/%" PRIu64 " sig %u (%u) matched", tx.tx_ptr, tx.tx_id, s->id, s->iid);
2002  AlertQueueAppend(det_ctx, s, p, tx.tx_id, alert_flags);
2003 
2004  if ((s->flags & SIG_FLAG_FIREWALL) && (s->action & ACTION_ACCEPT)) {
2005  break_out_of_app_filter = ApplyAccept(p, flow_flags, s, &tx, tx_end_state,
2006  fw_next_progress_missing, &tx_fw_verdict, &skip_fw_hook,
2007  &skip_before_progress);
2008  }
2009  } else if (last_for_progress) {
2010  SCLogDebug("sid %u: not a match: %s rule, last_for_progress %s", s->id,
2011  (s->flags & SIG_FLAG_FIREWALL) ? "firewall" : "regular",
2012  BOOL2STR(last_for_progress));
2013  if (s->flags & SIG_FLAG_FIREWALL) {
2014  SCLogDebug("%" PRIu64 ": %s default drop for progress", PcapPacketCntGet(p),
2015  flow_flags & STREAM_TOSERVER ? "toserver" : "toclient");
2016  /* if this rule was the last for our progress state, and it didn't match,
2017  * we have to invoke the default drop policy. */
2019  p->flow->flags |= FLOW_ACTION_DROP;
2020  break_out_of_app_filter = true;
2021  tx_fw_verdict = true;
2022  }
2023  }
2024  DetectVarProcessList(det_ctx, p->flow, p);
2025  RULE_PROFILING_END(det_ctx, s, r, p);
2026 
2027  if (det_ctx->post_rule_work_queue.len > 0) {
2028  SCLogDebug("%p/%" PRIu64 " post_rule_work_queue len %u", tx.tx_ptr, tx.tx_id,
2029  det_ctx->post_rule_work_queue.len);
2030  /* run post match prefilter engines on work queue */
2031  PrefilterPostRuleMatch(det_ctx, scratch->sgh, p, f);
2032 
2033  uint32_t prev_array_idx = array_idx;
2034  for (uint32_t j = 0; j < det_ctx->pmq.rule_id_array_cnt; j++) {
2035  const Signature *ts = de_ctx->sig_array[det_ctx->pmq.rule_id_array[j]];
2036  if (ts->app_inspect != NULL) {
2037  const SigIntId id = ts->iid;
2038  det_ctx->tx_candidates[array_idx].s = ts;
2039  det_ctx->tx_candidates[array_idx].id = id;
2040  det_ctx->tx_candidates[array_idx].flags = NULL;
2041  det_ctx->tx_candidates[array_idx].stream_reset = 0;
2042  array_idx++;
2043 
2044  SCLogDebug("%p/%" PRIu64 " rule %u (%u) added from 'post match' prefilter",
2045  tx.tx_ptr, tx.tx_id, ts->id, id);
2046  }
2047  }
2048  SCLogDebug("%p/%" PRIu64 " rules added from 'post match' prefilter: %u", tx.tx_ptr,
2049  tx.tx_id, array_idx - prev_array_idx);
2050  if (prev_array_idx != array_idx) {
2051  /* sort, but only part of array we're still going to process */
2052  qsort(det_ctx->tx_candidates + i, array_idx - i, sizeof(RuleMatchCandidateTx),
2053  DetectRunTxSortHelper);
2054  }
2055  det_ctx->post_rule_work_queue.len = 0;
2056  PMQ_RESET(&det_ctx->pmq);
2057  }
2058 
2059  if (break_out_of_app_filter)
2060  break;
2061  }
2062  if (tx_fw_verdict)
2063  fw_verdicted++;
2064 
2065  det_ctx->tx_id = 0;
2066  det_ctx->tx_id_set = false;
2067  det_ctx->p = NULL;
2068 
2069  /* see if we have any updated state to store in the tx */
2070 
2071  /* this side of the tx is done */
2072  if (tx.tx_progress >= tx.tx_end_state) {
2073  SCLogDebug("%" PRIu64 ": %s tx done", PcapPacketCntGet(p),
2074  flow_flags & STREAM_TOSERVER ? "toserver" : "toclient");
2075  const uint8_t inspected_flag = (flow_flags & STREAM_TOSERVER)
2078  tx.tx_data_ptr->flags |= inspected_flag;
2079  SCLogDebug("%p/%" PRIu64 " tx is done for direction %s. Progress %02x", tx.tx_ptr,
2080  tx.tx_id, flow_flags & STREAM_TOSERVER ? "toserver" : "toclient",
2081  tx.detect_progress);
2082  }
2083 
2084  if (tx.detect_progress != tx.detect_progress_orig) {
2085  SCLogDebug("%" PRIu64 ": %s tx state change %u -> %u", PcapPacketCntGet(p),
2086  flow_flags & STREAM_TOSERVER ? "toserver" : "toclient", tx.detect_progress_orig,
2087  tx.detect_progress);
2088  SCLogDebug("%p/%" PRIu64 " Storing new progress %02x (was %02x)", tx.tx_ptr, tx.tx_id,
2090 
2091  StoreDetectProgress(&tx, flow_flags, tx.detect_progress);
2092  }
2093 
2094  InspectionBufferClean(det_ctx);
2095 
2096  next:
2097  if (!ires.has_next)
2098  break;
2099  }
2100 
2101  /* apply default policy if there were txs to inspect, we have fw rules and non of the rules
2102  * applied a policy. */
2103  SCLogDebug("packet %" PRIu64 ": tx_inspected %u fw_verdicted %u", PcapPacketCntGet(p),
2104  tx_inspected, fw_verdicted);
2105  if (tx_inspected && have_fw_rules && tx_inspected != fw_verdicted) {
2106  SCLogDebug("%" PRIu64 ": %s default drop", PcapPacketCntGet(p),
2107  flow_flags & STREAM_TOSERVER ? "toserver" : "toclient");
2109  p->flow->flags |= FLOW_ACTION_DROP;
2110  return;
2111  }
2112  /* if all tables have been bypassed, we accept:packet */
2113  if (tx_inspected == 0 && fw_verdicted == 0 && have_fw_rules) {
2114  DetectRunAppendDefaultAccept(det_ctx, p);
2115  }
2116 }
2117 
2118 static void DetectRunFrames(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx,
2119  Packet *p, Flow *f, DetectRunScratchpad *scratch)
2120 {
2121  const SigGroupHead *const sgh = scratch->sgh;
2122  const AppProto alproto = f->alproto;
2123 
2124  /* for TCP, limit inspection to pseudo packets or real packet that did
2125  * an app-layer update. */
2126  if (p->proto == IPPROTO_TCP && !PKT_IS_PSEUDOPKT(p) &&
2127  ((PKT_IS_TOSERVER(p) && (f->flags & FLOW_TS_APP_UPDATED) == 0) ||
2128  (PKT_IS_TOCLIENT(p) && (f->flags & FLOW_TC_APP_UPDATED) == 0))) {
2129  SCLogDebug("pcap_cnt %" PRIu64 ": %s: skip frame inspection for TCP w/o APP UPDATE",
2130  PcapPacketCntGet(p), PKT_IS_TOSERVER(p) ? "toserver" : "toclient");
2131  return;
2132  }
2133  FramesContainer *frames_container = AppLayerFramesGetContainer(f);
2134  if (frames_container == NULL) {
2135  return;
2136  }
2137  Frames *frames;
2138  if (PKT_IS_TOSERVER(p)) {
2139  frames = &frames_container->toserver;
2140  } else {
2141  frames = &frames_container->toclient;
2142  }
2143 
2144  for (uint32_t idx = 0; idx < frames->cnt; idx++) {
2145  SCLogDebug("frame %u", idx);
2146  Frame *frame = FrameGetByIndex(frames, idx);
2147  if (frame == NULL) {
2148  continue;
2149  }
2150 
2151  det_ctx->frame_inspect_progress = 0;
2152  uint32_t array_idx = 0;
2153  uint32_t total_rules = det_ctx->match_array_cnt;
2154 
2155  /* run prefilter engines and merge results into a candidates array */
2156  if (sgh->frame_engines) {
2157  // PACKET_PROFILING_DETECT_START(p, PROF_DETECT_PF_TX);
2158  DetectRunPrefilterFrame(det_ctx, sgh, p, frames, frame, alproto);
2159  // PACKET_PROFILING_DETECT_END(p, PROF_DETECT_PF_TX);
2160  SCLogDebug("%p/%" PRIi64 " rules added from prefilter: %u candidates", frame, frame->id,
2161  det_ctx->pmq.rule_id_array_cnt);
2162 
2163  total_rules += det_ctx->pmq.rule_id_array_cnt;
2164 
2165  if (!(RuleMatchCandidateTxArrayHasSpace(
2166  det_ctx, total_rules))) { // TODO is it safe to overload?
2167  RuleMatchCandidateTxArrayExpand(det_ctx, total_rules);
2168  }
2169 
2170  for (uint32_t i = 0; i < det_ctx->pmq.rule_id_array_cnt; i++) {
2171  const Signature *s = de_ctx->sig_array[det_ctx->pmq.rule_id_array[i]];
2172  const SigIntId id = s->iid;
2173  det_ctx->tx_candidates[array_idx].s = s;
2174  det_ctx->tx_candidates[array_idx].id = id;
2175  det_ctx->tx_candidates[array_idx].flags = NULL;
2176  det_ctx->tx_candidates[array_idx].stream_reset = 0;
2177  array_idx++;
2178  }
2179  PMQ_RESET(&det_ctx->pmq);
2180  }
2181  /* merge 'state' rules from the regular prefilter */
2182  uint32_t x = array_idx;
2183  for (uint32_t i = 0; i < det_ctx->match_array_cnt; i++) {
2184  const Signature *s = det_ctx->match_array[i];
2185  if (s->frame_inspect != NULL) {
2186  const SigIntId id = s->iid;
2187  det_ctx->tx_candidates[array_idx].s = s;
2188  det_ctx->tx_candidates[array_idx].id = id;
2189  det_ctx->tx_candidates[array_idx].flags = NULL;
2190  det_ctx->tx_candidates[array_idx].stream_reset = 0;
2191  array_idx++;
2192 
2193  SCLogDebug("%p/%" PRIi64 " rule %u (%u) added from 'match' list", frame, frame->id,
2194  s->id, id);
2195  }
2196  }
2197  SCLogDebug("%p/%" PRIi64 " rules added from 'match' list: %u", frame, frame->id,
2198  array_idx - x);
2199  (void)x;
2200 
2201  /* run rules: inspect the match candidates */
2202  for (uint32_t i = 0; i < array_idx; i++) {
2203  const Signature *s = det_ctx->tx_candidates[i].s;
2204 
2205  /* deduplicate: rules_array is sorted, but not deduplicated.
2206  * As they are back to back in that case we can check for it
2207  * here. We select the stored state one as that comes first
2208  * in the array. */
2209  while ((i + 1) < array_idx &&
2210  det_ctx->tx_candidates[i].s == det_ctx->tx_candidates[i + 1].s) {
2211  i++;
2212  }
2213  SCLogDebug("%p/%" PRIi64 " inspecting: sid %u (%u)", frame, frame->id, s->id, s->iid);
2214 
2215  /* start new inspection */
2216  SCLogDebug("%p/%" PRIi64 " Start sid %u", frame, frame->id, s->id);
2217 
2218  /* call individual rule inspection */
2220  bool r = DetectRunInspectRuleHeader(p, f, s, s->flags);
2221  if (r) {
2222  r = DetectRunFrameInspectRule(tv, det_ctx, s, f, p, frames, frame);
2223  if (r) {
2224  /* match */
2225  DetectRunPostMatch(tv, det_ctx, p, s);
2226 
2227  uint8_t alert_flags = (PACKET_ALERT_FLAG_STATE_MATCH | PACKET_ALERT_FLAG_FRAME);
2228  det_ctx->frame_id = frame->id;
2229  SCLogDebug(
2230  "%p/%" PRIi64 " sig %u (%u) matched", frame, frame->id, s->id, s->iid);
2231  if (frame->flags & FRAME_FLAG_TX_ID_SET) {
2232  alert_flags |= PACKET_ALERT_FLAG_TX;
2233  }
2234  AlertQueueAppend(det_ctx, s, p, frame->tx_id, alert_flags);
2235  }
2236  }
2237  DetectVarProcessList(det_ctx, p->flow, p);
2238  RULE_PROFILING_END(det_ctx, s, r, p);
2239  }
2240 
2241  /* update Frame::inspect_progress here instead of in the code above. The reason is that a
2242  * frame might be used more than once in buffers with transforms. */
2243  if (frame->inspect_progress < det_ctx->frame_inspect_progress) {
2244  frame->inspect_progress = det_ctx->frame_inspect_progress;
2245  SCLogDebug("frame->inspect_progress: %" PRIu64 " -> updated", frame->inspect_progress);
2246  } else {
2247  SCLogDebug(
2248  "frame->inspect_progress: %" PRIu64 " -> not updated", frame->inspect_progress);
2249  }
2250 
2251  SCLogDebug("%p/%" PRIi64 " rules inspected, running cleanup", frame, frame->id);
2252  InspectionBufferClean(det_ctx);
2253  }
2254 }
2255 
2256 static DetectEngineThreadCtx *GetTenantById(HashTable *h, uint32_t id)
2257 {
2258  /* technically we need to pass a DetectEngineThreadCtx struct with the
2259  * tenant_id member. But as that member is the first in the struct, we
2260  * can use the id directly. */
2261  return HashTableLookup(h, &id, 0);
2262 }
2263 
2264 static void DetectFlow(ThreadVars *tv,
2266  Packet *p)
2267 {
2268  Flow *const f = p->flow;
2269 
2270  /* we check the flow drop here, and not the packet drop. This is
2271  * to allow stream engine "invalid" drop packets to still be
2272  * evaluated by the stream event rules. */
2273  if (f->flags & FLOW_ACTION_DROP) {
2275  SCReturn;
2276  }
2277 
2278  /* in firewall mode, we still need to run the fw rulesets even for exception policy pass */
2279  bool skip = false;
2280  if (EngineModeIsFirewall()) {
2281  skip = (f->flags & (FLOW_ACTION_ACCEPT));
2282 
2283  } else {
2284  skip = (p->flags & PKT_NOPACKET_INSPECTION || f->flags & (FLOW_ACTION_PASS));
2285  }
2286  if (skip) {
2287  /* enforce prior accept:flow */
2288  if (f->flags & FLOW_ACTION_ACCEPT) {
2289  p->action |= ACTION_ACCEPT;
2290  }
2291  /* hack: if we are in pass the entire flow mode, we need to still
2292  * update the inspect_id forward. So test for the condition here,
2293  * and call the update code if necessary. */
2294  const int pass = (f->flags & (FLOW_ACTION_PASS | FLOW_ACTION_ACCEPT));
2295  if (pass) {
2296  uint8_t flags = STREAM_FLAGS_FOR_PACKET(p);
2298  if (f->alstate) {
2300  }
2301  }
2302  SCLogDebug("p->pcap %" PRIu64 ": no detection on packet, "
2303  "PKT_NOPACKET_INSPECTION is set",
2304  PcapPacketCntGet(p));
2305  return;
2306  }
2307 
2308  /* see if the packet matches one or more of the sigs */
2309  DetectRun(tv, de_ctx, det_ctx, p);
2310 }
2311 
2312 
2313 static void DetectNoFlow(ThreadVars *tv,
2315  Packet *p)
2316 {
2317  /* No need to perform any detection on this packet, if the given flag is set.*/
2319  return;
2320  }
2321 
2322  /* see if the packet matches one or more of the sigs */
2323  DetectRun(tv, de_ctx, det_ctx, p);
2324 }
2325 
2327 {
2328  const DetectEngineCtx *de_ctx = det_ctx->de_ctx;
2329  const SigGroupHead *sgh = de_ctx->pre_flow_sgh;
2330 
2331  SCLogDebug("thread id: %u, packet %" PRIu64 ", sgh %p", tv->id, PcapPacketCntGet(p), sgh);
2332  DetectRunPacketHook(tv, de_ctx, det_ctx, sgh, p);
2333  return p->action;
2334 }
2335 
2337 {
2338  const DetectEngineCtx *de_ctx = det_ctx->de_ctx;
2339  const int direction = (PKT_IS_TOCLIENT(p) != 0);
2340  const SigGroupHead *sgh = de_ctx->pre_stream_sgh[direction];
2341 
2342  SCLogDebug("thread id: %u, packet %" PRIu64 ", sgh %p", tv->id, PcapPacketCntGet(p), sgh);
2343  DetectRunPacketHook(tv, de_ctx, det_ctx, sgh, p);
2344  return p->action;
2345 }
2346 
2347 /** \brief Detection engine thread wrapper.
2348  * \param tv thread vars
2349  * \param p packet to inspect
2350  * \param data thread specific data
2351  * \param pq packet queue
2352  * \retval TM_ECODE_FAILED error
2353  * \retval TM_ECODE_OK ok
2354  */
2355 TmEcode Detect(ThreadVars *tv, Packet *p, void *data)
2356 {
2358 
2359  DetectEngineCtx *de_ctx = NULL;
2360  DetectEngineThreadCtx *det_ctx = (DetectEngineThreadCtx *)data;
2361  if (det_ctx == NULL) {
2362  printf("ERROR: Detect has no thread ctx\n");
2363  goto error;
2364  }
2365 
2366  if (unlikely(SC_ATOMIC_GET(det_ctx->so_far_used_by_detect) == 0)) {
2367  (void)SC_ATOMIC_SET(det_ctx->so_far_used_by_detect, 1);
2368  SCLogDebug("Detect Engine using new det_ctx - %p",
2369  det_ctx);
2370  }
2371 
2372  /* if in MT mode _and_ we have tenants registered, use
2373  * MT logic. */
2374  if (det_ctx->mt_det_ctxs_cnt > 0 && det_ctx->TenantGetId != NULL)
2375  {
2376  uint32_t tenant_id = p->tenant_id;
2377  if (tenant_id == 0)
2378  tenant_id = det_ctx->TenantGetId(det_ctx, p);
2379  if (tenant_id > 0 && tenant_id < det_ctx->mt_det_ctxs_cnt) {
2380  p->tenant_id = tenant_id;
2381  det_ctx = GetTenantById(det_ctx->mt_det_ctxs_hash, tenant_id);
2382  if (det_ctx == NULL)
2383  return TM_ECODE_OK;
2384  de_ctx = det_ctx->de_ctx;
2385  if (de_ctx == NULL)
2386  return TM_ECODE_OK;
2387 
2388  if (unlikely(SC_ATOMIC_GET(det_ctx->so_far_used_by_detect) == 0)) {
2389  (void)SC_ATOMIC_SET(det_ctx->so_far_used_by_detect, 1);
2390  SCLogDebug("MT de_ctx %p det_ctx %p (tenant %u)", de_ctx, det_ctx, tenant_id);
2391  }
2392  } else {
2393  /* use default if no tenants are registered for this packet */
2394  de_ctx = det_ctx->de_ctx;
2395  }
2396  } else {
2397  de_ctx = det_ctx->de_ctx;
2398  }
2399 
2400  if (p->flow) {
2401  DetectFlow(tv, de_ctx, det_ctx, p);
2402  } else {
2403  DetectNoFlow(tv, de_ctx, det_ctx, p);
2404  }
2405 
2406 #ifdef PROFILE_RULES
2407  /* aggregate statistics */
2408  struct timeval ts;
2409  gettimeofday(&ts, NULL);
2410  if (ts.tv_sec != det_ctx->rule_perf_last_sync) {
2411  SCProfilingRuleThreatAggregate(det_ctx);
2412  det_ctx->rule_perf_last_sync = ts.tv_sec;
2413  }
2414 #endif
2415 
2416  return TM_ECODE_OK;
2417 error:
2418  return TM_ECODE_FAILED;
2419 }
2420 
2421 /** \brief disable file features we don't need
2422  * Called if we have no detection engine.
2423  */
2425 {
2426  DetectPostInspectFileFlagsUpdate(f, NULL /* no sgh */, STREAM_TOSERVER);
2427  DetectPostInspectFileFlagsUpdate(f, NULL /* no sgh */, STREAM_TOCLIENT);
2428 }
2429 
2430 #ifdef UNITTESTS
2431 /**
2432  * \brief wrapper for old tests
2433  */
2436 {
2437  if (p->flow) {
2438  DetectFlow(tv, de_ctx, det_ctx, p);
2439  } else {
2440  DetectNoFlow(tv, de_ctx, det_ctx, p);
2441  }
2442 }
2443 #endif
2444 
2445 /*
2446  * TESTS
2447  */
2448 
2449 #ifdef UNITTESTS
2450 #include "tests/detect.c"
2451 #endif
PKT_IS_TOCLIENT
#define PKT_IS_TOCLIENT(p)
Definition: decode.h:240
default_accept
thread_local Signature default_accept
Definition: detect.c:1632
DetectEngineAppInspectionEngine_::stream
bool stream
Definition: detect.h:421
PacketCheckAction
bool PacketCheckAction(const Packet *p, const uint8_t a)
Definition: packet.c:50
FLOWFILE_NO_MD5_TS
#define FLOWFILE_NO_MD5_TS
Definition: flow.h:136
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:1501
PACKET_ALERT_FLAG_TX_GUESSED
#define PACKET_ALERT_FLAG_TX_GUESSED
Definition: decode.h:279
FLOWFILE_NO_MD5_TC
#define FLOWFILE_NO_MD5_TC
Definition: flow.h:137
SigGroupHead_::tx_engines
PrefilterEngine * tx_engines
Definition: detect.h:1650
DetectEngineAppInspectionEngine_
Definition: detect.h:416
Packet_::proto
uint8_t proto
Definition: decode.h:527
DetectTransaction_::tx_data_ptr
struct AppLayerTxData * tx_data_ptr
Definition: detect-engine-prefilter.h:34
DetectEngineAppInspectionEngine_::mpm
bool mpm
Definition: detect.h:420
DE_STATE_CHUNK_SIZE
#define DE_STATE_CHUNK_SIZE
Definition: detect-engine-state.h:55
RuleMatchCandidateTx::stream_stored
bool stream_stored
Definition: detect.h:1211
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:1335
PROF_DETECT_GETSGH
@ PROF_DETECT_GETSGH
Definition: suricata-common.h:458
ts
uint64_t ts
Definition: source-erf-file.c:55
AppLayerTxData::flags
uint8_t flags
Definition: app-layer-parser.h:187
DetectEngineAppInspectionEngine_::v2
struct DetectEngineAppInspectionEngine_::@82 v2
SCAppLayerParserStateIssetFlag
uint16_t SCAppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint16_t flag)
Definition: app-layer-parser.c:1871
detect-engine.h
detect-engine-proto.h
DetectEngineThreadCtx_::match_array_cnt
SigIntId match_array_cnt
Definition: detect.h:1349
Frame::tx_id
uint64_t tx_id
Definition: app-layer-frames.h:52
DetectEngineStateDirection_::flags
uint8_t flags
Definition: detect-engine-state.h:91
DetectEngineThreadCtx_::counter_alerts
StatsCounterId counter_alerts
Definition: detect.h:1297
detect-dsize.h
Signature_::addr_src_match6
DetectMatchAddressIPv6 * addr_src_match6
Definition: detect.h:715
Flow_::flags
uint64_t flags
Definition: flow.h:396
sigmatch_table
SigTableElmt * sigmatch_table
Definition: detect-parse.c:79
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1293
DetectEngineCtx_::decoder_event_sgh
struct SigGroupHead_ * decoder_event_sgh
Definition: detect.h:1022
FlowGetPacketDirection
int FlowGetPacketDirection(const Flow *f, const Packet *p)
determine the direction of the packet compared to the flow
Definition: flow.c:286
DetectEngineCtx_::flow_gh
DetectEngineLookupFlow flow_gh[FLOW_STATES]
Definition: detect.h:964
DE_STATE_FLAG_SIG_CANT_MATCH
#define DE_STATE_FLAG_SIG_CANT_MATCH
Definition: detect-engine-state.h:59
ALPROTO_DNS
@ ALPROTO_DNS
Definition: app-layer-protos.h:47
DetectEngineAppInspectionEngine_::next
struct DetectEngineAppInspectionEngine_ * next
Definition: detect.h:441
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:1639
APP_LAYER_TX_SKIP_INSPECT_TC
#define APP_LAYER_TX_SKIP_INSPECT_TC
Definition: app-layer-parser.h:63
PostRuleMatchWorkQueue::len
uint32_t len
Definition: detect.h:1235
PKT_IS_PSEUDOPKT
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition: decode.h:1346
DetectEngineState_
Definition: detect-engine-state.h:95
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:1638
PACKET_ALERT_FLAG_STATE_MATCH
#define PACKET_ALERT_FLAG_STATE_MATCH
Definition: decode.h:269
DetectEngineCtx_::guess_applayer
bool guess_applayer
Definition: detect.h:984
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
Signature_::app_progress_hook
uint8_t app_progress_hook
Definition: detect.h:709
AppLayerFramesGetContainer
FramesContainer * AppLayerFramesGetContainer(const Flow *f)
Definition: app-layer-parser.c:184
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:1586
PcapPacketCntGet
uint64_t PcapPacketCntGet(const Packet *p)
Definition: decode.c:1107
DetectEngineAppInspectionEngine_::Callback
InspectEngineFuncPtr Callback
Definition: detect.h:434
Signature_::alproto
AppProto alproto
Definition: detect.h:677
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
FLOW_SGH_TOCLIENT
#define FLOW_SGH_TOCLIENT
Definition: flow.h:74
AppLayerParserSetTransactionInspectId
void AppLayerParserSetTransactionInspectId(const Flow *f, AppLayerParserState *pstate, void *alstate, const uint8_t flags, bool tag_txs_as_inspected)
Definition: app-layer-parser.c:778
DetectEngineStateDirection_::cnt
SigIntId cnt
Definition: detect-engine-state.h:89
AppLayerGetTxIterator
AppLayerGetTxIteratorFunc AppLayerGetTxIterator(const uint8_t ipproto, const AppProto alproto)
Definition: app-layer-parser.c:711
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
SigMatchData_::is_last
bool is_last
Definition: detect.h:367
AppLayerTxData::de_state
DetectEngineState * de_state
Definition: app-layer-parser.h:218
InspectionBufferClean
void InspectionBufferClean(DetectEngineThreadCtx *det_ctx)
Definition: detect-engine-inspect-buffer.c:30
Flow_::proto
uint8_t proto
Definition: flow.h:369
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:86
PacketAlerts_::cnt
uint16_t cnt
Definition: decode.h:288
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:1111
DetectEngineThreadCtx_::tx_id
uint64_t tx_id
Definition: detect.h:1326
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:368
action-globals.h
FLOWFILE_NO_MAGIC_TS
#define FLOWFILE_NO_MAGIC_TS
Definition: flow.h:129
FramesContainer::toserver
Frames toserver
Definition: app-layer-frames.h:72
Packet_::flags
uint32_t flags
Definition: decode.h:551
Packet_::action
uint8_t action
Definition: decode.h:613
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:347
DetectTransaction_::tx_end_state
const int tx_end_state
Definition: detect-engine-prefilter.h:44
PROF_DETECT_ALERT
@ PROF_DETECT_ALERT
Definition: suricata-common.h:469
DetectEngineThreadCtx_::pmq
PrefilterRuleStore pmq
Definition: detect.h:1358
SIG_GROUP_HEAD_HAVEFILESHA1
#define SIG_GROUP_HEAD_HAVEFILESHA1
Definition: detect.h:1503
FLOW_TC_APP_UPDATED
#define FLOW_TC_APP_UPDATED
Definition: flow.h:119
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:937
AppLayerParserGetStateProgressCompletionStatus
int AppLayerParserGetStateProgressCompletionStatus(AppProto alproto, uint8_t direction)
Definition: app-layer-parser.c:1140
DetectEngineCtx_::pre_stream_sgh
struct SigGroupHead_ * pre_stream_sgh[2]
Definition: detect.h:1163
DETECT_PROTO_ETHERNET
#define DETECT_PROTO_ETHERNET
Definition: detect-engine-proto.h:33
DetectRunScratchpad
struct DetectRunScratchpad DetectRunScratchpad
PROF_DETECT_PF_TX
@ PROF_DETECT_PF_TX
Definition: suricata-common.h:464
Frames::cnt
uint16_t cnt
Definition: app-layer-frames.h:59
Frame::id
int64_t id
Definition: app-layer-frames.h:51
DetectEngineThreadCtx_::p
Packet * p
Definition: detect.h:1330
DetectEngineState_::dir_state
DetectEngineStateDirection dir_state[2]
Definition: detect-engine-state.h:96
FrameGetByIndex
Frame * FrameGetByIndex(Frames *frames, const uint32_t idx)
Definition: app-layer-frames.c:145
RuleMatchCandidateTx::id
SigIntId id
Definition: detect.h:1207
PROF_DETECT_CLEANUP
@ PROF_DETECT_CLEANUP
Definition: suricata-common.h:471
SIG_FLAG_DST_ANY
#define SIG_FLAG_DST_ANY
Definition: detect.h:241
ACTION_SCOPE_FLOW
@ ACTION_SCOPE_FLOW
Definition: action-globals.h:45
NO_TX
#define NO_TX
Definition: detect.c:1410
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:224
HashTable_
Definition: util-hash.h:35
SIG_FLAG_TXBOTHDIR
#define SIG_FLAG_TXBOTHDIR
Definition: detect.h:249
Packet_::sig_mask
SignatureMask sig_mask
Definition: decode.h:542
Frames
Definition: app-layer-frames.h:58
FramesContainer
Definition: app-layer-frames.h:71
PacketAlerts_::drop
PacketAlert drop
Definition: decode.h:294
DetectEngineThreadCtx_::counter_alerts_overflow
StatsCounterId counter_alerts_overflow
Definition: detect.h:1299
DetectRunScratchpad
Definition: detect.c:69
SIG_GROUP_HEAD_HAVERAWSTREAM
#define SIG_GROUP_HEAD_HAVERAWSTREAM
Definition: detect.h:1497
FLOW_ACTION_DROP
#define FLOW_ACTION_DROP
Definition: flow.h:69
TcpStream_::flags
uint16_t flags
Definition: stream-tcp-private.h:107
FLOWFILE_NONE
#define FLOWFILE_NONE
Definition: flow.h:159
detect-engine-frame.h
SigMatchSignatures
void SigMatchSignatures(ThreadVars *tv, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:2434
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:735
proto
uint8_t proto
Definition: decode-template.h:0
m
SCMutex m
Definition: flow-hash.h:6
DetectPort_::sh
struct SigGroupHead_ * sh
Definition: detect.h:230
PKT_NOPAYLOAD_INSPECTION
#define PKT_NOPAYLOAD_INSPECTION
Definition: decode.h:1279
PACKET_PROFILING_DETECT_END
#define PACKET_PROFILING_DETECT_END(p, id)
Definition: util-profiling.h:221
DetectEngineThreadCtx_::counter_alerts_suppressed
StatsCounterId counter_alerts_suppressed
Definition: detect.h:1301
Detect
TmEcode Detect(ThreadVars *tv, Packet *p, void *data)
Detection engine thread wrapper.
Definition: detect.c:2355
detect-engine-payload.h
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:536
EngineModeIsFirewall
bool EngineModeIsFirewall(void)
Definition: suricata.c:239
SIG_FLAG_SRC_ANY
#define SIG_FLAG_SRC_ANY
Definition: detect.h:240
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
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:229
Flow_::protoctx
void * protoctx
Definition: flow.h:426
AppLayerGetTxIterTuple::tx_ptr
void * tx_ptr
Definition: app-layer-parser.h:165
SigMatchData_
Data needed for Match()
Definition: detect.h:365
DeStateStoreItem_::sid
SigIntId sid
Definition: detect-engine-state.h:77
RuleMatchCandidateTx::s
const Signature * s
Definition: detect.h:1217
KEYWORD_PROFILING_START
#define KEYWORD_PROFILING_START
Definition: util-profiling.h:50
SigMatchData_::type
uint16_t type
Definition: detect.h:366
DetectEngineCtx_::version
uint32_t version
Definition: detect.h:1018
DisableDetectFlowFileFlags
void DisableDetectFlowFileFlags(Flow *f)
disable file features we don't need Called if we have no detection engine.
Definition: detect.c:2424
AppLayerParserGetTransactionInspectId
uint64_t AppLayerParserGetTransactionInspectId(AppLayerParserState *pstate, uint8_t direction)
Definition: app-layer-parser.c:743
Packet_::alerts
PacketAlerts alerts
Definition: decode.h:624
DetectTransaction_::tx_progress
const int tx_progress
Definition: detect-engine-prefilter.h:43
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:74
Packet_::events
PacketEngineEvents events
Definition: decode.h:630
Signature_::frame_inspect
DetectEngineFrameInspectionEngine * frame_inspect
Definition: detect.h:731
PROF_DETECT_PF_SORT2
@ PROF_DETECT_PF_SORT2
Definition: suricata-common.h:467
pad
uint16_t pad
Definition: source-erf-file.c:61
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
PacketCreateMask
void PacketCreateMask(Packet *p, SignatureMask *mask, AppProto alproto, bool app_decoder_events)
Definition: detect-engine-build.c:401
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:1264
PacketAlert_::action
uint8_t action
Definition: decode.h:251
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:1804
SIG_FLAG_FIREWALL
#define SIG_FLAG_FIREWALL
Definition: detect.h:245
Flow_::sgh_toserver
const struct SigGroupHead_ * sgh_toserver
Definition: flow.h:479
PROF_DETECT_TX_UPDATE
@ PROF_DETECT_TX_UPDATE
Definition: suricata-common.h:470
DetectEngineAppInspectionEngine_::id
uint8_t id
Definition: detect.h:419
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
StatsCounterAvgAddI64
void StatsCounterAvgAddI64(StatsThreadContext *stats, StatsCounterAvgId id, int64_t x)
Definition: counters.c:239
DetectEngineAppInspectionEngine_::sm_list
uint16_t sm_list
Definition: detect.h:424
FLOWFILE_INIT
#define FLOWFILE_INIT
Definition: flow.h:126
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:471
FLOW_ACTION_PASS
#define FLOW_ACTION_PASS
Definition: flow.h:116
DETECT_ENGINE_INSPECT_SIG_CANT_MATCH_FILES
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH_FILES
Definition: detect-engine-state.h:46
FLOWFILE_NO_SHA1_TC
#define FLOWFILE_NO_SHA1_TC
Definition: flow.h:141
DETECT_SM_LIST_POSTMATCH
@ DETECT_SM_LIST_POSTMATCH
Definition: detect.h:127
FramesContainer::toclient
Frames toclient
Definition: app-layer-frames.h:73
DetectEngineCtx_::pre_flow_sgh
struct SigGroupHead_ * pre_flow_sgh
Definition: detect.h:1168
DetectEngineThreadCtx_::tx_candidates
RuleMatchCandidateTx * tx_candidates
Definition: detect.h:1351
SIG_TYPE_PKT
@ SIG_TYPE_PKT
Definition: detect.h:72
PKT_DROP_REASON_DEFAULT_APP_POLICY
@ PKT_DROP_REASON_DEFAULT_APP_POLICY
Definition: decode.h:400
Signature_::addr_src_match4
DetectMatchAddressIPv4 * addr_src_match4
Definition: detect.h:712
decode.h
PKT_SRC_WIRE
@ PKT_SRC_WIRE
Definition: decode.h:52
DETECT_PROTO_ARP
#define DETECT_PROTO_ARP
Definition: detect-engine-proto.h:34
TOSERVER
#define TOSERVER
Definition: flow.h:45
DetectEngineThreadCtx_::counter_mpm_list
StatsCounterAvgId counter_mpm_list
Definition: detect.h:1303
AppLayerTxData
Definition: app-layer-parser.h:177
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:19
PKT_IS_TOSERVER
#define PKT_IS_TOSERVER(p)
Definition: decode.h:239
Prefilter
void Prefilter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, const uint8_t flags, const SignatureMask mask)
Definition: detect-engine-prefilter.c:216
DetectTransaction_::detect_progress_orig
const uint8_t detect_progress_orig
Definition: detect-engine-prefilter.h:41
DetectEngineThreadCtx_
Definition: detect.h:1252
DEBUG_VALIDATE_PACKET
#define DEBUG_VALIDATE_PACKET(p)
Definition: util-validate.h:101
DeStateStoreItem_::flags
uint32_t flags
Definition: detect-engine-state.h:76
PKT_STREAM_ADD
#define PKT_STREAM_ADD
Definition: decode.h:1287
DetectTransaction_::detect_progress
uint8_t detect_progress
Definition: detect-engine-prefilter.h:39
FLOWFILE_NO_STORE_TS
#define FLOWFILE_NO_STORE_TS
Definition: flow.h:133
BIT_U32
#define BIT_U32(n)
Definition: suricata-common.h:417
DetectEngineThreadCtx_::tx_candidates_size
uint32_t tx_candidates_size
Definition: detect.h:1352
FRAME_FLAG_TX_ID_SET
#define FRAME_FLAG_TX_ID_SET
Definition: app-layer-frames.h:36
PKT_PSEUDO_STREAM_END
#define PKT_PSEUDO_STREAM_END
Definition: decode.h:1295
PKT_IS_FRAGMENT
#define PKT_IS_FRAGMENT
Definition: decode.h:1317
BOOL2STR
#define BOOL2STR(b)
Definition: util-debug.h:542
STREAM_FLAGS_FOR_PACKET
#define STREAM_FLAGS_FOR_PACKET(p)
Definition: stream.h:30
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
PMQ_RESET
#define PMQ_RESET(pmq)
Definition: util-prefilter.h:46
detect-engine-mpm.h
DetectEngineLookupFlow_::sgh
struct SigGroupHead_ * sgh[256]
Definition: detect.h:869
HashTableLookup
void * HashTableLookup(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:182
AppLayerGetTxIterTuple::tx_id
uint64_t tx_id
Definition: app-layer-parser.h:166
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
DeStateStore_::next
struct DeStateStore_ * next
Definition: detect-engine-state.h:82
DetectRunScratchpad::default_action
const uint8_t default_action
Definition: detect.c:79
Packet_::sp
Port sp
Definition: decode.h:512
FLOWFILE_NO_SHA256_TS
#define FLOWFILE_NO_SHA256_TS
Definition: flow.h:144
DETECT_ENGINE_INSPECT_SIG_MATCH
#define DETECT_ENGINE_INSPECT_SIG_MATCH
Definition: detect-engine-state.h:41
PKT_DETECT_HAS_STREAMDATA
#define PKT_DETECT_HAS_STREAMDATA
Definition: decode.h:1332
FLOW_PKT_TOCLIENT_FIRST
#define FLOW_PKT_TOCLIENT_FIRST
Definition: flow.h:228
StreamReassembleRawHasDataReady
bool StreamReassembleRawHasDataReady(TcpSession *ssn, Packet *p)
does the stream engine have data to inspect?
Definition: stream-tcp-reassemble.c:1505
detect-engine-port.h
PktSrcToString
const char * PktSrcToString(enum PktSrcEnum pkt_src)
Definition: decode.c:876
DetectPort_
Port structure for detection engine.
Definition: detect.h:219
PacketAlerts_::discarded
uint16_t discarded
Definition: decode.h:289
app-layer-parser.h
Signature_::app_inspect
DetectEngineAppInspectionEngine * app_inspect
Definition: detect.h:729
ThreadVars_::id
int id
Definition: threadvars.h:86
util-detect.h
detect-engine-profile.h
Flow_::sgh_toclient
const struct SigGroupHead_ * sgh_toclient
Definition: flow.h:476
DetectEngineThreadCtx_::base64_decoded_len
int base64_decoded_len
Definition: detect.h:1333
SIG_FLAG_REQUIRE_FLOWVAR
#define SIG_FLAG_REQUIRE_FLOWVAR
Definition: detect.h:266
RuleMatchCandidateTx::stream_result
uint8_t stream_result
Definition: detect.h:1212
Signature_::action
uint8_t action
Definition: detect.h:687
util-profiling.h
DetectTransaction_::tx_id
const uint64_t tx_id
Definition: detect-engine-prefilter.h:33
DetectEngineLookupFlow_::udp
DetectPort * udp
Definition: detect.h:868
DetectEngineThreadCtx_::raw_stream_progress
uint64_t raw_stream_progress
Definition: detect.h:1273
SigIntId
#define SigIntId
Definition: detect-engine-state.h:38
FileUpdateFlowFileFlags
void FileUpdateFlowFileFlags(Flow *f, uint16_t set_file_flags, uint8_t direction)
set a flow's file flags
Definition: util-file.c:1091
SCReturn
#define SCReturn
Definition: util-debug.h:286
Signature_::flags
uint32_t flags
Definition: detect.h:673
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:369
RuleMatchCandidateTxArrayFree
void RuleMatchCandidateTxArrayFree(DetectEngineThreadCtx *det_ctx)
Definition: detect.c:1099
AppLayerGetTxIterState
Definition: app-layer-parser.h:153
Packet_
Definition: decode.h:505
detect-engine-build.h
ACTION_SCOPE_TX
@ ACTION_SCOPE_TX
Definition: action-globals.h:47
DetectEngineThreadCtx_::frame_id
int64_t frame_id
Definition: detect.h:1327
detect-engine-alert.h
AppLayerTxData::guessed_applayer_logged
uint8_t guessed_applayer_logged
Definition: app-layer-parser.h:207
DetectEngineThreadCtx_::filestore_cnt
uint16_t filestore_cnt
Definition: detect.h:1294
PROF_DETECT_IPONLY
@ PROF_DETECT_IPONLY
Definition: suricata-common.h:459
RULE_PROFILING_END
#define RULE_PROFILING_END(a, b, c, p)
Definition: util-profiling.h:422
TmEcode
TmEcode
Definition: tm-threads-common.h:80
RULE_PROFILING_START
#define RULE_PROFILING_START(p)
Definition: util-profiling.h:421
ALPROTO_DOH2
@ ALPROTO_DOH2
Definition: app-layer-protos.h:66
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:300
DetectPreFlow
uint8_t DetectPreFlow(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, Packet *p)
Definition: detect.c:2326
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:1430
detect-replace.h
AppLayerGetTxIterTuple
Definition: app-layer-parser.h:164
RulesDumpMatchArray
void RulesDumpMatchArray(const DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, const Packet *p)
Definition: detect-engine-profile.c:78
ALPROTO_HTTP2
@ ALPROTO_HTTP2
Definition: app-layer-protos.h:69
Signature_::addr_dst_match6_cnt
uint16_t addr_dst_match6_cnt
Definition: detect.h:699
AppLayerTxData::detect_progress_ts
uint8_t detect_progress_ts
Definition: app-layer-parser.h:215
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:225
SigGroupHead_::frame_engines
PrefilterEngine * frame_engines
Definition: detect.h:1651
PACKET_ALERT_NOTX
#define PACKET_ALERT_NOTX
Definition: detect.h:55
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:280
Signature_::sp
DetectPort * sp
Definition: detect.h:723
APP_LAYER_PARSER_NO_INSPECTION
#define APP_LAYER_PARSER_NO_INSPECTION
Definition: app-layer-parser.h:44
AppLayerParserGetTx
void * AppLayerParserGetTx(uint8_t ipproto, AppProto alproto, void *alstate, uint64_t tx_id)
Definition: app-layer-parser.c:1133
DetectRunScratchpad::sgh
const SigGroupHead * sgh
Definition: detect.c:80
PACKET_ALERT_FLAG_APPLY_ACTION_TO_PACKET
#define PACKET_ALERT_FLAG_APPLY_ACTION_TO_PACKET
Definition: decode.h:281
PacketAlertFinalize
void PacketAlertFinalize(const 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:603
DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
#define DETECT_ENGINE_INSPECT_SIG_CANT_MATCH
Definition: detect-engine-state.h:42
DETECT_ENGINE_STATE_FLAG_FILE_NEW
#define DETECT_ENGINE_STATE_FLAG_FILE_NEW
Definition: detect-engine-state.h:73
Flow_::flowvar
GenericVar * flowvar
Definition: flow.h:482
PKT_DROP_REASON_DEFAULT_PACKET_POLICY
@ PKT_DROP_REASON_DEFAULT_PACKET_POLICY
Definition: decode.h:399
RuleMatchCandidateTx::flags
uint32_t * flags
Definition: detect.h:1208
PACKET_ALERT_FLAG_FRAME
#define PACKET_ALERT_FLAG_FRAME
Definition: decode.h:277
Frame::flags
uint8_t flags
Definition: app-layer-frames.h:45
DetectEngineAppInspectionEngine_::alproto
AppProto alproto
Definition: detect.h:417
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:145
DetectEngineStateDirection_::head
DeStateStore * head
Definition: detect-engine-state.h:86
DETECT_ENGINE_INSPECT_SIG_MATCH_MORE_FILES
#define DETECT_ENGINE_INSPECT_SIG_MATCH_MORE_FILES
Definition: detect-engine-state.h:52
DetectEngineCtx_::eth_non_ip_sgh
struct SigGroupHead_ * eth_non_ip_sgh
Definition: detect.h:1025
DetectProto_::flags
uint8_t flags
Definition: detect-engine-proto.h:40
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:1619
Packet_::tenant_id
uint32_t tenant_id
Definition: decode.h:665
Packet_::flow
struct Flow_ * flow
Definition: decode.h:553
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:130
flags
uint8_t flags
Definition: decode-gre.h:0
SCGenericVarFree
void SCGenericVarFree(GenericVar *gv)
Definition: util-var.c:48
suricata-common.h
SIG_FLAG_SP_ANY
#define SIG_FLAG_SP_ANY
Definition: detect.h:242
ActionScope
ActionScope
Definition: action-globals.h:42
AppLayerTxData::updated_tc
bool updated_tc
Definition: app-layer-parser.h:184
ACTION_SCOPE_HOOK
@ ACTION_SCOPE_HOOK
Definition: action-globals.h:46
Signature_::action_scope
uint8_t action_scope
Definition: detect.h:694
packet.h
DeStateStore_
Definition: detect-engine-state.h:80
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:539
PROF_DETECT_SETUP
@ PROF_DETECT_SETUP
Definition: suricata-common.h:457
DetectEngineStateDirection_
Definition: detect-engine-state.h:85
DetectEngineThreadCtx_::frame_inspect_progress
uint64_t frame_inspect_progress
Definition: detect.h:1328
DetectEngineCtx_::profile_match_logging_threshold
uint32_t profile_match_logging_threshold
Definition: detect.h:1057
FLOW_TS_APP_UPDATED
#define FLOW_TS_APP_UPDATED
Definition: flow.h:118
Signature_::proto
DetectProto * proto
Definition: detect.h:691
AppLayerParserGetTxData
AppLayerTxData * AppLayerParserGetTxData(uint8_t ipproto, AppProto alproto, void *tx)
Definition: app-layer-parser.c:1207
FatalError
#define FatalError(...)
Definition: util-debug.h:517
AppLayerTxData::detect_progress_tc
uint8_t detect_progress_tc
Definition: app-layer-parser.h:216
TcpSession_::client
TcpStream client
Definition: stream-tcp-private.h:297
FLOWFILE_NO_STORE_TC
#define FLOWFILE_NO_STORE_TC
Definition: flow.h:134
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:33
DetectEngineAppInspectionEngine_::progress
int16_t progress
Definition: detect.h:426
FLOW_ACTION_ACCEPT
#define FLOW_ACTION_ACCEPT
Definition: flow.h:63
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:700
StreamReassembleRawUpdateProgress
void StreamReassembleRawUpdateProgress(TcpSession *ssn, Packet *p, const uint64_t progress)
update stream engine after detection
Definition: stream-tcp-reassemble.c:1551
FLOWFILE_NO_SHA1_TS
#define FLOWFILE_NO_SHA1_TS
Definition: flow.h:140
PROF_DETECT_RULES
@ PROF_DETECT_RULES
Definition: suricata-common.h:460
APP_LAYER_TX_INSPECTED_TS
#define APP_LAYER_TX_INSPECTED_TS
Definition: app-layer-parser.h:65
DetectRunScratchpad::app_decoder_events
const bool app_decoder_events
Definition: detect.c:72
TcpSession_::server
TcpStream server
Definition: stream-tcp-private.h:296
Signature_::dp
DetectPort * dp
Definition: detect.h:723
PacketAlerts_::suppressed
uint16_t suppressed
Definition: decode.h:290
PACKET_PROFILING_DETECT_START
#define PACKET_PROFILING_DETECT_START(p, id)
Definition: util-profiling.h:214
DetectEngineThreadCtx_::replace
const Signature ** replace
Definition: detect.h:1344
Signature_::iid
SigIntId iid
Definition: detect.h:684
FLOW_SGH_TOSERVER
#define FLOW_SGH_TOSERVER
Definition: flow.h:72
APP_LAYER_TX_ACCEPT
#define APP_LAYER_TX_ACCEPT
Definition: app-layer-parser.h:68
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Packet_::pkt_src
uint8_t pkt_src
Definition: decode.h:615
SGH_PROFILING_RECORD
#define SGH_PROFILING_RECORD(det_ctx, sgh)
Definition: util-profiling.h:252
Signature_::addr_dst_match6
DetectMatchAddressIPv6 * addr_dst_match6
Definition: detect.h:714
Flow_::alstate
void * alstate
Definition: flow.h:472
Signature_::id
uint32_t id
Definition: detect.h:717
DeStateStore_::store
DeStateStoreItem store[DE_STATE_CHUNK_SIZE]
Definition: detect-engine-state.h:81
DetectEngineCtx_::guess_applayer_log_limit
uint8_t guess_applayer_log_limit
Definition: detect.h:981
RuleMatchCandidateTx::stream_reset
uint32_t stream_reset
Definition: detect.h:1214
ACTION_SCOPE_PACKET
@ ACTION_SCOPE_PACKET
Definition: action-globals.h:44
detect-engine-iponly.h
Signature_
Signature container.
Definition: detect.h:672
AppLayerGetTxIterTuple::has_next
bool has_next
Definition: app-layer-parser.h:167
PACKET_ALERT_FLAG_TX
#define PACKET_ALERT_FLAG_TX
Definition: decode.h:273
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
TRACE_SID_TXS
#define TRACE_SID_TXS(sid, txs,...)
Definition: detect.c:1162
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:226
DetectEngineThreadCtx_::tx_id_set
bool tx_id_set
Definition: detect.h:1324
PacketDrop
void PacketDrop(Packet *p, const uint8_t action, enum PacketDropReason r)
issue drop action
Definition: packet.c:34
ACTION_ACCEPT
#define ACTION_ACCEPT
Definition: action-globals.h:36
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:1373
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:1000
DetectEngineCtx_::sig_array
Signature ** sig_array
Definition: detect.h:955
Packet_::dst
Address dst
Definition: decode.h:510
PROF_DETECT_TX
@ PROF_DETECT_TX
Definition: suricata-common.h:461
DetectEngineAppInspectionEngine_::dir
uint8_t dir
Definition: detect.h:418
PKT_NOPACKET_INSPECTION
#define PKT_NOPACKET_INSPECTION
Definition: decode.h:1274
PrefilterPostRuleMatch
void PrefilterPostRuleMatch(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, Flow *f)
invoke post-rule match "prefilter" engines
Definition: detect-engine-prefilter.c:193
DetectGetInnerTx
void * DetectGetInnerTx(void *tx_ptr, AppProto alproto, AppProto engine_alproto, uint8_t flow_flags)
Definition: detect.c:1166
DetectPreStream
uint8_t DetectPreStream(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, Packet *p)
Definition: detect.c:2336
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:58
STREAMTCP_STREAM_FLAG_DISABLE_RAW
#define STREAMTCP_STREAM_FLAG_DISABLE_RAW
Definition: stream-tcp-private.h:238
DetectEngineThreadCtx_::json_content_len
uint8_t json_content_len
Definition: detect.h:1291
DetectEngineThreadCtx_::mt_det_ctxs_cnt
uint32_t mt_det_ctxs_cnt
Definition: detect.h:1262
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:227
likely
#define likely(expr)
Definition: util-optimize.h:32
IPPROTO_SCTP
#define IPPROTO_SCTP
Definition: decode.h:1255
DE_STATE_FLAG_FILE_INSPECT
#define DE_STATE_FLAG_FILE_INSPECT
Definition: detect-engine-state.h:63
DetectEngineThreadCtx_::counter_match_list
StatsCounterAvgId counter_match_list
Definition: detect.h:1304
DetectEngineCtx_::io_ctx
DetectEngineIPOnlyCtx io_ctx
Definition: detect.h:975
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:711
FlowGetDisruptionFlags
uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags)
get 'disruption' flags: GAP/DEPTH/PASS
Definition: flow.c:1165
TcpSession_
Definition: stream-tcp-private.h:283
flow.h
Signature_::addr_src_match4_cnt
uint16_t addr_src_match4_cnt
Definition: detect.h:698
DeStateStoreItem_
Definition: detect-engine-state.h:75
Signature_::addr_dst_match4_cnt
uint16_t addr_dst_match4_cnt
Definition: detect.h:697
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:443
Packet_::dp
Port dp
Definition: decode.h:520
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DetectEngineCtx_::sig_array_len
uint32_t sig_array_len
Definition: detect.h:956
SIG_GROUP_HEAD_HAVEFILESHA256
#define SIG_GROUP_HEAD_HAVEFILESHA256
Definition: detect.h:1504
ThreadVars_::stats
StatsThreadContext stats
Definition: threadvars.h:121
Signature_::type
enum SignatureType type
Definition: detect.h:675
StatsCounterAddI64
void StatsCounterAddI64(StatsThreadContext *stats, StatsCounterId id, int64_t x)
Adds a value of type uint64_t to the local counter.
Definition: counters.c:145
SigGroupHead_::filestore_cnt
uint16_t filestore_cnt
Definition: detect.h:1644
AppLayerParserGetTxCnt
uint64_t AppLayerParserGetTxCnt(const Flow *f, void *alstate)
Definition: app-layer-parser.c:1126
AppLayerParserHasDecoderEvents
bool AppLayerParserHasDecoderEvents(AppLayerParserState *pstate)
Definition: app-layer-parser.c:1537
FLOW_PKT_TOSERVER_FIRST
#define FLOW_PKT_TOSERVER_FIRST
Definition: flow.h:227
DetectEngineLookupFlow_::tcp
DetectPort * tcp
Definition: detect.h:867
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
detect-engine-address.h
Flow_::tenant_id
uint32_t tenant_id
Definition: flow.h:417
Packet_::src
Address src
Definition: decode.h:509
SigMatchSignaturesGetSgh
const SigGroupHead * SigMatchSignaturesGetSgh(const DetectEngineCtx *de_ctx, const Packet *p)
Get the SigGroupHead for a packet.
Definition: detect.c:282
DetectRunPrefilterTx
void DetectRunPrefilterTx(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, const uint8_t ipproto, const uint8_t flow_flags, const AppProto alproto, void *alstate, DetectTransaction *tx)
run prefilter engines on a transaction
Definition: detect-engine-prefilter.c:95
RuleMatchCandidateTxArrayInit
void RuleMatchCandidateTxArrayInit(DetectEngineThreadCtx *det_ctx, uint32_t size)
Definition: detect.c:1086
APP_LAYER_TX_INSPECTED_TC
#define APP_LAYER_TX_INSPECTED_TC
Definition: app-layer-parser.h:66
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:585
DetectEngineThreadCtx_::post_rule_work_queue
PostRuleMatchWorkQueue post_rule_work_queue
Definition: detect.h:1356
PKT_STREAM_EST
#define PKT_STREAM_EST
Definition: decode.h:1289
detect-engine-threshold.h
APP_LAYER_TX_SKIP_INSPECT_TS
#define APP_LAYER_TX_SKIP_INSPECT_TS
Definition: app-layer-parser.h:62
Signature_::mask
SignatureMask mask
Definition: detect.h:683
AppLayerTxData::updated_ts
bool updated_ts
Definition: app-layer-parser.h:185
app-layer.h
RuleMatchCandidateTx
Definition: detect.h:1206
DetectEngineThreadCtx_::TenantGetId
uint32_t(* TenantGetId)(const void *, const Packet *p)
Definition: detect.h:1269
PrefilterRuleStore_::rule_id_array
SigIntId * rule_id_array
Definition: util-prefilter.h:38
PacketEngineEvents_::cnt
uint8_t cnt
Definition: decode.h:308
Flow_::de_ctx_version
uint32_t de_ctx_version
Definition: flow.h:457
DetectProtoContainsProto
int DetectProtoContainsProto(const DetectProto *dp, int proto)
see if a DetectProto contains a certain proto
Definition: detect-engine-proto.c:115
DetectEngineThreadCtx_::match_array
Signature ** match_array
Definition: detect.h:1341