suricata
detect-engine-content-inspection.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2023 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 Anoop Saldanha <anoopsaldanha@gmail.com>
22  *
23  * Performs content inspection on any buffer supplied.
24  */
25 
26 #include "suricata-common.h"
27 #include "suricata.h"
28 #include "decode.h"
29 
30 #include "detect.h"
31 #include "detect-engine.h"
32 #include "detect-parse.h"
33 
34 #include "rust.h"
35 
36 #include "detect-asn1.h"
37 #include "detect-content.h"
38 #include "detect-pcre.h"
39 #include "detect-isdataat.h"
40 #include "detect-bytetest.h"
41 #include "detect-bytemath.h"
42 #include "detect-bytejump.h"
43 #include "detect-byte-extract.h"
44 #include "detect-entropy.h"
45 #include "detect-replace.h"
47 #include "detect-uricontent.h"
48 #include "detect-urilen.h"
49 #include "detect-engine-uint.h"
50 #include "detect-bsize.h"
51 #include "detect-lua.h"
52 #include "detect-base64-decode.h"
53 #include "detect-base64-data.h"
54 #include "detect-dataset.h"
55 #include "detect-datarep.h"
56 
57 #include "util-spm.h"
58 #include "util-debug.h"
59 #include "util-print.h"
60 #include "util-validate.h"
61 
62 #include "util-unittest-helper.h"
63 #include "util-profiling.h"
64 
65 #include "util-lua.h"
66 
67 #ifdef UNITTESTS
68 thread_local uint32_t ut_inspection_recursion_counter = 0;
69 #endif
70 
72  struct {
73  uint32_t count;
74  const uint32_t limit;
76 };
77 
78 /**
79  * \brief Run the actual payload match functions
80  *
81  * All keywords are evaluated against the buffer with buffer_len.
82  *
83  * For accounting the last match in relative matching the
84  * det_ctx->buffer_offset int is used.
85  *
86  * \param det_ctx Detection engine thread context
87  * \param s Signature to inspect
88  * \param sm SigMatch to inspect
89  * \param p Packet. Can be NULL.
90  * \param f Flow (for pcre flowvar storage)
91  * \param buffer Ptr to the buffer to inspect
92  * \param buffer_len Length of the payload
93  * \param stream_start_offset Indicates the start of the current buffer in
94  * the whole buffer stream inspected. This
95  * applies if the current buffer is inspected
96  * in chunks.
97  * \param inspection_mode Refers to the engine inspection mode we are currently
98  * inspecting. Can be payload, stream, one of the http
99  * buffer inspection modes or dce inspection mode.
100  * \param flags DETECT_CI_FLAG_*
101  *
102  * \retval -1 no match and give up (discontinue matching)
103  * \retval 0 no match
104  * \retval 1 match
105  */
106 static int DetectEngineContentInspectionInternal(DetectEngineThreadCtx *det_ctx,
107  struct DetectEngineContentInspectionCtx *ctx, const Signature *s, const SigMatchData *smd,
108  Packet *p, Flow *f, const uint8_t *buffer, const uint32_t buffer_len,
109  const uint64_t stream_start_offset, const uint8_t flags,
110  const enum DetectContentInspectionType inspection_mode)
111 {
112  SCEnter();
114 
115  ctx->recursion.count++;
116  if (unlikely(ctx->recursion.count == ctx->recursion.limit)) {
117  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
118  SCReturnInt(-1);
119  }
120 
121  // we want the ability to match on bsize: 0
122  if (smd == NULL || buffer == NULL) {
123  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
124  SCReturnInt(0);
125  }
126 
127  if (smd->type == DETECT_CONTENT) {
128  const DetectContentData *cd = (const DetectContentData *)smd->ctx;
129  SCLogDebug("inspecting content %"PRIu32" buffer_len %"PRIu32, cd->id, buffer_len);
130 
131  /* we might have already have this content matched by the mpm.
132  * (if there is any other reason why we'd want to avoid checking
133  * it here, please fill it in) */
134  //if (cd->flags & DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED) {
135  // goto match;
136  //}
137 
138  /* rule parsers should take care of this */
139 #ifdef DEBUG
140  BUG_ON(cd->depth != 0 && cd->depth <= cd->offset);
141 #endif
142 
143  /* search for our pattern, checking the matches recursively.
144  * if we match we look for the next SigMatch as well */
145  uint32_t prev_offset = 0; /**< used in recursive searching */
146  uint32_t prev_buffer_offset = det_ctx->buffer_offset;
147 
148  do {
149  uint32_t depth = buffer_len;
150  uint32_t offset = 0;
151  if ((cd->flags & DETECT_CONTENT_DISTANCE) ||
152  (cd->flags & DETECT_CONTENT_WITHIN)) {
153  SCLogDebug("det_ctx->buffer_offset %" PRIu32, det_ctx->buffer_offset);
154  offset = prev_buffer_offset;
155 
156  int distance = cd->distance;
157  if (cd->flags & DETECT_CONTENT_DISTANCE) {
159  // This cast is wrong if a 64-bit value was extracted
160  distance = (uint32_t)det_ctx->byte_values[cd->distance];
161  }
162  if (distance < 0 && (uint32_t)(abs(distance)) > offset)
163  offset = 0;
164  else
165  offset += distance;
166 
167  SCLogDebug("cd->distance %"PRIi32", offset %"PRIu32", depth %"PRIu32,
168  distance, offset, depth);
169  }
170 
171  if (cd->flags & DETECT_CONTENT_WITHIN) {
172  if (cd->flags & DETECT_CONTENT_WITHIN_VAR) {
173  // This cast is wrong if a 64-bit value was extracted for within
174  if ((int32_t)depth > (int32_t)(prev_buffer_offset + det_ctx->byte_values[cd->within] + distance)) {
175  depth = prev_buffer_offset +
176  (uint32_t)det_ctx->byte_values[cd->within] + distance;
177  }
178  } else {
179  if ((int32_t)depth > (int32_t)(prev_buffer_offset + cd->within + distance)) {
180  depth = prev_buffer_offset + cd->within + distance;
181  }
182 
183  SCLogDebug("cd->within %"PRIi32", det_ctx->buffer_offset %"PRIu32", depth %"PRIu32,
184  cd->within, prev_buffer_offset, depth);
185  }
186 
187  if (stream_start_offset != 0 && prev_buffer_offset == 0) {
188  if (depth <= stream_start_offset) {
189  goto no_match;
190  } else if (depth >= (stream_start_offset + buffer_len)) {
191  ;
192  } else {
193  depth = depth - (uint32_t)stream_start_offset;
194  }
195  }
196  }
197 
198  if (cd->flags & DETECT_CONTENT_DEPTH_VAR) {
199  if ((det_ctx->byte_values[cd->depth] + prev_buffer_offset) < depth) {
200  // ok to cast as we checked the byte value fits in a u32
201  depth = prev_buffer_offset + (uint32_t)det_ctx->byte_values[cd->depth];
202  }
203  } else {
204  if (cd->depth != 0) {
205  if ((cd->depth + prev_buffer_offset) < depth) {
206  depth = prev_buffer_offset + cd->depth;
207  }
208 
209  SCLogDebug("cd->depth %"PRIu32", depth %"PRIu32, cd->depth, depth);
210  }
211  }
212 
213  if (cd->flags & DETECT_CONTENT_OFFSET_VAR) {
214  if (det_ctx->byte_values[cd->offset] > offset) {
215  // This cast is wrong if a 64-bit value was extracted
216  offset = (uint32_t)det_ctx->byte_values[cd->offset];
217  }
218  } else {
219  if (cd->offset > offset) {
220  offset = cd->offset;
221  SCLogDebug("setting offset %"PRIu32, offset);
222  }
223  }
224  } else { /* implied no relative matches */
225  /* set depth */
226  if (cd->flags & DETECT_CONTENT_DEPTH_VAR) {
227  // This cast is wrong if a 64-bit value was extracted
228  depth = (uint32_t)det_ctx->byte_values[cd->depth];
229  } else {
230  if (cd->depth != 0) {
231  depth = cd->depth;
232  }
233  }
234 
235  if (stream_start_offset != 0 && cd->flags & DETECT_CONTENT_DEPTH) {
236  if (depth <= stream_start_offset) {
237  goto no_match;
238  } else if (depth >= (stream_start_offset + buffer_len)) {
239  ;
240  } else {
241  depth = (uint32_t)(depth - stream_start_offset);
242  }
243  }
244 
245  /* set offset */
246  if (cd->flags & DETECT_CONTENT_OFFSET_VAR) {
247  // This cast is wrong if a 64-bit value was extracted
248  offset = (uint32_t)det_ctx->byte_values[cd->offset];
249  } else {
250  offset = cd->offset;
251  }
252  prev_buffer_offset = 0;
253  }
254 
255  /* If the value came from a variable, make sure to adjust the depth so it's relative
256  * to the offset value.
257  */
259  depth += offset;
260  }
261 
262  /* update offset with prev_offset if we're searching for
263  * matches after the first occurrence. */
264  SCLogDebug("offset %"PRIu32", prev_offset %"PRIu32, offset, prev_offset);
265  if (prev_offset != 0)
266  offset = prev_offset;
267 
268  SCLogDebug("offset %"PRIu32", depth %"PRIu32, offset, depth);
269 
270  if (depth > buffer_len)
271  depth = buffer_len;
272 
273  /* if offset is bigger than depth we can never match on a pattern.
274  * We can however, "match" on a negated pattern. */
275  if (offset > depth || depth == 0) {
276  if (cd->flags & DETECT_CONTENT_NEGATED) {
277  goto match;
278  } else {
279  goto no_match;
280  }
281  }
282 
283  const uint8_t *sbuffer = buffer + offset;
284  uint32_t sbuffer_len = depth - offset;
285  SCLogDebug("sbuffer_len %" PRIu32 " depth: %" PRIu32 ", buffer_len: %" PRIu32,
286  sbuffer_len, depth, buffer_len);
287 #ifdef DEBUG
288  BUG_ON(sbuffer_len > buffer_len);
289 #endif
290  const uint8_t *found;
291  if (cd->flags & DETECT_CONTENT_ENDS_WITH && depth < buffer_len) {
292  SCLogDebug("depth < buffer_len while DETECT_CONTENT_ENDS_WITH is set. Can't possibly match.");
293  found = NULL;
294  } else if (cd->content_len > sbuffer_len) {
295  found = NULL;
296  } else {
297  /* do the actual search */
298  found = SpmScan(cd->spm_ctx, det_ctx->spm_thread_ctx, sbuffer,
299  sbuffer_len);
300  }
301 
302  /* next we evaluate the result in combination with the
303  * negation flag. */
304  SCLogDebug("found %p cd negated %s", found, cd->flags & DETECT_CONTENT_NEGATED ? "true" : "false");
305 
306  if (found == NULL) {
307  if (!(cd->flags & DETECT_CONTENT_NEGATED)) {
308  if ((cd->flags & (DETECT_CONTENT_DISTANCE | DETECT_CONTENT_WITHIN)) == 0) {
309  /* independent match from previous matches, so failure is fatal */
310  goto no_match_discontinue;
311  }
312 
313  goto no_match;
314  } else {
315  goto match;
316  }
317  }
318 
319  uint32_t match_offset = (uint32_t)((found - buffer) + cd->content_len);
320  if (cd->flags & DETECT_CONTENT_NEGATED) {
321  SCLogDebug("content %" PRIu32 " matched at offset %" PRIu32
322  ", but negated so no match",
323  cd->id, match_offset);
324  /* don't bother carrying recursive matches now, for preceding
325  * relative keywords */
326 
327  /* found a match but not at the end of the buffer */
328  if (cd->flags & DETECT_CONTENT_ENDS_WITH) {
329  if (sbuffer_len != match_offset) {
330  SCLogDebug("content \"%s\" %" PRIu32 " matched at offset %" PRIu32
331  ", but not at end of buffer so match",
332  cd->content, cd->id, match_offset);
333  goto match;
334  }
335  }
336  if (DETECT_CONTENT_IS_SINGLE(cd)) {
337  goto no_match_discontinue;
338  }
339  goto no_match;
340  }
341 
342  SCLogDebug("content %" PRIu32 " matched at offset %" PRIu32 "", cd->id, match_offset);
343  det_ctx->buffer_offset = match_offset;
344 
345  if ((cd->flags & DETECT_CONTENT_ENDS_WITH) == 0 || match_offset == buffer_len) {
346  /* Match branch, add replace to the list if needed */
348  if (inspection_mode == DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD) {
349  /* we will need to replace content if match is confirmed
350  * cast to non-const as replace writes to it. */
351  det_ctx->replist =
352  DetectReplaceAddToList(det_ctx->replist, (uint8_t *)found, cd);
353  } else {
354  SCLogWarning("Can't modify payload without packet");
355  }
356  }
357 
358  /* if this is the last match we're done */
359  if (smd->is_last) {
360  goto match;
361  }
362 
363  SCLogDebug("content %" PRIu32, cd->id);
364  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
365 
366  /* see if the next buffer keywords match. If not, we will
367  * search for another occurrence of this content and see
368  * if the others match then until we run out of matches */
369  int r = DetectEngineContentInspectionInternal(det_ctx, ctx, s, smd + 1, p, f,
370  buffer, buffer_len, stream_start_offset, flags, inspection_mode);
371  if (r == 1) {
372  SCReturnInt(1);
373  } else if (r == -1) {
374  SCLogDebug("'next sm' said to discontinue this right now");
375  SCReturnInt(-1);
376  }
377  SCLogDebug("no match for 'next sm'");
378 
379  /* no match and no reason to look for another instance */
380  if ((cd->flags & DETECT_CONTENT_WITHIN_NEXT) == 0) {
381  SCLogDebug("'next sm' does not depend on me, so we can give up");
382  SCReturnInt(-1);
383  }
384 
385  SCLogDebug("'next sm' depends on me %p, lets see what we can do (flags %u)", cd,
386  cd->flags);
387  }
388  /* set the previous match offset to the start of this match + 1 */
389  prev_offset = (match_offset - (cd->content_len - 1));
390  SCLogDebug("trying to see if there is another match after prev_offset %" PRIu32,
391  prev_offset);
392  } while(1);
393 
394  } else if (smd->type == DETECT_ABSENT) {
395  const DetectAbsentData *id = (DetectAbsentData *)smd->ctx;
396  if (!id->or_else) {
397  // we match only on absent buffer
398  goto no_match;
399  }
400  goto match;
401  } else if (smd->type == DETECT_ISDATAAT) {
402  SCLogDebug("inspecting isdataat");
403 
404  const DetectIsdataatData *id = (DetectIsdataatData *)smd->ctx;
405  uint32_t dataat = id->dataat;
406  if (id->flags & ISDATAAT_OFFSET_VAR) {
407  uint64_t be_value = det_ctx->byte_values[dataat];
408  if (be_value >= 100000000) {
409  if ((id->flags & ISDATAAT_NEGATED) == 0) {
410  SCLogDebug("extracted value %"PRIu64" very big: no match", be_value);
411  goto no_match;
412  }
413  SCLogDebug("extracted value way %"PRIu64" very big: match", be_value);
414  goto match;
415  }
416  dataat = (uint32_t)be_value;
417  SCLogDebug("isdataat: using value %u from byte_extract local_id %u", dataat, id->dataat);
418  }
419 
420  if (id->flags & ISDATAAT_RELATIVE) {
421  if (det_ctx->buffer_offset + dataat > buffer_len) {
422  SCLogDebug("det_ctx->buffer_offset + dataat %"PRIu32" > %"PRIu32, det_ctx->buffer_offset + dataat, buffer_len);
423  if (id->flags & ISDATAAT_NEGATED)
424  goto match;
425  if ((id->flags & ISDATAAT_OFFSET_VAR) == 0) {
426  goto no_match_discontinue;
427  }
428  goto no_match;
429  } else {
430  SCLogDebug("relative isdataat match");
431  if (id->flags & ISDATAAT_NEGATED) {
432  goto no_match;
433  }
434  goto match;
435  }
436  } else {
437  if (dataat < buffer_len) {
438  SCLogDebug("absolute isdataat match");
439  if (id->flags & ISDATAAT_NEGATED) {
440  if ((id->flags & ISDATAAT_OFFSET_VAR) == 0) {
441  goto no_match_discontinue;
442  }
443  goto no_match;
444  }
445  goto match;
446  } else {
447  SCLogDebug("absolute isdataat mismatch, id->isdataat %"PRIu32", buffer_len %"PRIu32"", dataat, buffer_len);
448  if (id->flags & ISDATAAT_NEGATED)
449  goto match;
450  if ((id->flags & ISDATAAT_OFFSET_VAR) == 0) {
451  goto no_match_discontinue;
452  }
453  goto no_match;
454  }
455  }
456 
457  } else if (smd->type == DETECT_PCRE) {
458  SCLogDebug("inspecting pcre");
459  const DetectPcreData *pe = (const DetectPcreData *)smd->ctx;
460  uint32_t prev_buffer_offset = det_ctx->buffer_offset;
461  uint32_t prev_offset = 0;
462 
463  det_ctx->pcre_match_start_offset = 0;
464  do {
465  int r = DetectPcrePayloadMatch(det_ctx, s, smd, p, f, buffer, buffer_len);
466  if (r == 0) {
467  goto no_match;
468  }
469  if (!(pe->flags & DETECT_PCRE_RELATIVE_NEXT)) {
470  SCLogDebug("no relative match coming up, so this is a match");
471  goto match;
472  }
473  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
474 
475  /* save it, in case we need to do a pcre match once again */
476  prev_offset = det_ctx->pcre_match_start_offset;
477 
478  /* see if the next payload keywords match. If not, we will
479  * search for another occurrence of this pcre and see
480  * if the others match, until we run out of matches */
481  r = DetectEngineContentInspectionInternal(det_ctx, ctx, s, smd + 1, p, f, buffer,
482  buffer_len, stream_start_offset, flags, inspection_mode);
483  if (r == 1) {
484  SCReturnInt(1);
485  } else if (r == -1) {
486  SCReturnInt(-1);
487  }
488 
489  if (prev_offset == 0) {
490  // This happens for negated PCRE
491  // We do not search for another occurrence of this pcre
492  SCReturnInt(0);
493  }
494  det_ctx->buffer_offset = prev_buffer_offset;
495  det_ctx->pcre_match_start_offset = prev_offset;
496  } while (1);
497 
498  } else if (smd->type == DETECT_ENTROPY) {
499  if (!DetectEntropyDoMatch(det_ctx, s, smd->ctx, f, buffer, buffer_len)) {
500  goto no_match;
501  }
502  goto match;
503  } else if (smd->type == DETECT_BYTETEST) {
504  const DetectBytetestData *btd = (const DetectBytetestData *)smd->ctx;
505  uint16_t btflags = btd->flags;
506  int32_t offset = btd->offset;
507  uint64_t value = btd->value;
508  int32_t nbytes = btd->nbytes;
509  if (btflags & DETECT_BYTETEST_OFFSET_VAR) {
510  // This cast is wrong if a 64-bit value was extracted
511  offset = (int32_t)det_ctx->byte_values[offset];
512  }
513  if (btflags & DETECT_BYTETEST_VALUE_VAR) {
514  value = det_ctx->byte_values[value];
515  }
516  if (btflags & DETECT_BYTETEST_NBYTES_VAR) {
517  // This cast is wrong if a 64-bit value was extracted
518  nbytes = (int32_t)det_ctx->byte_values[nbytes];
519  }
520 
521  /* if we have dce enabled we will have to use the endianness
522  * specified by the dce header */
523  if (btflags & DETECT_BYTETEST_DCE) {
524  /* enable the endianness flag temporarily. once we are done
525  * processing we reset the flags to the original value*/
526  btflags |= ((flags & DETECT_CI_FLAGS_DCE_LE) ?
528  }
529 
530  if (DetectBytetestDoMatch(det_ctx, s, smd->ctx, buffer, buffer_len, btflags, offset, nbytes,
531  value) != 1) {
532  goto no_match;
533  }
534 
535  goto match;
536 
537  } else if (smd->type == DETECT_BYTEJUMP) {
538  const DetectBytejumpData *bjd = (const DetectBytejumpData *)smd->ctx;
539  uint16_t bjflags = bjd->flags;
540  int32_t offset = bjd->offset;
541  int32_t nbytes;
542 
543  if (bjflags & DETECT_BYTEJUMP_OFFSET_VAR) {
544  // This cast is wrong if a 64-bit value was extracted
545  offset = (int32_t)det_ctx->byte_values[offset];
546  SCLogDebug("[BJ] using offset value %d", offset);
547  }
548 
549  if (bjflags & DETECT_BYTEJUMP_NBYTES_VAR) {
550  // This cast is wrong if a 64-bit value was extracted
551  nbytes = (int32_t)det_ctx->byte_values[bjd->nbytes];
552  SCLogDebug("[BJ] using nbytes value %d [index %d]", nbytes, bjd->nbytes);
553  } else {
554  nbytes = bjd->nbytes;
555  SCLogDebug("[BJ] using nbytes value %d [index n/a]", nbytes);
556  }
557 
558  /* if we have dce enabled we will have to use the endianness
559  * specified by the dce header */
560  if (bjflags & DETECT_BYTEJUMP_DCE) {
561  /* enable the endianness flag temporarily. once we are done
562  * processing we reset the flags to the original value*/
563  bjflags |= ((flags & DETECT_CI_FLAGS_DCE_LE) ?
565  }
566 
568  det_ctx, s, smd->ctx, buffer, buffer_len, bjflags, nbytes, offset)) {
569  goto no_match;
570  }
571 
572  goto match;
573 
574  } else if (smd->type == DETECT_BYTE_EXTRACT) {
575 
576  const SCDetectByteExtractData *bed = (const SCDetectByteExtractData *)smd->ctx;
577  uint8_t endian = bed->endian;
578 
579  /* if we have dce enabled we will have to use the endianness
580  * specified by the dce header */
581  if ((bed->flags & DETECT_BYTE_EXTRACT_FLAG_ENDIAN) && endian == EndianDCE &&
582  flags & (DETECT_CI_FLAGS_DCE_LE | DETECT_CI_FLAGS_DCE_BE)) {
583 
584  /* enable the endianness flag temporarily. once we are done
585  * processing we reset the flags to the original value*/
586  endian |= ((flags & DETECT_CI_FLAGS_DCE_LE) ? LittleEndian : BigEndian);
587  }
588 
589  if (DetectByteExtractDoMatch(det_ctx, smd, s, buffer, buffer_len,
590  &det_ctx->byte_values[bed->local_id], endian) != 1) {
591  goto no_match;
592  }
593 
594  SCLogDebug("[BE] Fetched value for index %d: %"PRIu64,
595  bed->local_id, det_ctx->byte_values[bed->local_id]);
596  goto match;
597 
598  } else if (smd->type == DETECT_BYTEMATH) {
599 
600  const DetectByteMathData *bmd = (const DetectByteMathData *)smd->ctx;
601  uint8_t endian = bmd->endian;
602 
603  /* if we have dce enabled we will have to use the endianness
604  * specified by the dce header */
605  if ((bmd->flags & DETECT_BYTEMATH_FLAG_ENDIAN) && endian == (int)EndianDCE &&
606  flags & (DETECT_CI_FLAGS_DCE_LE | DETECT_CI_FLAGS_DCE_BE)) {
607  /* enable the endianness flag temporarily. once we are done
608  * processing we reset the flags to the original value*/
609  endian = (uint8_t)((flags & DETECT_CI_FLAGS_DCE_LE) ? LittleEndian : BigEndian);
610  }
611  uint64_t rvalue;
612  if (bmd->flags & DETECT_BYTEMATH_FLAG_RVALUE_VAR) {
613  rvalue = det_ctx->byte_values[bmd->rvalue];
614  } else {
615  rvalue = bmd->rvalue;
616  }
617 
618  uint8_t nbytes;
619  if (bmd->flags & DETECT_BYTEMATH_FLAG_NBYTES_VAR) {
620  nbytes = (uint8_t)det_ctx->byte_values[bmd->nbytes];
621  } else {
622  nbytes = bmd->nbytes;
623  }
624 
625  if (DetectByteMathDoMatch(det_ctx, bmd, s, buffer, buffer_len, nbytes, rvalue,
626  &det_ctx->byte_values[bmd->local_id], endian) != 1) {
627  goto no_match;
628  }
629 
630  SCLogDebug("[BM] Fetched value for index %d: %"PRIu64,
631  bmd->local_id, det_ctx->byte_values[bmd->local_id]);
632  goto match;
633 
634  } else if (smd->type == DETECT_BSIZE) {
635 
636  const bool eof = (flags & DETECT_CI_FLAGS_END);
637  const uint64_t data_size = buffer_len + stream_start_offset;
638  int r = DetectBsizeMatch(smd->ctx, data_size, eof);
639  if (r < 0) {
640  goto no_match_discontinue;
641  } else if (r == 0) {
642  goto no_match;
643  }
644  goto match;
645 
646  } else if (smd->type == DETECT_DATASET) {
647 
648  //PrintRawDataFp(stdout, buffer, buffer_len);
649  const DetectDatasetData *sd = (const DetectDatasetData *) smd->ctx;
650  int r = DetectDatasetBufferMatch(det_ctx, sd, buffer, buffer_len); //TODO buffer offset?
651  if (r == 1) {
652  goto match;
653  }
654  goto no_match_discontinue;
655 
656  } else if (smd->type == DETECT_DATAREP) {
657 
658  //PrintRawDataFp(stdout, buffer, buffer_len);
659  const DetectDatarepData *sd = (const DetectDatarepData *) smd->ctx;
660  int r = DetectDatarepBufferMatch(det_ctx, sd, buffer, buffer_len); //TODO buffer offset?
661  if (r == 1) {
662  goto match;
663  }
664  goto no_match_discontinue;
665 
666  } else if (smd->type == DETECT_URILEN) {
667  SCLogDebug("inspecting uri len");
668 
669  int r;
670  const DetectUrilenData *urilend = (const DetectUrilenData *)smd->ctx;
671  if (buffer_len > UINT16_MAX) {
672  r = DetectU16Match(UINT16_MAX, &urilend->du16);
673  } else {
674  r = DetectU16Match((uint16_t)buffer_len, &urilend->du16);
675  }
676 
677  if (r == 1) {
678  goto match;
679  }
680  goto no_match_discontinue;
681  } else if (smd->type == DETECT_LUA) {
682  SCLogDebug("lua starting");
683 
684  if (DetectLuaMatchBuffer(det_ctx, s, smd, buffer, buffer_len,
685  det_ctx->buffer_offset, f) != 1)
686  {
687  SCLogDebug("lua no_match");
688  goto no_match;
689  }
690  SCLogDebug("lua match");
691  goto match;
692  } else if (smd->type == DETECT_BASE64_DECODE) {
693  if (DetectBase64DecodeDoMatch(det_ctx, s, smd, buffer, buffer_len)) {
694  if (s->sm_arrays[DETECT_SM_LIST_BASE64_DATA] != NULL) {
695  if (det_ctx->base64_decoded_len) {
696  /* reset buffer offset, as we treat this like a new buffer */
697  det_ctx->buffer_offset = 0;
698  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
699  int r = DetectEngineContentInspectionInternal(det_ctx, ctx, s,
701  det_ctx->base64_decoded, det_ctx->base64_decoded_len, 0,
703  if (r == 1) {
704  /* Base64 is a terminal list. */
705  goto final_match;
706  }
707  }
708  }
709  }
710  } else if (smd->type == DETECT_ASN1) {
711  if (!DetectAsn1Match(smd, buffer, buffer_len, det_ctx->buffer_offset)) {
712  SCLogDebug("asn1 no_match");
713  goto no_match;
714  }
715  SCLogDebug("asn1 match");
716  goto match;
717  } else {
718  SCLogDebug("sm->type %u", smd->type);
719 #ifdef DEBUG
720  BUG_ON(1);
721 #endif
722  }
723 
724 no_match:
725  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
726  SCReturnInt(0);
727 
728 no_match_discontinue:
729  KEYWORD_PROFILING_END(det_ctx, smd->type, 0);
730  SCReturnInt(-1);
731 
732 match:
733  /* this sigmatch matched, inspect the next one. If it was the last,
734  * the buffer portion of the signature matched. */
735  if (!smd->is_last) {
736  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
737  int r = DetectEngineContentInspectionInternal(det_ctx, ctx, s, smd + 1, p, f, buffer,
738  buffer_len, stream_start_offset, flags, inspection_mode);
739  SCReturnInt(r);
740  }
741 final_match:
742  KEYWORD_PROFILING_END(det_ctx, smd->type, 1);
743  SCReturnInt(1);
744 }
745 
746 /** \brief wrapper around DetectEngineContentInspectionInternal to return true/false only
747  *
748  * \param smd sigmatches to evaluate
749  */
751  const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *buffer,
752  const uint32_t buffer_len, const uint64_t stream_start_offset, const uint8_t flags,
753  const enum DetectContentInspectionType inspection_mode)
754 {
755  struct DetectEngineContentInspectionCtx ctx = { .recursion.count = 0,
756  .recursion.limit = de_ctx->inspection_recursion_limit };
757  det_ctx->buffer_offset = 0;
758 
759  int r = DetectEngineContentInspectionInternal(det_ctx, &ctx, s, smd, p, f, buffer, buffer_len,
760  stream_start_offset, flags, inspection_mode);
761 #ifdef UNITTESTS
762  ut_inspection_recursion_counter = ctx.recursion.count;
763 #endif
764  return (r == 1);
765 }
766 
767 /** \brief wrapper around DetectEngineContentInspectionInternal to return true/false only
768  *
769  * \param smd sigmatches to evaluate
770  */
772  const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const InspectionBuffer *b,
773  const enum DetectContentInspectionType inspection_mode)
774 {
775  struct DetectEngineContentInspectionCtx ctx = { .recursion.count = 0,
776  .recursion.limit = de_ctx->inspection_recursion_limit };
777 
778  det_ctx->buffer_offset = 0;
779 
780  int r = DetectEngineContentInspectionInternal(det_ctx, &ctx, s, smd, p, f, b->inspect,
781  b->inspect_len, b->inspect_offset, b->flags, inspection_mode);
782 #ifdef UNITTESTS
783  ut_inspection_recursion_counter = ctx.recursion.count;
784 #endif
785  return (r == 1);
786 }
787 
789 {
790  // we will match on NULL buffers there is one absent
791  bool absent_data = false;
792  while (1) {
793  if (smd->type == DETECT_ABSENT) {
794  absent_data = true;
795  break;
796  }
797  if (smd->is_last) {
798  break;
799  }
800  // smd does not get reused after this loop
801  smd++;
802  }
803  return absent_data;
804 }
805 
806 #ifdef UNITTESTS
808 #endif
DetectEngineContentInspectionCtx
Definition: detect-engine-content-inspection.c:71
DetectEngineThreadCtx_::byte_values
uint64_t * byte_values
Definition: detect.h:1351
DetectAsn1Match
bool DetectAsn1Match(const SigMatchData *smd, const uint8_t *buffer, const uint32_t buffer_len, const uint32_t offset)
Definition: detect-asn1.c:57
DetectContentData_::offset
uint16_t offset
Definition: detect-content.h:107
DetectBytetestData_::flags
uint16_t flags
Definition: detect-bytetest.h:58
DetectDatasetData_
Definition: detect-dataset.h:30
detect-engine-uint.h
DETECT_BYTETEST_VALUE_VAR
#define DETECT_BYTETEST_VALUE_VAR
Definition: detect-bytetest.h:49
detect-content.h
DetectEngineThreadCtx_::buffer_offset
uint32_t buffer_offset
Definition: detect.h:1340
detect-engine.h
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
detect-entropy.h
DETECT_CONTENT_DISTANCE_VAR
#define DETECT_CONTENT_DISTANCE_VAR
Definition: detect-content.h:47
DetectPcrePayloadMatch
int DetectPcrePayloadMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *payload, uint32_t payload_len)
Match a regex on a single payload.
Definition: detect-pcre.c:222
DETECT_BYTEJUMP
@ DETECT_BYTEJUMP
Definition: detect-engine-register.h:92
ISDATAAT_OFFSET_VAR
#define ISDATAAT_OFFSET_VAR
Definition: detect-isdataat.h:30
DETECT_ABSENT
@ DETECT_ABSENT
Definition: detect-engine-register.h:104
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
DetectContentData_::within
int32_t within
Definition: detect-content.h:109
DetectBase64DecodeDoMatch
int DetectBase64DecodeDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, const uint8_t *payload, uint32_t payload_len)
Definition: detect-base64-decode.c:66
DetectBytetestDoMatch
int DetectBytetestDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint16_t flags, int32_t offset, int32_t nbytes, uint64_t value)
Bytetest detection code.
Definition: detect-bytetest.c:155
DetectIsdataatData_::flags
uint8_t flags
Definition: detect-isdataat.h:34
DETECT_BYTEJUMP_LITTLE
#define DETECT_BYTEJUMP_LITTLE
Definition: detect-bytejump.h:35
DETECT_CONTENT
@ DETECT_CONTENT
Definition: detect-engine-register.h:78
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
detect-isdataat.h
DETECT_BYTEJUMP_NBYTES_VAR
#define DETECT_BYTEJUMP_NBYTES_VAR
Definition: detect-bytejump.h:43
SigMatchData_::is_last
bool is_last
Definition: detect.h:371
util-lua.h
DetectDatarepData_
Definition: detect-datarep.h:36
SigMatchData_::ctx
SigMatchCtx * ctx
Definition: detect.h:372
detect-bsize.h
InspectionBuffer
Definition: detect-engine-inspect-buffer.h:34
Flow_
Flow data structure.
Definition: flow.h:359
ctx
struct Thresholds ctx
DetectEngineCtx_::inspection_recursion_limit
int inspection_recursion_limit
Definition: detect.h:1040
DetectEngineCtx_
main detection engine ctx
Definition: detect.h:995
DETECT_DATAREP
@ DETECT_DATAREP
Definition: detect-engine-register.h:96
DETECT_ENTROPY
@ DETECT_ENTROPY
Definition: detect-engine-register.h:105
DETECT_BYTETEST_DCE
#define DETECT_BYTETEST_DCE
Definition: detect-bytetest.h:47
DETECT_CONTENT_DEPTH_VAR
#define DETECT_CONTENT_DEPTH_VAR
Definition: detect-content.h:46
detect-lua.h
rust.h
DetectContentInspectionMatchOnAbsentBuffer
bool DetectContentInspectionMatchOnAbsentBuffer(const SigMatchData *smd)
tells if we should match on absent buffer, because there is an absent keyword being used
Definition: detect-engine-content-inspection.c:788
DETECT_BYTEJUMP_DCE
#define DETECT_BYTEJUMP_DCE
Definition: detect-bytejump.h:40
DetectEngineThreadCtx_::spm_thread_ctx
SpmThreadCtx * spm_thread_ctx
Definition: detect.h:1348
InspectionBuffer::flags
uint8_t flags
Definition: detect-engine-inspect-buffer.h:39
DetectContentInspectionType
DetectContentInspectionType
Definition: detect-engine-content-inspection.h:31
p
Packet * p
Definition: fuzz_dataset.c:30
Signature_::sm_arrays
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:759
DetectIsdataatData_
Definition: detect-isdataat.h:32
DetectContentData_
Definition: detect-content.h:93
DetectPcreData_::flags
uint16_t flags
Definition: detect-pcre.h:52
DetectBytetestData_::nbytes
uint8_t nbytes
Definition: detect-bytetest.h:54
DetectBytetestData_
Definition: detect-bytetest.h:53
SigMatchData_
Data needed for Match()
Definition: detect.h:369
detect-pcre.h
KEYWORD_PROFILING_START
#define KEYWORD_PROFILING_START
Definition: util-profiling.h:50
SigMatchData_::type
uint16_t type
Definition: detect.h:370
DetectBytejumpData_
Definition: detect-bytejump.h:47
DetectEngineContentInspectionCtx::recursion
struct DetectEngineContentInspectionCtx::@50 recursion
DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_PAYLOAD
Definition: detect-engine-content-inspection.h:32
DETECT_ASN1
@ DETECT_ASN1
Definition: detect-engine-register.h:100
DetectBytejumpData_::offset
int32_t offset
Definition: detect-bytejump.h:51
util-unittest-helper.h
detect-asn1.h
KEYWORD_PROFILING_END
#define KEYWORD_PROFILING_END(ctx, type, m)
Definition: util-profiling.h:64
detect-base64-data.h
DetectByteExtractDoMatch
int DetectByteExtractDoMatch(DetectEngineThreadCtx *det_ctx, const SigMatchData *smd, const Signature *s, const uint8_t *payload, uint32_t payload_len, uint64_t *value, uint8_t endian)
Definition: detect-byte-extract.c:81
DetectReplaceAddToList
DetectReplaceList * DetectReplaceAddToList(DetectReplaceList *replist, uint8_t *found, const DetectContentData *cd)
Definition: detect-replace.c:170
decode.h
util-debug.h
DETECT_CONTENT_ENDS_WITH
#define DETECT_CONTENT_ENDS_WITH
Definition: detect-content.h:42
DETECT_CONTENT_DISTANCE
#define DETECT_CONTENT_DISTANCE
Definition: detect-content.h:30
de_ctx
DetectEngineCtx * de_ctx
Definition: fuzz_siginit.c:22
DetectEntropyDoMatch
bool DetectEntropyDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchCtx *ctx, Flow *flow, const uint8_t *buffer, const uint32_t buffer_len)
Definition: detect-entropy.c:86
DetectBsizeMatch
int DetectBsizeMatch(const SigMatchCtx *ctx, const uint64_t buffer_size, bool eof)
bsize match function
Definition: detect-bsize.c:121
DetectEngineThreadCtx_
Definition: detect.h:1316
DETECT_BSIZE
@ DETECT_BSIZE
Definition: detect-engine-register.h:99
DETECT_SM_LIST_BASE64_DATA
@ DETECT_SM_LIST_BASE64_DATA
Definition: detect.h:125
DETECT_LUA
@ DETECT_LUA
Definition: detect-engine-register.h:101
DETECT_CONTENT_DEPTH
#define DETECT_CONTENT_DEPTH
Definition: detect-content.h:33
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:284
detect.h
DETECT_CONTENT_IS_SINGLE
#define DETECT_CONTENT_IS_SINGLE(c)
Definition: detect-content.h:68
DETECT_CONTENT_NEGATED
#define DETECT_CONTENT_NEGATED
Definition: detect-content.h:40
InspectionBuffer::inspect_offset
uint64_t inspect_offset
Definition: detect-engine-inspect-buffer.h:36
DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE
Definition: detect-engine-content-inspection.h:36
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
DetectContentData_::id
PatIntId id
Definition: detect-content.h:105
DetectLuaMatchBuffer
int DetectLuaMatchBuffer(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, const uint8_t *buffer, uint32_t buffer_len, uint32_t offset, Flow *f)
Definition: detect-lua.c:237
DetectEngineContentInspection
bool DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const uint8_t *buffer, const uint32_t buffer_len, const uint64_t stream_start_offset, const uint8_t flags, const enum DetectContentInspectionType inspection_mode)
wrapper around DetectEngineContentInspectionInternal to return true/false only
Definition: detect-engine-content-inspection.c:750
DetectBytejumpDoMatch
bool DetectBytejumpDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchCtx *ctx, const uint8_t *payload, uint32_t payload_len, uint16_t flags, int32_t nbytes, int32_t offset)
Byte jump match function.
Definition: detect-bytejump.c:138
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:322
DetectEngineThreadCtx_::base64_decoded_len
int base64_decoded_len
Definition: detect.h:1399
util-profiling.h
DETECT_BYTETEST_OFFSET_VAR
#define DETECT_BYTETEST_OFFSET_VAR
Definition: detect-bytetest.h:50
DetectContentData_::depth
uint16_t depth
Definition: detect-content.h:106
SpmScan
uint8_t * SpmScan(const SpmCtx *ctx, SpmThreadCtx *thread_ctx, const uint8_t *haystack, uint32_t haystack_len)
Definition: util-spm.c:202
Packet_
Definition: decode.h:516
ISDATAAT_RELATIVE
#define ISDATAAT_RELATIVE
Definition: detect-isdataat.h:27
detect-bytejump.h
DETECT_BYTETEST_NBYTES_VAR
#define DETECT_BYTETEST_NBYTES_VAR
Definition: detect-bytetest.h:51
DETECT_CI_FLAGS_END
#define DETECT_CI_FLAGS_END
Definition: detect-engine-content-inspection.h:42
DetectContentData_::flags
uint32_t flags
Definition: detect-content.h:104
DETECT_URILEN
@ DETECT_URILEN
Definition: detect-engine-register.h:103
detect-replace.h
DETECT_PCRE
@ DETECT_PCRE
Definition: detect-engine-register.h:80
detect-engine-content-inspection.h
DETECT_CONTENT_WITHIN_VAR
#define DETECT_CONTENT_WITHIN_VAR
Definition: detect-content.h:48
DetectDatasetBufferMatch
int DetectDatasetBufferMatch(DetectEngineThreadCtx *det_ctx, const DetectDatasetData *sd, const uint8_t *data, const uint32_t data_len)
Definition: detect-dataset.c:165
DetectDatarepBufferMatch
int DetectDatarepBufferMatch(DetectEngineThreadCtx *det_ctx, const DetectDatarepData *sd, const uint8_t *data, const uint32_t data_len)
Definition: detect-datarep.c:70
DETECT_BYTETEST
@ DETECT_BYTETEST
Definition: detect-engine-register.h:91
DetectByteMathDoMatch
int DetectByteMathDoMatch(DetectEngineThreadCtx *det_ctx, const DetectByteMathData *data, const Signature *s, const uint8_t *payload, const uint32_t payload_len, uint8_t nbytes, uint64_t rvalue, uint64_t *value, uint8_t endian)
Definition: detect-bytemath.c:89
DETECT_CI_FLAGS_SINGLE
#define DETECT_CI_FLAGS_SINGLE
Definition: detect-engine-content-inspection.h:50
DetectU16Match
int DetectU16Match(const uint16_t parg, const DetectUintData_u16 *du16)
Definition: detect-engine-uint.c:105
flags
uint8_t flags
Definition: decode-gre.h:0
suricata-common.h
DetectAbsentData_
Definition: detect-isdataat.h:37
detect-byte-extract.h
DetectContentData_::distance
int32_t distance
Definition: detect-content.h:108
DetectBytejumpData_::nbytes
uint8_t nbytes
Definition: detect-bytejump.h:48
ut_inspection_recursion_counter
thread_local uint32_t ut_inspection_recursion_counter
Definition: detect-engine-content-inspection.c:68
DETECT_CONTENT_WITHIN_NEXT
#define DETECT_CONTENT_WITHIN_NEXT
Definition: detect-content.h:57
util-spm.h
DetectContentData_::content
uint8_t * content
Definition: detect-content.h:94
detect-dataset.h
DetectEngineContentInspectionCtx::limit
const uint32_t limit
Definition: detect-engine-content-inspection.c:74
util-validate.h
detect-base64-decode.h
ISDATAAT_NEGATED
#define ISDATAAT_NEGATED
Definition: detect-isdataat.h:29
DetectContentData_::spm_ctx
SpmCtx * spm_ctx
Definition: detect-content.h:111
InspectionBuffer::inspect_len
uint32_t inspect_len
Definition: detect-engine-inspect-buffer.h:37
DetectEngineThreadCtx_::pcre_match_start_offset
uint32_t pcre_match_start_offset
Definition: detect.h:1344
InspectionBuffer::inspect
const uint8_t * inspect
Definition: detect-engine-inspect-buffer.h:35
detect-datarep.h
DETECT_BYTE_EXTRACT
@ DETECT_BYTE_EXTRACT
Definition: detect-engine-register.h:94
detect-parse.h
Signature_
Signature container.
Definition: detect.h:692
DETECT_ISDATAAT
@ DETECT_ISDATAAT
Definition: detect-engine-register.h:102
DetectBytetestData_::offset
int32_t offset
Definition: detect-bytetest.h:60
DetectIsdataatData_::dataat
uint16_t dataat
Definition: detect-isdataat.h:33
DetectEngineThreadCtx_::base64_decoded
uint8_t * base64_decoded
Definition: detect.h:1398
DETECT_PCRE_RELATIVE_NEXT
#define DETECT_PCRE_RELATIVE_NEXT
Definition: detect-pcre.h:34
detect-urilen.h
suricata.h
DetectPcreData_
Definition: detect-pcre.h:48
DetectContentData_::content_len
uint16_t content_len
Definition: detect-content.h:95
DETECT_BYTEMATH
@ DETECT_BYTEMATH
Definition: detect-engine-register.h:93
DETECT_BASE64_DECODE
@ DETECT_BASE64_DECODE
Definition: detect-engine-register.h:97
detect-uricontent.h
DetectEngineContentInspectionBuffer
bool DetectEngineContentInspectionBuffer(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, const InspectionBuffer *b, const enum DetectContentInspectionType inspection_mode)
wrapper around DetectEngineContentInspectionInternal to return true/false only
Definition: detect-engine-content-inspection.c:771
DetectEngineThreadCtx_::replist
DetectReplaceList * replist
Definition: detect.h:1432
DetectEngineContentInspectionCtx::count
uint32_t count
Definition: detect-engine-content-inspection.c:73
DETECT_CONTENT_REPLACE
#define DETECT_CONTENT_REPLACE
Definition: detect-content.h:51
DetectAbsentData_::or_else
bool or_else
Definition: detect-isdataat.h:39
detect-engine-content-inspection.c
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:288
DETECT_BYTETEST_LITTLE
#define DETECT_BYTETEST_LITTLE
Definition: detect-bytetest.h:43
DETECT_DATASET
@ DETECT_DATASET
Definition: detect-engine-register.h:95
DetectBytetestData_::value
uint64_t value
Definition: detect-bytetest.h:62
DETECT_CONTENT_WITHIN
#define DETECT_CONTENT_WITHIN
Definition: detect-content.h:31
DETECT_BYTEJUMP_OFFSET_VAR
#define DETECT_BYTEJUMP_OFFSET_VAR
Definition: detect-bytejump.h:44
DetectBytejumpData_::flags
uint16_t flags
Definition: detect-bytejump.h:50
detect-bytemath.h
DETECT_CONTENT_OFFSET_VAR
#define DETECT_CONTENT_OFFSET_VAR
Definition: detect-content.h:45
detect-bytetest.h
f
Flow f
Definition: fuzz_dataset.c:32