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