suricata
detect-engine-frame.c
Go to the documentation of this file.
1/* Copyright (C) 2021-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 Victor Julien <victor@inliniac.net>
22 *
23 */
24
25#include "suricata-common.h"
26#include "suricata.h"
27
28#include "app-layer-parser.h"
29#include "app-layer-frames.h"
30
31#include "detect-engine.h"
34#include "detect-engine-mpm.h"
35#include "detect-engine-frame.h"
36
37#include "stream-tcp.h"
38
39#include "util-profiling.h"
40#include "util-validate.h"
41#include "util-print.h"
42
44 // shared between prefilter and inspect
47 const Frame *frame;
49 uint32_t idx; /**< multi buffer idx, incremented for each stream chunk */
50
51 // inspection only
53 const Signature *s;
54 int inspect_result; // DETECT_ENGINE_INSPECT_SIG_MATCH / DETECT_ENGINE_INSPECT_SIG_NO_MATCH
56
57 // prefilter only
59
61};
62
63static bool SetupStreamCallbackData(struct FrameStreamData *dst, const TcpSession *ssn,
64 const TcpStream *stream, DetectEngineThreadCtx *det_ctx,
65 const DetectEngineTransforms *transforms, const Frames *_frames, const Frame *frame,
66 const int list_id, const bool eof);
67
68static bool BufferSetup(struct FrameStreamData *fsd, InspectionBuffer *buffer, const uint8_t *input,
69 const uint32_t input_len, const uint64_t input_offset);
70static void BufferSetupUdp(DetectEngineThreadCtx *det_ctx, InspectionBuffer *buffer,
71 const Frame *frame, const Packet *p, const DetectEngineTransforms *transforms);
72
74 const Frames *frames, const Frame *frame, const AppProto alproto)
75{
76 SCLogDebug("pcap_cnt %" PRIu64, p->pcap_cnt);
77 PrefilterEngine *engine = sgh->frame_engines;
78 do {
79 if ((engine->alproto == alproto || engine->alproto == ALPROTO_UNKNOWN) &&
80 (engine->ctx.frame_type == frame->type ||
81 engine->ctx.frame_type == FRAME_ANY_TYPE)) {
82 SCLogDebug("frame %p engine %p", frame, engine);
84 engine->cb.PrefilterFrame(det_ctx, engine->pectx, p, frames, frame);
85 PREFILTER_PROFILING_END(det_ctx, engine->gid);
86 }
87 if (engine->is_last)
88 break;
89 engine++;
90 } while (1);
91}
92
93/* generic mpm for frame engines */
94
95// TODO same as Generic?
101
102static int FrameStreamDataPrefilterFunc(
103 void *cb_data, const uint8_t *input, const uint32_t input_len, const uint64_t input_offset)
104{
105 struct FrameStreamData *fsd = cb_data;
106 SCLogDebug("prefilter: fsd %p { det_ctx:%p, transforms:%p, frame:%p, list_id:%d, idx:%u, "
107 "data_offset:%" PRIu64 "}, input: %p, input_len:%u, input_offset:%" PRIu64,
108 fsd, fsd->det_ctx, fsd->transforms, fsd->frame, fsd->list_id, fsd->idx,
109 fsd->requested_stream_offset, input, input_len, input_offset);
110 // PrintRawDataFp(stdout, input, input_len);
111
112 InspectionBuffer *buffer =
114 if (buffer == NULL) {
115 return 0;
116 }
117 SCLogDebug("buffer %p idx %u", buffer, fsd->idx);
118
119 const int more_chunks = BufferSetup(fsd, buffer, input, input_len, input_offset);
120
121 const uint32_t data_len = buffer->inspect_len;
122 const uint8_t *data = buffer->inspect;
124 const MpmCtx *mpm_ctx = fsd->mpm_ctx;
125
126 if (data != NULL && data_len >= mpm_ctx->minlen) {
127 // PrintRawDataFp(stdout, data, data_len);
128
130 mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, data, data_len);
131 SCLogDebug("det_ctx->pmq.rule_id_array_cnt %u", det_ctx->pmq.rule_id_array_cnt);
133 }
134 return more_chunks;
135}
136
137/** \brief Generic Mpm prefilter callback
138 *
139 * \param det_ctx detection engine thread ctx
140 * \param frames container for the frames
141 * \param frame frame to inspect
142 * \param pectx inspection context
143 */
144static void PrefilterMpmFrame(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
145 const Frames *frames, const Frame *frame)
146{
147 SCEnter();
148
149 const PrefilterMpmFrameCtx *ctx = (const PrefilterMpmFrameCtx *)pectx;
150 const MpmCtx *mpm_ctx = ctx->mpm_ctx;
151
152 SCLogDebug("packet:%" PRIu64 ", prefilter running on list %d -> frame field type %u",
153 p->pcap_cnt, ctx->list_id, frame->type);
154 if (p->proto == IPPROTO_UDP) {
155 // TODO can we use single here? Could it conflict with TCP?
157 if (buffer == NULL)
158 return;
160 if (frame->offset >= p->payload_len)
161 return;
162
163 BufferSetupUdp(det_ctx, buffer, frame, p, ctx->transforms);
164 const uint32_t data_len = buffer->inspect_len;
165 const uint8_t *data = buffer->inspect;
166
167 // PrintRawDataFp(stdout, data, data_len);
168
169 if (data != NULL && data_len >= mpm_ctx->minlen) {
171 mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, data, data_len);
172 SCLogDebug("det_ctx->pmq.rule_id_array_cnt %u", det_ctx->pmq.rule_id_array_cnt);
174 }
175 } else if (p->proto == IPPROTO_TCP) {
177 TcpSession *ssn = p->flow->protoctx;
178 TcpStream *stream;
179 if (PKT_IS_TOSERVER(p)) {
180 stream = &ssn->client;
181 } else {
182 stream = &ssn->server;
183 }
184 const bool eof = ssn->state == TCP_CLOSED || PKT_IS_PSEUDOPKT(p);
185
186 struct FrameStreamData fsd;
187 memset(&fsd, 0, sizeof(fsd));
188 fsd.mpm_ctx = mpm_ctx;
189
190 if (SetupStreamCallbackData(&fsd, ssn, stream, det_ctx, ctx->transforms, frames, frame,
191 ctx->list_id, eof)) {
192 StreamReassembleForFrame(ssn, stream, FrameStreamDataPrefilterFunc, &fsd,
193 fsd.requested_stream_offset, eof);
194 }
195 } else {
197 }
198 SCLogDebug("packet:%" PRIu64
199 ", prefilter done running on list %d -> frame field type %u; have %u matches",
201}
202
203static void PrefilterMpmFrameFree(void *ptr)
204{
205 SCFree(ptr);
206}
207
209 const DetectBufferMpmRegistry *mpm_reg, int list_id)
210{
211 SCEnter();
212 PrefilterMpmFrameCtx *pectx = SCCalloc(1, sizeof(*pectx));
213 if (pectx == NULL)
214 return -1;
215 pectx->list_id = list_id;
217 pectx->mpm_ctx = mpm_ctx;
218 pectx->transforms = &mpm_reg->transforms;
219
220 int r = PrefilterAppendFrameEngine(de_ctx, sgh, PrefilterMpmFrame, mpm_reg->frame_v1.alproto,
221 mpm_reg->frame_v1.type, pectx, PrefilterMpmFrameFree, mpm_reg->pname);
222 if (r != 0) {
223 SCFree(pectx);
224 }
225 return r;
226}
227
229 Flow *f, Packet *p, const Frames *frames, const Frame *frame)
230{
232
233 SCLogDebug("inspecting rule %u against frame %p/%" PRIi64 "/%s", s->id, frame, frame->id,
235
236 for (DetectEngineFrameInspectionEngine *e = s->frame_inspect; e != NULL; e = e->next) {
237 if (frame->type == e->type) {
238 // TODO check alproto, direction?
239
240 // TODO there should be only one inspect engine for this frame, ever?
241
242 if (e->v1.Callback(det_ctx, e, s, p, frames, frame)) {
243 SCLogDebug("sid %u: e %p Callback returned true", s->id, e);
244 return true;
245 }
246 SCLogDebug("sid %u: e %p Callback returned false", s->id, e);
247 } else {
249 "sid %u: e %p not for frame type %u (want %u)", s->id, e, frame->type, e->type);
250 }
251 }
252 return false;
253}
254
255static void BufferSetupUdp(DetectEngineThreadCtx *det_ctx, InspectionBuffer *buffer,
256 const Frame *frame, const Packet *p, const DetectEngineTransforms *transforms)
257{
258 uint8_t ci_flags = DETECT_CI_FLAGS_START;
259 uint32_t frame_len;
260 if (frame->len == -1) {
261 frame_len = (uint32_t)(p->payload_len - frame->offset);
262 } else {
263 frame_len = (uint32_t)frame->len;
264 }
265 if (frame->offset + frame_len > p->payload_len) {
266 frame_len = (uint32_t)(p->payload_len - frame->offset);
267 } else {
268 ci_flags |= DETECT_CI_FLAGS_END;
269 }
270 const uint8_t *data = p->payload + frame->offset;
271 const uint32_t data_len = frame_len;
272
273 SCLogDebug("packet %" PRIu64 " -> frame %p/%" PRIi64 "/%s offset %" PRIu64
274 " type %u len %" PRIi64,
275 p->pcap_cnt, frame, frame->id,
278
279 InspectionBufferSetupMulti(det_ctx, buffer, transforms, data, data_len);
280 buffer->inspect_offset = 0;
281 buffer->flags = ci_flags;
282}
283
284/** \internal
285 * \brief setup buffer based on frame in UDP payload
286 */
287static int DetectFrameInspectUdp(DetectEngineThreadCtx *det_ctx,
288 const DetectEngineFrameInspectionEngine *engine, const Signature *s,
289 const DetectEngineTransforms *transforms, Packet *p, const Frames *_frames,
290 const Frame *frame, const int list_id)
291{
292 SCLogDebug("packet:%" PRIu64 ", inspect: s:%p s->id:%u, transforms:%p", p->pcap_cnt, s, s->id,
293 transforms);
294
295 // TODO can we use single here? Could it conflict with TCP?
297 if (buffer == NULL)
299
301 if (frame->offset >= p->payload_len)
303
304 if (!buffer->initialized)
305 BufferSetupUdp(det_ctx, buffer, frame, p, transforms);
307 if (buffer->inspect == NULL)
309
310 const bool match = DetectEngineContentInspection(det_ctx->de_ctx, det_ctx, s, engine->smd, p,
311 p->flow, buffer->inspect, buffer->inspect_len, 0, buffer->flags,
313 if (match) {
314 SCLogDebug("match!");
316 } else {
318 }
319}
320
321/**
322 * \retval bool true if callback should run again */
323static bool BufferSetup(struct FrameStreamData *fsd, InspectionBuffer *buffer, const uint8_t *input,
324 const uint32_t input_len, const uint64_t input_offset)
325{
326 const Frame *frame = fsd->frame;
327 /* so: relative to start of stream */
328 const uint64_t so_input_re = input_offset + input_len;
329 const uint64_t so_frame_re =
330 frame->offset + (uint64_t)frame->len; // TODO if eof, set to available data?
331 SCLogDebug("frame offset:%" PRIu64, frame->offset);
332 const uint8_t *data = input;
333 uint8_t ci_flags = 0;
334 uint32_t data_len;
335
336 /* fo: frame offset; offset relative to start of the frame */
337 uint64_t fo_inspect_offset = 0;
338
339 if (frame->offset == 0 && input_offset == 0) {
340 ci_flags |= DETECT_CI_FLAGS_START;
341 SCLogDebug("have frame data start");
342
343 if (frame->len >= 0) {
344 data_len = MIN(input_len, (uint32_t)frame->len);
345 if (data_len == frame->len) {
346 ci_flags |= DETECT_CI_FLAGS_END;
347 SCLogDebug("have frame data end");
348 }
349 } else {
350 data_len = input_len;
351 }
352 } else {
353 const uint64_t so_frame_inspect_offset = frame->inspect_progress + frame->offset;
354 const uint64_t so_inspect_offset = MAX(input_offset, so_frame_inspect_offset);
355 fo_inspect_offset = so_inspect_offset - frame->offset;
356
357 if (frame->offset >= input_offset) {
358 ci_flags |= DETECT_CI_FLAGS_START;
359 SCLogDebug("have frame data start");
360 }
361 if (frame->len >= 0) {
362 if (fo_inspect_offset >= (uint64_t)frame->len) {
363 SCLogDebug("data entirely past frame (%" PRIu64 " > %" PRIi64 ")",
364 fo_inspect_offset, frame->len);
366 return false;
367 }
368
369 /* in: relative to start of input data */
370 DEBUG_VALIDATE_BUG_ON(so_inspect_offset < input_offset);
371 DEBUG_VALIDATE_BUG_ON(so_inspect_offset - input_offset > UINT32_MAX);
372 const uint32_t in_data_offset = (uint32_t)(so_inspect_offset - input_offset);
373 data += in_data_offset;
374
375 uint32_t in_data_excess = 0;
376 if (so_input_re >= so_frame_re) {
377 ci_flags |= DETECT_CI_FLAGS_END;
378 SCLogDebug("have frame data end");
379 DEBUG_VALIDATE_BUG_ON(so_input_re - so_frame_re > UINT32_MAX);
380 in_data_excess = (uint32_t)(so_input_re - so_frame_re);
381 }
382 data_len = input_len - in_data_offset - in_data_excess;
383 } else {
384 /* in: relative to start of input data */
385 DEBUG_VALIDATE_BUG_ON(so_inspect_offset < input_offset);
386 DEBUG_VALIDATE_BUG_ON(so_inspect_offset - input_offset > UINT32_MAX);
387 const uint32_t in_data_offset = (uint32_t)(so_inspect_offset - input_offset);
388 data += in_data_offset;
389 data_len = input_len - in_data_offset;
390 }
391 }
392 // PrintRawDataFp(stdout, data, data_len);
393 SCLogDebug("fsd->transforms %p", fsd->transforms);
394 InspectionBufferSetupMulti(fsd->det_ctx, buffer, fsd->transforms, data, data_len);
395 SCLogDebug("inspect_offset %" PRIu64, fo_inspect_offset);
396 buffer->inspect_offset = fo_inspect_offset;
397 buffer->flags = ci_flags;
398
399 if (frame->len >= 0 && so_input_re >= so_frame_re) {
400 SCLogDebug("have the full frame, we can set progress accordingly (%" PRIu64 " > %" PRIu64
401 ")",
402 so_input_re, so_frame_re);
404 MAX(fo_inspect_offset + data_len, fsd->det_ctx->frame_inspect_progress);
405 } else {
407 MAX(fo_inspect_offset + data_len, fsd->det_ctx->frame_inspect_progress);
408 /* in IPS mode keep a sliding window */
409 const bool ips = StreamTcpInlineMode();
410 if (ips) {
411 if (fsd->det_ctx->frame_inspect_progress < 2500)
413 else
414 fsd->det_ctx->frame_inspect_progress -= 2500;
415 }
416 SCLogDebug("ips %s inspect_progress %" PRIu64, BOOL2STR(ips),
418 }
419
420 /* keep going as long as there is possibly still data for this frame */
421 const bool ret = (frame->len >= 0 && so_input_re >= so_frame_re);
422 SCLogDebug("buffer set up, more to do: %s", BOOL2STR(ret));
423 return ret;
424}
425
426static int FrameStreamDataInspectFunc(
427 void *cb_data, const uint8_t *input, const uint32_t input_len, const uint64_t input_offset)
428{
429 struct FrameStreamData *fsd = cb_data;
430 SCLogDebug("inspect: fsd %p { det_ctx:%p, transforms:%p, s:%p, s->id:%u, frame:%p, list_id:%d, "
431 "idx:%u, "
432 "requested_stream_offset:%" PRIu64
433 "}, input: %p, input_len:%u, input_offset:%" PRIu64,
434 fsd, fsd->det_ctx, fsd->transforms, fsd->s, fsd->s->id, fsd->frame, fsd->list_id,
435 fsd->idx, fsd->requested_stream_offset, input, input_len, input_offset);
436 // PrintRawDataFp(stdout, input, input_len);
437
438 InspectionBuffer *buffer =
440 if (buffer == NULL) {
441 return 0;
442 }
443 SCLogDebug("buffer %p idx %u", buffer, fsd->idx);
444
445 /* if we've not done so already, set up the buffer */
446 int more_chunks = 1;
447 if (!buffer->initialized) {
448 more_chunks = BufferSetup(fsd, buffer, input, input_len, input_offset);
449 }
451 if (buffer->inspect == NULL) {
452 return more_chunks;
453 }
454
455 const uint32_t data_len = buffer->inspect_len;
456 const uint8_t *data = buffer->inspect;
457 const uint64_t data_offset = buffer->inspect_offset;
459
461 const Signature *s = fsd->s;
462 Packet *p = fsd->p;
463
464#ifdef DEBUG
465 const uint8_t ci_flags = buffer->flags;
466 SCLogDebug("frame %p offset %" PRIu64 " type %u len %" PRIi64
467 " ci_flags %02x (start:%s, end:%s)",
468 fsd->frame, fsd->frame->offset, fsd->frame->type, fsd->frame->len, ci_flags,
469 (ci_flags & DETECT_CI_FLAGS_START) ? "true" : "false",
470 (ci_flags & DETECT_CI_FLAGS_END) ? "true" : "false");
471 SCLogDebug("buffer %p offset %" PRIu64 " len %u ci_flags %02x (start:%s, end:%s)", buffer,
472 buffer->inspect_offset, buffer->inspect_len, ci_flags,
473 (ci_flags & DETECT_CI_FLAGS_START) ? "true" : "false",
474 (ci_flags & DETECT_CI_FLAGS_END) ? "true" : "false");
475 // PrintRawDataFp(stdout, data, data_len);
476 // PrintRawDataFp(stdout, data, MIN(64, data_len));
477#endif
478 DEBUG_VALIDATE_BUG_ON(fsd->frame->len > 0 && (int64_t)data_len > fsd->frame->len);
479
480 const bool match = DetectEngineContentInspection(det_ctx->de_ctx, det_ctx, s, engine->smd, p,
481 p->flow, data, data_len, data_offset, buffer->flags,
483 if (match) {
484 SCLogDebug("DETECT_ENGINE_INSPECT_SIG_MATCH");
486 } else {
487 SCLogDebug("DETECT_ENGINE_INSPECT_SIG_NO_MATCH");
488 }
489 return more_chunks;
490}
491
492static bool SetupStreamCallbackData(struct FrameStreamData *dst, const TcpSession *ssn,
494 const DetectEngineTransforms *transforms, const Frames *_frames, const Frame *frame,
495 const int list_id, const bool eof)
496{
497 SCLogDebug("frame %" PRIi64 ", len %" PRIi64 ", offset %" PRIu64 ", inspect_progress %" PRIu64,
499
500 const uint64_t frame_offset = frame->offset;
501 const uint64_t usable = StreamDataRightEdge(stream, eof);
502 if (usable <= frame_offset)
503 return false;
504
505 uint64_t want = frame->inspect_progress;
506 if (frame->len == -1) {
507 if (eof) {
508 want = usable;
509 } else {
510 want += 2500;
511 }
512 } else {
513 /* don't have the full frame yet */
514 if (frame->offset + frame->len > usable) {
515 want += 2500;
516 } else {
517 want = frame->offset + frame->len;
518 }
519 }
520
521 const bool ips = StreamTcpInlineMode();
522
523 const uint64_t have = usable;
524 if (!ips && have < want) {
525 SCLogDebug("wanted %" PRIu64 " bytes, got %" PRIu64, want, have);
526 return false;
527 }
528
529 const uint64_t available_data = usable - STREAM_BASE_OFFSET(stream);
530 SCLogDebug("check inspection for having 2500 bytes: %" PRIu64, available_data);
531 if (!ips && !eof && available_data < 2500 &&
532 (frame->len < 0 || frame->len > (int64_t)available_data)) {
533 SCLogDebug("skip inspection until we have 2500 bytes (have %" PRIu64 ")", available_data);
534 return false;
535 }
536
537 const uint64_t offset =
539
540 dst->det_ctx = det_ctx;
541 dst->transforms = transforms;
542 dst->frame = frame;
543 dst->list_id = list_id;
544 dst->requested_stream_offset = offset;
545 return true;
546}
547
548/**
549 * \brief Do the content inspection & validation for a signature
550 *
551 * \param de_ctx Detection engine context
552 * \param det_ctx Detection engine thread context
553 * \param s Signature to inspect
554 * \param p Packet
555 * \param frame stream frame to inspect
556 *
557 * \retval 0 no match.
558 * \retval 1 match.
559 */
561 const DetectEngineFrameInspectionEngine *engine, const Signature *s, Packet *p,
562 const Frames *frames, const Frame *frame)
563{
564 /* if prefilter didn't already run, we need to consider transformations */
566 if (!engine->mpm) {
567 transforms = engine->v1.transforms;
568 }
569 const int list_id = engine->sm_list;
570 SCLogDebug("running inspect on %d", list_id);
571
572 if (p->proto == IPPROTO_UDP) {
573 return DetectFrameInspectUdp(det_ctx, engine, s, transforms, p, frames, frame, list_id);
574 }
575 DEBUG_VALIDATE_BUG_ON(p->proto != IPPROTO_TCP);
576
577 SCLogDebug("packet:%" PRIu64 ", frame->id:%" PRIu64
578 ", list:%d, transforms:%p, s:%p, s->id:%u, engine:%p",
579 p->pcap_cnt, frame->id, engine->sm_list, engine->v1.transforms, s, s->id, engine);
580
582 TcpSession *ssn = p->flow->protoctx;
583 TcpStream *stream;
584 if (PKT_IS_TOSERVER(p)) {
585 stream = &ssn->client;
586 } else {
587 stream = &ssn->server;
588 }
589 const bool eof = ssn->state == TCP_CLOSED || PKT_IS_PSEUDOPKT(p);
590
591 struct FrameStreamData fsd;
592 memset(&fsd, 0, sizeof(fsd));
593 fsd.inspect_engine = engine;
594 fsd.s = s;
596 fsd.p = p;
597
598 if (!SetupStreamCallbackData(
599 &fsd, ssn, stream, det_ctx, transforms, frames, frame, list_id, eof)) {
601 }
603 ssn, stream, FrameStreamDataInspectFunc, &fsd, fsd.requested_stream_offset, eof);
604
605 return fsd.inspect_result;
606}
uint16_t dst
#define FRAME_ANY_TYPE
const char * AppLayerParserGetFrameNameById(uint8_t ipproto, AppProto alproto, const uint8_t id)
uint16_t AppProto
@ ALPROTO_UNKNOWN
#define PKT_IS_PSEUDOPKT(p)
return 1 if the packet is a pseudo packet
Definition decode.h:1321
#define PKT_IS_TOSERVER(p)
Definition decode.h:238
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
@ DETECT_ENGINE_CONTENT_INSPECTION_MODE_FRAME
#define DETECT_CI_FLAGS_END
#define DETECT_CI_FLAGS_START
bool DetectRunFrameInspectRule(ThreadVars *tv, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f, Packet *p, const Frames *frames, const Frame *frame)
void DetectRunPrefilterFrame(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh, Packet *p, const Frames *frames, const Frame *frame, const AppProto alproto)
int PrefilterGenericMpmFrameRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
int DetectEngineInspectFrameBufferGeneric(DetectEngineThreadCtx *det_ctx, const DetectEngineFrameInspectionEngine *engine, const Signature *s, Packet *p, const Frames *frames, const Frame *frame)
Do the content inspection & validation for a signature.
void InspectionBufferSetupMultiEmpty(InspectionBuffer *buffer)
setup the buffer empty
InspectionBuffer * InspectionBufferMultipleForListGet(DetectEngineThreadCtx *det_ctx, const int list_id, const uint32_t local_id)
for a InspectionBufferMultipleForList get a InspectionBuffer
void InspectionBufferSetupMulti(DetectEngineThreadCtx *det_ctx, InspectionBuffer *buffer, const DetectEngineTransforms *transforms, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
int PrefilterAppendFrameEngine(DetectEngineCtx *de_ctx, SigGroupHead *sgh, PrefilterFrameFn PrefilterFrameFunc, AppProto alproto, uint8_t frame_type, void *pectx, void(*FreeFunc)(void *pectx), const char *name)
#define DETECT_ENGINE_INSPECT_SIG_MATCH
#define DETECT_ENGINE_INSPECT_SIG_NO_MATCH
ThreadVars * tv
DetectEngineCtx * de_ctx
struct Thresholds ctx
@ TCP_CLOSED
#define STREAM_BASE_OFFSET(stream)
uint64_t StreamDataRightEdge(const TcpStream *stream, const bool eof)
int StreamReassembleForFrame(TcpSession *ssn, TcpStream *stream, StreamReassembleRawFunc Callback, void *cb_data, const uint64_t offset, const bool eof)
bool StreamTcpInlineMode(void)
See if stream engine is operating in inline mode.
one time registration of keywords at start up
Definition detect.h:762
struct DetectBufferMpmRegistry_::@98::@102 frame_v1
enum DetectBufferMpmType type
Definition detect.h:770
DetectEngineTransforms transforms
Definition detect.h:775
main detection engine ctx
Definition detect.h:932
struct DetectEngineFrameInspectionEngine::@94 v1
const DetectEngineTransforms * transforms
Definition detect.h:518
MpmThreadCtx mtc
Definition detect.h:1345
uint64_t frame_inspect_progress
Definition detect.h:1322
DetectEngineCtx * de_ctx
Definition detect.h:1364
PrefilterRuleStore pmq
Definition detect.h:1349
Flow data structure.
Definition flow.h:356
uint8_t proto
Definition flow.h:378
AppProto alproto
application level protocol
Definition flow.h:450
void * protoctx
Definition flow.h:441
uint64_t requested_stream_offset
const DetectEngineFrameInspectionEngine * inspect_engine
const DetectEngineTransforms * transforms
const Signature * s
const MpmCtx * mpm_ctx
DetectEngineThreadCtx * det_ctx
int64_t id
uint8_t type
int64_t len
uint64_t offset
uint64_t inspect_progress
uint8_t mpm_type
Definition util-mpm.h:95
uint16_t minlen
Definition util-mpm.h:104
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition util-mpm.h:178
uint64_t pcap_cnt
Definition decode.h:626
struct Flow_ * flow
Definition decode.h:546
uint8_t * payload
Definition decode.h:605
uint16_t payload_len
Definition decode.h:606
uint8_t proto
Definition decode.h:523
union PrefilterEngine_::@113 cb
AppProto alproto
Definition detect.h:1568
union PrefilterEngine_::@112 ctx
uint8_t frame_type
Definition detect.h:1578
PrefilterFrameFn PrefilterFrame
Definition detect.h:1591
uint32_t gid
Definition detect.h:1597
const DetectEngineTransforms * transforms
Container for matching data for a signature group.
Definition detect.h:1629
PrefilterEngine * frame_engines
Definition detect.h:1642
Signature container.
Definition detect.h:668
DetectEngineFrameInspectionEngine * frame_inspect
Definition detect.h:727
uint32_t id
Definition detect.h:713
Per thread variable structure.
Definition threadvars.h:58
#define BUG_ON(x)
#define MIN(x, y)
#define MAX(x, y)
#define SCEnter(...)
Definition util-debug.h:277
#define BOOL2STR(b)
Definition util-debug.h:535
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition util-mpm.c:47
#define PREFILTER_PROFILING_END(ctx, profile_id)
#define PREFILTER_PROFILING_ADD_BYTES(det_ctx, bytes)
#define PREFILTER_PROFILING_START(det_ctx)
uint64_t offset
#define DEBUG_VALIDATE_BUG_ON(exp)