44 if (
unlikely(frame_config == NULL)) {
59 const uint64_t bits = UINT64_MAX;
73 static inline bool FrameConfigTypeIsEnabled(
const AppProto p,
const uint8_t
type)
84 const char *type_name =
"unknown";
87 }
else if (frames != NULL) {
90 SCLogDebug(
"[%s] %p: frame:%p type:%u/%s id:%" PRIi64
" flags:%02x offset:%" PRIu64
91 ", len:%" PRIi64
", inspect_progress:%" PRIu64
", events:%u %u/%u/%u/%u",
92 prefix, frames, frame, frame->
type, type_name, frame->
id, frame->
flags, frame->
offset,
97 #define FrameDebug(prefix, frames, frame)
105 Frame *candidate = NULL;
108 "frames %p cnt %u, looking for last of type %" PRIu8, frames, frames->
cnt, frame_type);
109 for (uint16_t i = 0; i < frames->
cnt; i++) {
112 FrameDebug(
"get_by_id(static)", frames, frame);
113 if (frame->
type == frame_type && frame->
len == -1)
118 FrameDebug(
"get_by_id(dynamic)", frames, frame);
119 if (frame->
type == frame_type && frame->
len == -1)
128 SCLogDebug(
"frames %p cnt %u, looking for %" PRIi64, frames, frames->
cnt,
id);
129 for (uint16_t i = 0; i < frames->
cnt; i++) {
132 FrameDebug(
"get_by_id(static)", frames, frame);
138 FrameDebug(
"get_by_id(dynamic)", frames, frame);
148 if (idx >= frames->
cnt)
174 }
else if (frames->
dframes == NULL) {
195 if (dyn_cnt < frames->dyn_size) {
201 SCLogDebug(
"limit reached! 256 dynamic frames already");
208 uint16_t new_dyn_size = frames->
dyn_size * 2;
209 uint32_t new_alloc_size = new_dyn_size *
sizeof(
Frame);
216 memset((uint8_t *)ptr + (frames->
dyn_size *
sizeof(
Frame)), 0x00,
226 return &frames->
dframes[dyn_cnt];
230 static void FrameClean(
Frame *frame)
232 memset(frame, 0,
sizeof(*frame));
242 static void AppLayerFrameDumpForFrames(
const char *prefix,
const Frames *frames)
245 for (uint16_t i = 0; i < frames->
cnt; i++) {
259 static inline uint64_t FrameLeftEdge(
const TcpStream *stream,
const Frame *frame)
263 const int64_t frame_offset = frame->
offset;
264 const int64_t frame_data = app_progress - frame_offset;
266 SCLogDebug(
"frame_offset %" PRIi64
", frame_data %" PRIi64
", frame->len %" PRIi64,
267 frame_offset, frame_data, frame->
len);
271 if (frame->
len < 0) {
272 if (frame_data <= 2500) {
273 SCLogDebug(
"got <= 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
277 SCLogDebug(
"got > 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
278 (frame_offset + (frame_data - 2500)));
279 return frame_offset + (frame_data - 2500);
285 if (frame->
len <= frame_data) {
286 uint64_t x = frame_offset + frame_data;
295 }
else if (frame_data < 2500) {
296 uint64_t x = frame_offset;
300 uint64_t x = frame_offset + (frame_data - 2500);
330 static int FrameSlide(
const char *ds,
Frames *frames,
const TcpStream *stream,
const uint32_t slide)
332 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
337 SCLogDebug(
"%s frames %p: sliding %u bytes", ds, frames, slide);
340 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
341 const uint16_t start = frames->
cnt;
342 uint16_t removed = 0;
345 for (uint16_t i = 0; i < frames->
cnt; i++) {
349 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
351 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
353 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
358 if (frame != nframe) {
359 FrameCopy(nframe, frame);
362 le =
MIN(le, FrameLeftEdge(stream, nframe));
369 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
371 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
373 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
383 if (frame != nframe) {
384 FrameCopy(nframe, frame);
387 le =
MIN(le, FrameLeftEdge(stream, nframe));
399 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
400 " (+slide), cnt %u, removed %u, start %u",
404 snprintf(pf,
sizeof(pf),
"%s:post_slide", ds);
405 AppLayerFrameDumpForFrames(pf, frames);
414 if (frames_container == NULL)
419 if (direction == STREAM_TOSERVER) {
421 frames = &frames_container->
toserver;
422 FrameSlide(
"toserver", frames, stream, slide);
425 frames = &frames_container->
toclient;
426 FrameSlide(
"toclient", frames, stream, slide);
430 static void FrameFreeSingleFrame(
Frames *frames,
Frame *r)
436 static void FramesClear(
Frames *frames)
441 for (uint16_t i = 0; i < frames->
cnt; i++) {
445 FrameFreeSingleFrame(frames, r);
450 FrameFreeSingleFrame(frames, r);
467 const uint8_t *frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
469 SCLogDebug(
"frame_start:%p stream_slice->input:%p stream_slice->offset:%" PRIu64, frame_start,
472 if (!(FrameConfigTypeIsEnabled(
f->
alproto, frame_type)))
476 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
479 if (frame_start < stream_slice->input ||
487 ptrdiff_t ptr_offset = frame_start - stream_slice->
input;
490 SCLogDebug(
"flow %p direction %s frame %p starting at %" PRIu64
" len %" PRIi64
491 " (offset %" PRIu64
")",
492 f, dir == 0 ?
"toserver" :
"toclient", frame_start,
offset,
len, stream_slice->
offset);
497 if (frames_container == NULL)
502 frames = &frames_container->
toserver;
504 frames = &frames_container->
toclient;
507 uint64_t abs_frame_offset = stream_slice->
offset + ptr_offset;
509 Frame *r = FrameNew(frames, abs_frame_offset,
len);
511 r->
type = frame_type;
517 static Frame *AppLayerFrameUdp(
518 Flow *
f,
const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
522 if (!(FrameConfigTypeIsEnabled(
f->
alproto, frame_type)))
526 if (frames_container == NULL)
531 frames = &frames_container->
toserver;
533 frames = &frames_container->
toclient;
536 Frame *r = FrameNew(frames, frame_start_rel,
len);
538 r->
type = frame_type;
546 const int64_t
len,
int dir, uint8_t frame_type)
552 if (!(FrameConfigTypeIsEnabled(
f->
alproto, frame_type)))
556 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
559 if (stream_slice->
input == NULL)
567 if (
f->
proto == IPPROTO_UDP) {
568 return AppLayerFrameUdp(
f, frame_start_rel,
len, dir, frame_type);
572 if (frames_container == NULL)
577 frames = &frames_container->
toserver;
579 frames = &frames_container->
toclient;
582 const uint64_t frame_abs_offset = (uint64_t)frame_start_rel + stream_slice->
offset;
583 #ifdef DEBUG_VALIDATION
589 Frame *r = FrameNew(frames, frame_abs_offset,
len);
591 r->
type = frame_type;
601 if (frames_container != NULL) {
602 AppLayerFrameDumpForFrames(
"toserver::dump", &frames_container->
toserver);
603 AppLayerFrameDumpForFrames(
"toclient::dump", &frames_container->
toclient);
612 const uint64_t frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
614 if (!(FrameConfigTypeIsEnabled(
f->
alproto, frame_type)))
618 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
621 if (stream_slice->
input == NULL)
632 if (frames_container == NULL)
637 frames = &frames_container->
toserver;
639 frames = &frames_container->
toclient;
642 SCLogDebug(
"flow %p direction %s frame type %u offset %" PRIu64
" len %" PRIi64
643 " (slice offset %" PRIu64
")",
644 f, dir == 0 ?
"toserver" :
"toclient", frame_type, frame_start,
len,
646 Frame *r = FrameNew(frames, frame_start,
len);
648 r->
type = frame_type;
701 SCLogDebug(
"get frame_id %" PRIi64
" direction %u/%s frames_container %p", frame_id, dir,
702 dir == 0 ?
"toserver" :
"toclient", frames_container);
703 if (frames_container == NULL)
708 frames = &frames_container->
toserver;
710 frames = &frames_container->
toclient;
718 if (!(FrameConfigTypeIsEnabled(
f->
alproto, frame_type)))
722 SCLogDebug(
"get frame_type %" PRIu8
" direction %u/%s frames_container %p", frame_type, dir,
723 dir == 0 ?
"toserver" :
"toclient", frames_container);
724 if (frames_container == NULL)
729 frames = &frames_container->
toserver;
731 frames = &frames_container->
toclient;
737 static inline bool FrameIsDone(
const Frame *frame,
const uint64_t abs_right_edge)
743 const int64_t frame_abs_offset = frame->
offset;
744 const int64_t frame_right_edge = frame_abs_offset + frame->
len;
745 if ((uint64_t)frame_right_edge <= abs_right_edge) {
746 SCLogDebug(
"frame %p id %" PRIi64
" is done", frame, frame->
id);
752 static void FramePrune(
Frames *frames,
const TcpStream *stream,
const bool eof)
754 #ifdef DEBUG_VALIDATION
757 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64,
763 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
764 const uint16_t start = frames->
cnt;
765 uint16_t removed = 0;
768 for (uint16_t i = 0; i < frames->
cnt; i++) {
772 if (eof || FrameIsDone(frame, acked)) {
774 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
777 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
781 const uint64_t fle = FrameLeftEdge(stream, frame);
783 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
785 if (frame != nframe) {
786 FrameCopy(nframe, frame);
795 if (eof || FrameIsDone(frame, acked)) {
797 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
800 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
804 const uint64_t fle = FrameLeftEdge(stream, frame);
806 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
813 if (frame != nframe) {
814 FrameCopy(nframe, frame);
826 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
827 ", cnt %u, removed %u, start %u",
830 AppLayerFrameDumpForFrames(
"post_slide", frames);
832 if (frames->
cnt > 0) {
843 if (frames_container == NULL)
848 if (
p->
proto == IPPROTO_UDP) {
851 frames = &frames_container->
toserver;
853 frames = &frames_container->
toclient;
870 frames = &frames_container->
toserver;
873 frames = &frames_container->
toclient;
878 FramePrune(frames, stream, eof);