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));
241 static void AppLayerFrameDumpForFrames(
const char *prefix,
const Frames *frames)
244 for (uint16_t i = 0; i < frames->
cnt; i++) {
258 static inline uint64_t FrameLeftEdge(
const TcpStream *stream,
const Frame *frame)
262 const int64_t frame_offset = frame->
offset;
263 const int64_t frame_data = app_progress - frame_offset;
265 SCLogDebug(
"frame_offset %" PRIi64
", frame_data %" PRIi64
", frame->len %" PRIi64,
266 frame_offset, frame_data, frame->
len);
270 if (frame->
len < 0) {
271 if (frame_data <= 2500) {
272 SCLogDebug(
"got <= 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
276 SCLogDebug(
"got > 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
277 (frame_offset + (frame_data - 2500)));
278 return frame_offset + (frame_data - 2500);
284 if (frame->
len <= frame_data) {
285 uint64_t x = frame_offset + frame_data;
294 }
else if (frame_data < 2500) {
295 uint64_t x = frame_offset;
299 uint64_t x = frame_offset + (frame_data - 2500);
329 static int FrameSlide(
const char *ds,
Frames *frames,
const TcpStream *stream,
const uint32_t slide)
331 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
336 SCLogDebug(
"%s frames %p: sliding %u bytes", ds, frames, slide);
339 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
340 const uint16_t start = frames->
cnt;
341 uint16_t removed = 0;
344 for (uint16_t i = 0; i < frames->
cnt; i++) {
348 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
350 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
352 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
357 if (frame != nframe) {
358 FrameCopy(nframe, frame);
361 le =
MIN(le, FrameLeftEdge(stream, nframe));
368 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
370 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
372 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
382 if (frame != nframe) {
383 FrameCopy(nframe, frame);
386 le =
MIN(le, FrameLeftEdge(stream, nframe));
398 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
399 " (+slide), cnt %u, removed %u, start %u",
403 snprintf(pf,
sizeof(pf),
"%s:post_slide", ds);
404 AppLayerFrameDumpForFrames(pf, frames);
413 if (frames_container == NULL)
418 if (direction == STREAM_TOSERVER) {
420 frames = &frames_container->
toserver;
421 FrameSlide(
"toserver", frames, stream, slide);
424 frames = &frames_container->
toclient;
425 FrameSlide(
"toclient", frames, stream, slide);
429 static void FrameFreeSingleFrame(
Frames *frames,
Frame *r)
435 static void FramesClear(
Frames *frames)
440 for (uint16_t i = 0; i < frames->
cnt; i++) {
444 FrameFreeSingleFrame(frames, r);
449 FrameFreeSingleFrame(frames, r);
466 const uint8_t *frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
468 SCLogDebug(
"frame_start:%p stream_slice->input:%p stream_slice->offset:%" PRIu64, frame_start,
471 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
475 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
478 if (frame_start < stream_slice->input ||
486 ptrdiff_t ptr_offset = frame_start - stream_slice->
input;
489 SCLogDebug(
"flow %p direction %s frame %p starting at %" PRIu64
" len %" PRIi64
490 " (offset %" PRIu64
")",
491 f, dir == 0 ?
"toserver" :
"toclient", frame_start,
offset,
len, stream_slice->
offset);
496 if (frames_container == NULL)
501 frames = &frames_container->
toserver;
503 frames = &frames_container->
toclient;
506 uint64_t abs_frame_offset = stream_slice->
offset + ptr_offset;
508 Frame *r = FrameNew(frames, abs_frame_offset,
len);
510 r->
type = frame_type;
516 static Frame *AppLayerFrameUdp(
517 Flow *f,
const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
521 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
525 if (frames_container == NULL)
530 frames = &frames_container->
toserver;
532 frames = &frames_container->
toclient;
535 Frame *r = FrameNew(frames, frame_start_rel,
len);
537 r->
type = frame_type;
545 const int64_t
len,
int dir, uint8_t frame_type)
551 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
555 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
558 if (stream_slice->
input == NULL)
566 if (f->
proto == IPPROTO_UDP) {
567 return AppLayerFrameUdp(f, frame_start_rel,
len, dir, frame_type);
571 if (frames_container == NULL)
576 frames = &frames_container->
toserver;
578 frames = &frames_container->
toclient;
581 const uint64_t frame_abs_offset = (uint64_t)frame_start_rel + stream_slice->
offset;
582 #ifdef DEBUG_VALIDATION
584 const TcpStream *stream = dir == 0 ? &ssn->client : &ssn->server;
588 Frame *r = FrameNew(frames, frame_abs_offset,
len);
590 r->
type = frame_type;
600 if (frames_container != NULL) {
601 AppLayerFrameDumpForFrames(
"toserver::dump", &frames_container->
toserver);
602 AppLayerFrameDumpForFrames(
"toclient::dump", &frames_container->
toclient);
611 const uint64_t frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
613 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
617 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
620 if (stream_slice->
input == NULL)
631 if (frames_container == NULL)
636 frames = &frames_container->
toserver;
638 frames = &frames_container->
toclient;
641 SCLogDebug(
"flow %p direction %s frame type %u offset %" PRIu64
" len %" PRIi64
642 " (slice offset %" PRIu64
")",
643 f, dir == 0 ?
"toserver" :
"toclient", frame_type, frame_start,
len,
645 Frame *r = FrameNew(frames, frame_start,
len);
647 r->
type = frame_type;
700 SCLogDebug(
"get frame_id %" PRIi64
" direction %u/%s frames_container %p", frame_id, dir,
701 dir == 0 ?
"toserver" :
"toclient", frames_container);
702 if (frames_container == NULL)
707 frames = &frames_container->
toserver;
709 frames = &frames_container->
toclient;
717 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
721 SCLogDebug(
"get frame_type %" PRIu8
" direction %u/%s frames_container %p", frame_type, dir,
722 dir == 0 ?
"toserver" :
"toclient", frames_container);
723 if (frames_container == NULL)
728 frames = &frames_container->
toserver;
730 frames = &frames_container->
toclient;
736 static inline bool FrameIsDone(
const Frame *frame,
const uint64_t abs_right_edge)
742 const int64_t frame_abs_offset = frame->
offset;
743 const int64_t frame_right_edge = frame_abs_offset + frame->
len;
744 if ((uint64_t)frame_right_edge <= abs_right_edge) {
745 SCLogDebug(
"frame %p id %" PRIi64
" is done", frame, frame->
id);
751 static void FramePrune(
Frames *frames,
const TcpStream *stream,
const bool eof)
753 #ifdef DEBUG_VALIDATION
756 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64,
762 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
763 const uint16_t start = frames->
cnt;
764 uint16_t removed = 0;
767 for (uint16_t i = 0; i < frames->
cnt; i++) {
771 if (eof || FrameIsDone(frame, acked)) {
773 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
776 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
780 const uint64_t fle = FrameLeftEdge(stream, frame);
782 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
784 if (frame != nframe) {
785 FrameCopy(nframe, frame);
794 if (eof || FrameIsDone(frame, acked)) {
796 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
799 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
803 const uint64_t fle = FrameLeftEdge(stream, frame);
805 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
812 if (frame != nframe) {
813 FrameCopy(nframe, frame);
825 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
826 ", cnt %u, removed %u, start %u",
829 AppLayerFrameDumpForFrames(
"post_slide", frames);
831 if (frames->
cnt > 0) {
842 if (frames_container == NULL)
847 if (
p->
proto == IPPROTO_UDP) {
850 frames = &frames_container->
toserver;
852 frames = &frames_container->
toclient;
869 frames = &frames_container->
toserver;
872 frames = &frames_container->
toclient;
877 FramePrune(frames, stream, eof);