43 if (
unlikely(frame_config == NULL)) {
58 const uint64_t bits = UINT64_MAX;
72 static inline bool FrameConfigTypeIsEnabled(
const AppProto p,
const uint8_t
type)
83 const char *type_name =
"unknown";
86 }
else if (frames != NULL) {
89 SCLogDebug(
"[%s] %p: frame:%p type:%u/%s id:%" PRIi64
" flags:%02x offset:%" PRIu64
90 ", len:%" PRIi64
", inspect_progress:%" PRIu64
", events:%u %u/%u/%u/%u",
91 prefix, frames, frame, frame->
type, type_name, frame->
id, frame->
flags, frame->
offset,
96 #define FrameDebug(prefix, frames, frame)
104 Frame *candidate = NULL;
107 "frames %p cnt %u, looking for last of type %" PRIu8, frames, frames->
cnt, frame_type);
108 for (uint16_t i = 0; i < frames->
cnt; i++) {
111 FrameDebug(
"get_by_id(static)", frames, frame);
112 if (frame->
type == frame_type && frame->
len == -1)
117 FrameDebug(
"get_by_id(dynamic)", frames, frame);
118 if (frame->
type == frame_type && frame->
len == -1)
127 SCLogDebug(
"frames %p cnt %u, looking for %" PRIi64, frames, frames->
cnt,
id);
128 for (uint16_t i = 0; i < frames->
cnt; i++) {
131 FrameDebug(
"get_by_id(static)", frames, frame);
137 FrameDebug(
"get_by_id(dynamic)", frames, frame);
147 if (idx >= frames->
cnt)
173 }
else if (frames->
dframes == NULL) {
194 if (dyn_cnt < frames->dyn_size) {
200 SCLogDebug(
"limit reached! 256 dynamic frames already");
207 uint16_t new_dyn_size = frames->
dyn_size * 2;
208 uint32_t new_alloc_size = new_dyn_size *
sizeof(
Frame);
215 memset((uint8_t *)ptr + (frames->
dyn_size *
sizeof(
Frame)), 0x00,
225 return &frames->
dframes[dyn_cnt];
229 static void FrameClean(
Frame *frame)
231 memset(frame, 0,
sizeof(*frame));
240 static void AppLayerFrameDumpForFrames(
const char *prefix,
const Frames *frames)
243 for (uint16_t i = 0; i < frames->
cnt; i++) {
257 static inline uint64_t FrameLeftEdge(
const TcpStream *stream,
const Frame *frame)
261 const int64_t frame_offset = frame->
offset;
262 const int64_t frame_data = app_progress - frame_offset;
264 SCLogDebug(
"frame_offset %" PRIi64
", frame_data %" PRIi64
", frame->len %" PRIi64,
265 frame_offset, frame_data, frame->
len);
269 if (frame->
len < 0) {
270 if (frame_data <= 2500) {
271 SCLogDebug(
"got <= 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
275 SCLogDebug(
"got > 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
276 (frame_offset + (frame_data - 2500)));
277 return frame_offset + (frame_data - 2500);
283 if (frame->
len <= frame_data) {
284 uint64_t x = frame_offset + frame_data;
293 }
else if (frame_data < 2500) {
294 uint64_t x = frame_offset;
298 uint64_t x = frame_offset + (frame_data - 2500);
328 static int FrameSlide(
const char *ds,
Frames *frames,
const TcpStream *stream,
const uint32_t slide)
330 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
335 SCLogDebug(
"%s frames %p: sliding %u bytes", ds, frames, slide);
338 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
339 const uint16_t start = frames->
cnt;
340 uint16_t removed = 0;
343 for (uint16_t i = 0; i < frames->
cnt; i++) {
347 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
349 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
351 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
356 FrameCopy(nframe, frame);
357 if (frame != nframe) {
360 le =
MIN(le, FrameLeftEdge(stream, nframe));
367 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
369 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
371 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
381 FrameCopy(nframe, frame);
382 if (frame != nframe) {
385 le =
MIN(le, FrameLeftEdge(stream, nframe));
397 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
398 " (+slide), cnt %u, removed %u, start %u",
402 snprintf(pf,
sizeof(pf),
"%s:post_slide", ds);
403 AppLayerFrameDumpForFrames(pf, frames);
412 if (frames_container == NULL)
417 if (direction == STREAM_TOSERVER) {
419 frames = &frames_container->
toserver;
420 FrameSlide(
"toserver", frames, stream, slide);
423 frames = &frames_container->
toclient;
424 FrameSlide(
"toclient", frames, stream, slide);
428 static void FrameFreeSingleFrame(
Frames *frames,
Frame *r)
434 static void FramesClear(
Frames *frames)
439 for (uint16_t i = 0; i < frames->
cnt; i++) {
443 FrameFreeSingleFrame(frames, r);
448 FrameFreeSingleFrame(frames, r);
465 const uint8_t *frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
467 SCLogDebug(
"frame_start:%p stream_slice->input:%p stream_slice->offset:%" PRIu64, frame_start,
468 stream_slice->input, stream_slice->offset);
470 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
474 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
477 if (frame_start < stream_slice->input ||
478 frame_start > stream_slice->input + stream_slice->input_len)
485 ptrdiff_t ptr_offset = frame_start - stream_slice->input;
487 uint64_t
offset = ptr_offset + stream_slice->offset;
488 SCLogDebug(
"flow %p direction %s frame %p starting at %" PRIu64
" len %" PRIi64
489 " (offset %" PRIu64
")",
490 f, dir == 0 ?
"toserver" :
"toclient", frame_start,
offset,
len, stream_slice->offset);
495 if (frames_container == NULL)
500 frames = &frames_container->
toserver;
502 frames = &frames_container->
toclient;
505 uint64_t abs_frame_offset = stream_slice->offset + ptr_offset;
507 Frame *r = FrameNew(frames, abs_frame_offset,
len);
509 r->
type = frame_type;
515 static Frame *AppLayerFrameUdp(
516 Flow *f,
const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
520 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
524 if (frames_container == NULL)
529 frames = &frames_container->
toserver;
531 frames = &frames_container->
toclient;
534 Frame *r = FrameNew(frames, frame_start_rel,
len);
536 r->
type = frame_type;
544 const int64_t
len,
int dir, uint8_t frame_type)
550 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
554 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
557 if (stream_slice->input == NULL)
565 if (f->
proto == IPPROTO_UDP) {
566 return AppLayerFrameUdp(f, frame_start_rel,
len, dir, frame_type);
570 if (frames_container == NULL)
575 frames = &frames_container->
toserver;
577 frames = &frames_container->
toclient;
580 const uint64_t frame_abs_offset = (uint64_t)frame_start_rel + stream_slice->offset;
581 #ifdef DEBUG_VALIDATION
583 const TcpStream *stream = dir == 0 ? &ssn->client : &ssn->server;
587 Frame *r = FrameNew(frames, frame_abs_offset,
len);
589 r->
type = frame_type;
599 if (frames_container != NULL) {
600 AppLayerFrameDumpForFrames(
"toserver::dump", &frames_container->
toserver);
601 AppLayerFrameDumpForFrames(
"toclient::dump", &frames_container->
toclient);
610 const uint64_t frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
612 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
616 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
619 if (stream_slice->input == NULL)
630 if (frames_container == NULL)
635 frames = &frames_container->
toserver;
637 frames = &frames_container->
toclient;
640 SCLogDebug(
"flow %p direction %s frame type %u offset %" PRIu64
" len %" PRIi64
641 " (slice offset %" PRIu64
")",
642 f, dir == 0 ?
"toserver" :
"toclient", frame_type, frame_start,
len,
643 stream_slice->offset);
644 Frame *r = FrameNew(frames, frame_start,
len);
646 r->
type = frame_type;
699 SCLogDebug(
"get frame_id %" PRIi64
" direction %u/%s frames_container %p", frame_id, dir,
700 dir == 0 ?
"toserver" :
"toclient", frames_container);
701 if (frames_container == NULL)
706 frames = &frames_container->
toserver;
708 frames = &frames_container->
toclient;
716 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
720 SCLogDebug(
"get frame_type %" PRIu8
" direction %u/%s frames_container %p", frame_type, dir,
721 dir == 0 ?
"toserver" :
"toclient", frames_container);
722 if (frames_container == NULL)
727 frames = &frames_container->
toserver;
729 frames = &frames_container->
toclient;
735 static inline bool FrameIsDone(
const Frame *frame,
const uint64_t abs_right_edge)
741 const int64_t frame_abs_offset = frame->
offset;
742 const int64_t frame_right_edge = frame_abs_offset + frame->
len;
743 if ((uint64_t)frame_right_edge <= abs_right_edge) {
744 SCLogDebug(
"frame %p id %" PRIi64
" is done", frame, frame->
id);
750 static void FramePrune(
Frames *frames,
const TcpStream *stream,
const bool eof)
752 #ifdef DEBUG_VALIDATION
755 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64,
761 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
762 const uint16_t start = frames->
cnt;
763 uint16_t removed = 0;
766 for (uint16_t i = 0; i < frames->
cnt; i++) {
770 if (eof || FrameIsDone(frame, acked)) {
772 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
775 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
779 const uint64_t fle = FrameLeftEdge(stream, frame);
781 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
783 FrameCopy(nframe, frame);
784 if (frame != nframe) {
793 if (eof || FrameIsDone(frame, acked)) {
795 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
798 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
802 const uint64_t fle = FrameLeftEdge(stream, frame);
804 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
811 FrameCopy(nframe, frame);
812 if (frame != nframe) {
824 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
825 ", cnt %u, removed %u, start %u",
828 AppLayerFrameDumpForFrames(
"post_slide", frames);
830 if (frames->
cnt > 0) {
841 if (frames_container == NULL)
846 if (p->
proto == IPPROTO_UDP) {
849 frames = &frames_container->
toserver;
851 frames = &frames_container->
toclient;
867 frames = &frames_container->
toserver;
870 frames = &frames_container->
toclient;
875 FramePrune(frames, stream, eof);