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