42 if (
unlikely(frame_config == NULL)) {
57 const uint64_t bits = UINT64_MAX;
71 static inline bool FrameConfigTypeIsEnabled(
const AppProto p,
const uint8_t
type)
82 const char *type_name =
"unknown";
85 }
else if (frames != NULL) {
88 SCLogDebug(
"[%s] %p: frame:%p type:%u/%s id:%" PRIi64
" flags:%02x offset:%" PRIu64
89 ", len:%" PRIi64
", inspect_progress:%" PRIu64
", events:%u %u/%u/%u/%u",
90 prefix, frames, frame, frame->
type, type_name, frame->
id, frame->
flags, frame->
offset,
95 #define FrameDebug(prefix, frames, frame)
103 Frame *candidate = NULL;
106 "frames %p cnt %u, looking for last of type %" PRIu8, frames, frames->
cnt, frame_type);
107 for (uint16_t i = 0; i < frames->
cnt; i++) {
110 FrameDebug(
"get_by_id(static)", frames, frame);
111 if (frame->
type == frame_type && frame->
len == -1)
116 FrameDebug(
"get_by_id(dynamic)", frames, frame);
117 if (frame->
type == frame_type && frame->
len == -1)
126 SCLogDebug(
"frames %p cnt %u, looking for %" PRIi64, frames, frames->
cnt,
id);
127 for (uint16_t i = 0; i < frames->
cnt; i++) {
130 FrameDebug(
"get_by_id(static)", frames, frame);
136 FrameDebug(
"get_by_id(dynamic)", frames, frame);
146 if (idx >= frames->
cnt)
172 }
else if (frames->
dframes == NULL) {
193 if (dyn_cnt < frames->dyn_size) {
199 SCLogDebug(
"limit reached! 256 dynamic frames already");
206 uint16_t new_dyn_size = frames->
dyn_size * 2;
207 uint32_t new_alloc_size = new_dyn_size *
sizeof(
Frame);
214 memset((uint8_t *)ptr + (frames->
dyn_size *
sizeof(
Frame)), 0x00,
224 return &frames->
dframes[dyn_cnt];
228 static void FrameClean(
Frame *frame)
230 memset(frame, 0,
sizeof(*frame));
239 static void AppLayerFrameDumpForFrames(
const char *prefix,
const Frames *frames)
242 for (uint16_t i = 0; i < frames->
cnt; i++) {
256 static inline uint64_t FrameLeftEdge(
const TcpStream *stream,
const Frame *frame)
260 const int64_t frame_offset = frame->
offset;
261 const int64_t frame_data = app_progress - frame_offset;
263 SCLogDebug(
"frame_offset %" PRIi64
", frame_data %" PRIi64
", frame->len %" PRIi64,
264 frame_offset, frame_data, frame->
len);
268 if (frame->
len < 0) {
269 if (frame_data <= 2500) {
270 SCLogDebug(
"got <= 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
274 SCLogDebug(
"got > 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
275 (frame_offset + (frame_data - 2500)));
276 return frame_offset + (frame_data - 2500);
282 if (frame->
len <= frame_data) {
283 uint64_t x = frame_offset + frame_data;
292 }
else if (frame_data < 2500) {
293 uint64_t x = frame_offset;
297 uint64_t x = frame_offset + (frame_data - 2500);
327 static int FrameSlide(
const char *ds,
Frames *frames,
const TcpStream *stream,
const uint32_t slide)
329 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
334 SCLogDebug(
"%s frames %p: sliding %u bytes", ds, frames, slide);
337 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
338 const uint16_t start = frames->
cnt;
339 uint16_t removed = 0;
342 for (uint16_t i = 0; i < frames->
cnt; i++) {
346 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
348 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
350 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
355 FrameCopy(nframe, frame);
356 if (frame != nframe) {
359 le =
MIN(le, FrameLeftEdge(stream, nframe));
366 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
368 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
370 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
380 FrameCopy(nframe, frame);
381 if (frame != nframe) {
384 le =
MIN(le, FrameLeftEdge(stream, nframe));
396 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
397 " (+slide), cnt %u, removed %u, start %u",
401 snprintf(pf,
sizeof(pf),
"%s:post_slide", ds);
402 AppLayerFrameDumpForFrames(pf, frames);
411 if (frames_container == NULL)
416 if (direction == STREAM_TOSERVER) {
418 frames = &frames_container->
toserver;
419 FrameSlide(
"toserver", frames, stream, slide);
422 frames = &frames_container->
toclient;
423 FrameSlide(
"toclient", frames, stream, slide);
427 static void FrameFreeSingleFrame(
Frames *frames,
Frame *r)
433 static void FramesClear(
Frames *frames)
438 for (uint16_t i = 0; i < frames->
cnt; i++) {
442 FrameFreeSingleFrame(frames, r);
447 FrameFreeSingleFrame(frames, r);
464 const uint8_t *frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
466 SCLogDebug(
"frame_start:%p stream_slice->input:%p stream_slice->offset:%" PRIu64, frame_start,
467 stream_slice->input, stream_slice->offset);
469 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
473 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
476 if (frame_start < stream_slice->input ||
477 frame_start > stream_slice->input + stream_slice->input_len)
484 ptrdiff_t ptr_offset = frame_start - stream_slice->input;
486 uint64_t
offset = ptr_offset + stream_slice->offset;
487 SCLogDebug(
"flow %p direction %s frame %p starting at %" PRIu64
" len %" PRIi64
488 " (offset %" PRIu64
")",
489 f, dir == 0 ?
"toserver" :
"toclient", frame_start,
offset,
len, stream_slice->offset);
494 if (frames_container == NULL)
499 frames = &frames_container->
toserver;
501 frames = &frames_container->
toclient;
504 uint64_t abs_frame_offset = stream_slice->offset + ptr_offset;
506 Frame *r = FrameNew(frames, abs_frame_offset,
len);
508 r->
type = frame_type;
514 static Frame *AppLayerFrameUdp(
515 Flow *f,
const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
519 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
523 if (frames_container == NULL)
528 frames = &frames_container->
toserver;
530 frames = &frames_container->
toclient;
533 Frame *r = FrameNew(frames, frame_start_rel,
len);
535 r->
type = frame_type;
543 const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
545 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
549 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
552 if (stream_slice->input == NULL)
560 if (f->
proto == IPPROTO_UDP) {
561 return AppLayerFrameUdp(f, frame_start_rel,
len, dir, frame_type);
565 if (frames_container == NULL)
570 frames = &frames_container->
toserver;
572 frames = &frames_container->
toclient;
575 const uint64_t frame_abs_offset = (uint64_t)frame_start_rel + stream_slice->offset;
576 #ifdef DEBUG_VALIDATION
578 const TcpStream *stream = dir == 0 ? &ssn->client : &ssn->server;
582 Frame *r = FrameNew(frames, frame_abs_offset,
len);
584 r->
type = frame_type;
594 if (frames_container != NULL) {
595 AppLayerFrameDumpForFrames(
"toserver::dump", &frames_container->
toserver);
596 AppLayerFrameDumpForFrames(
"toclient::dump", &frames_container->
toclient);
605 const uint64_t frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
607 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
611 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
614 if (stream_slice->input == NULL)
625 if (frames_container == NULL)
630 frames = &frames_container->
toserver;
632 frames = &frames_container->
toclient;
635 SCLogDebug(
"flow %p direction %s frame type %u offset %" PRIu64
" len %" PRIi64
636 " (slice offset %" PRIu64
")",
637 f, dir == 0 ?
"toserver" :
"toclient", frame_type, frame_start,
len,
638 stream_slice->offset);
639 Frame *r = FrameNew(frames, frame_start,
len);
641 r->
type = frame_type;
703 SCLogDebug(
"get frame_id %" PRIi64
" direction %u/%s frames_container %p", frame_id, dir,
704 dir == 0 ?
"toserver" :
"toclient", frames_container);
705 if (frames_container == NULL)
710 frames = &frames_container->
toserver;
712 frames = &frames_container->
toclient;
720 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
724 SCLogDebug(
"get frame_type %" PRIu8
" direction %u/%s frames_container %p", frame_type, dir,
725 dir == 0 ?
"toserver" :
"toclient", frames_container);
726 if (frames_container == NULL)
731 frames = &frames_container->
toserver;
733 frames = &frames_container->
toclient;
739 static inline bool FrameIsDone(
const Frame *frame,
const uint64_t abs_right_edge)
745 const int64_t frame_abs_offset = frame->
offset;
746 const int64_t frame_right_edge = frame_abs_offset + frame->
len;
747 if ((uint64_t)frame_right_edge <= abs_right_edge) {
748 SCLogDebug(
"frame %p id %" PRIi64
" is done", frame, frame->
id);
754 static void FramePrune(
Frames *frames,
const TcpStream *stream,
const bool eof)
756 #ifdef DEBUG_VALIDATION
759 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64,
765 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
766 const uint16_t start = frames->
cnt;
767 uint16_t removed = 0;
770 for (uint16_t i = 0; i < frames->
cnt; i++) {
774 if (eof || FrameIsDone(frame, acked)) {
776 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
779 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
783 const uint64_t fle = FrameLeftEdge(stream, frame);
785 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
787 FrameCopy(nframe, frame);
788 if (frame != nframe) {
797 if (eof || FrameIsDone(frame, acked)) {
799 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
802 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
806 const uint64_t fle = FrameLeftEdge(stream, frame);
808 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
815 FrameCopy(nframe, frame);
816 if (frame != nframe) {
828 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
829 ", cnt %u, removed %u, start %u",
832 AppLayerFrameDumpForFrames(
"post_slide", frames);
834 if (frames->
cnt > 0) {
845 if (frames_container == NULL)
850 if (p->
proto == IPPROTO_UDP) {
853 frames = &frames_container->
toserver;
855 frames = &frames_container->
toclient;
871 frames = &frames_container->
toserver;
874 frames = &frames_container->
toclient;
879 FramePrune(frames, stream, eof);