47 const uint64_t bits = UINT64_MAX;
61 static inline bool FrameConfigTypeIsEnabled(
const AppProto p,
const uint8_t
type)
72 const char *type_name =
"unknown";
75 }
else if (frames != NULL) {
78 SCLogDebug(
"[%s] %p: frame:%p type:%u/%s id:%" PRIi64
" flags:%02x offset:%" PRIu64
79 ", len:%" PRIi64
", inspect_progress:%" PRIu64
", events:%u %u/%u/%u/%u",
80 prefix, frames, frame, frame->
type, type_name, frame->
id, frame->
flags, frame->
offset,
85 #define FrameDebug(prefix, frames, frame)
93 Frame *candidate = NULL;
96 "frames %p cnt %u, looking for last of type %" PRIu8, frames, frames->
cnt, frame_type);
97 for (uint16_t i = 0; i < frames->
cnt; i++) {
100 FrameDebug(
"get_by_id(static)", frames, frame);
101 if (frame->
type == frame_type && frame->
len == -1)
106 FrameDebug(
"get_by_id(dynamic)", frames, frame);
107 if (frame->
type == frame_type && frame->
len == -1)
116 SCLogDebug(
"frames %p cnt %u, looking for %" PRIi64, frames, frames->
cnt,
id);
117 for (uint16_t i = 0; i < frames->
cnt; i++) {
120 FrameDebug(
"get_by_id(static)", frames, frame);
126 FrameDebug(
"get_by_id(dynamic)", frames, frame);
136 if (idx >= frames->
cnt)
162 }
else if (frames->
dframes == NULL) {
183 if (dyn_cnt < frames->dyn_size) {
189 SCLogDebug(
"limit reached! 256 dynamic frames already");
196 uint16_t new_dyn_size = frames->
dyn_size * 2;
197 uint32_t new_alloc_size = new_dyn_size *
sizeof(
Frame);
204 memset((uint8_t *)ptr + (frames->
dyn_size *
sizeof(
Frame)), 0x00,
214 return &frames->
dframes[dyn_cnt];
218 static void FrameClean(
Frame *frame)
220 memset(frame, 0,
sizeof(*frame));
229 static void AppLayerFrameDumpForFrames(
const char *prefix,
const Frames *frames)
232 for (uint16_t i = 0; i < frames->
cnt; i++) {
246 static inline uint64_t FrameLeftEdge(
const TcpStream *stream,
const Frame *frame)
250 const int64_t frame_offset = frame->
offset;
251 const int64_t frame_data = app_progress - frame_offset;
253 SCLogDebug(
"frame_offset %" PRIi64
", frame_data %" PRIi64
", frame->len %" PRIi64,
254 frame_offset, frame_data, frame->
len);
255 BUG_ON(frame_offset > app_progress);
258 if (frame->
len < 0) {
259 if (frame_data <= 2500) {
260 SCLogDebug(
"got <= 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
264 SCLogDebug(
"got > 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
265 (frame_offset + (frame_data - 2500)));
266 return frame_offset + (frame_data - 2500);
272 if (frame->
len <= frame_data) {
273 uint64_t x = frame_offset + frame_data;
282 }
else if (frame_data < 2500) {
283 uint64_t x = frame_offset;
287 uint64_t x = frame_offset + (frame_data - 2500);
317 static int FrameSlide(
const char *ds,
Frames *frames,
const TcpStream *stream,
const uint32_t slide)
319 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
324 SCLogDebug(
"%s frames %p: sliding %u bytes", ds, frames, slide);
327 const uint16_t start = frames->
cnt;
328 uint16_t removed = 0;
330 for (uint16_t i = 0; i < frames->
cnt; i++) {
334 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
336 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
341 FrameCopy(nframe, frame);
342 if (frame != nframe) {
345 le =
MIN(le, FrameLeftEdge(stream, nframe));
352 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
354 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
364 FrameCopy(nframe, frame);
365 if (frame != nframe) {
368 le =
MIN(le, FrameLeftEdge(stream, nframe));
380 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
381 " (+slide), cnt %u, removed %u, start %u",
385 snprintf(pf,
sizeof(pf),
"%s:post_slide", ds);
386 AppLayerFrameDumpForFrames(pf, frames);
388 BUG_ON(x != start - removed);
395 if (frames_container == NULL)
400 if (direction == STREAM_TOSERVER) {
402 frames = &frames_container->
toserver;
403 FrameSlide(
"toserver", frames, stream, slide);
406 frames = &frames_container->
toclient;
407 FrameSlide(
"toclient", frames, stream, slide);
411 static void FrameFreeSingleFrame(
Frames *frames,
Frame *r)
417 static void FramesClear(
Frames *frames)
422 for (uint16_t i = 0; i < frames->
cnt; i++) {
426 FrameFreeSingleFrame(frames, r);
431 FrameFreeSingleFrame(frames, r);
448 const uint8_t *frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
450 SCLogDebug(
"frame_start:%p stream_slice->input:%p stream_slice->offset:%" PRIu64, frame_start,
451 stream_slice->input, stream_slice->offset);
453 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
457 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
460 if (frame_start < stream_slice->input ||
461 frame_start > stream_slice->input + stream_slice->input_len)
464 BUG_ON(frame_start < stream_slice->input);
465 BUG_ON(stream_slice->input == NULL);
468 ptrdiff_t ptr_offset = frame_start - stream_slice->input;
470 uint64_t
offset = ptr_offset + stream_slice->offset;
471 SCLogDebug(
"flow %p direction %s frame %p starting at %" PRIu64
" len %" PRIi64
472 " (offset %" PRIu64
")",
473 f, dir == 0 ?
"toserver" :
"toclient", frame_start,
offset,
len, stream_slice->offset);
478 if (frames_container == NULL)
483 frames = &frames_container->
toserver;
485 frames = &frames_container->
toclient;
488 uint64_t abs_frame_offset = stream_slice->offset + ptr_offset;
490 Frame *r = FrameNew(frames, abs_frame_offset,
len);
492 r->
type = frame_type;
498 static Frame *AppLayerFrameUdp(
499 Flow *f,
const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
503 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
507 if (frames_container == NULL)
512 frames = &frames_container->
toserver;
514 frames = &frames_container->
toclient;
517 Frame *r = FrameNew(frames, frame_start_rel,
len);
519 r->
type = frame_type;
527 const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
529 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
533 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
536 if (stream_slice->input == NULL)
539 BUG_ON(stream_slice->input == NULL);
544 if (f->
proto == IPPROTO_UDP) {
545 return AppLayerFrameUdp(f, frame_start_rel,
len, dir, frame_type);
549 if (frames_container == NULL)
554 frames = &frames_container->
toserver;
556 frames = &frames_container->
toclient;
559 const uint64_t frame_abs_offset = (uint64_t)frame_start_rel + stream_slice->offset;
560 #ifdef DEBUG_VALIDATION
562 const TcpStream *stream = dir == 0 ? &ssn->client : &ssn->server;
566 Frame *r = FrameNew(frames, frame_abs_offset,
len);
568 r->
type = frame_type;
578 if (frames_container != NULL) {
579 AppLayerFrameDumpForFrames(
"toserver::dump", &frames_container->
toserver);
580 AppLayerFrameDumpForFrames(
"toclient::dump", &frames_container->
toclient);
589 const uint64_t frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
591 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
595 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
598 if (stream_slice->input == NULL)
601 BUG_ON(stream_slice->input == NULL);
606 BUG_ON(frame_start - stream_slice->offset >= (uint64_t)INT_MAX);
609 if (frames_container == NULL)
614 frames = &frames_container->
toserver;
616 frames = &frames_container->
toclient;
619 SCLogDebug(
"flow %p direction %s frame type %u offset %" PRIu64
" len %" PRIi64
620 " (slice offset %" PRIu64
")",
621 f, dir == 0 ?
"toserver" :
"toclient", frame_type, frame_start,
len,
622 stream_slice->offset);
623 Frame *r = FrameNew(frames, frame_start,
len);
625 r->
type = frame_type;
687 SCLogDebug(
"get frame_id %" PRIi64
" direction %u/%s frames_container %p", frame_id, dir,
688 dir == 0 ?
"toserver" :
"toclient", frames_container);
689 if (frames_container == NULL)
694 frames = &frames_container->
toserver;
696 frames = &frames_container->
toclient;
704 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
708 SCLogDebug(
"get frame_type %" PRIu8
" direction %u/%s frames_container %p", frame_type, dir,
709 dir == 0 ?
"toserver" :
"toclient", frames_container);
710 if (frames_container == NULL)
715 frames = &frames_container->
toserver;
717 frames = &frames_container->
toclient;
723 static inline bool FrameIsDone(
const Frame *frame,
const uint64_t abs_right_edge)
729 const int64_t frame_abs_offset = frame->
offset;
730 const int64_t frame_right_edge = frame_abs_offset + frame->
len;
731 if ((uint64_t)frame_right_edge <= abs_right_edge) {
732 SCLogDebug(
"frame %p id %" PRIi64
" is done", frame, frame->
id);
738 static void FramePrune(
Frames *frames,
const TcpStream *stream,
const bool eof)
741 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64,
747 const uint16_t start = frames->
cnt;
748 uint16_t removed = 0;
750 for (uint16_t i = 0; i < frames->
cnt; i++) {
754 if (eof || FrameIsDone(frame, acked)) {
756 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
761 const uint64_t fle = FrameLeftEdge(stream, frame);
763 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
765 FrameCopy(nframe, frame);
766 if (frame != nframe) {
775 if (eof || FrameIsDone(frame, acked)) {
777 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
782 const uint64_t fle = FrameLeftEdge(stream, frame);
784 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
791 FrameCopy(nframe, frame);
792 if (frame != nframe) {
804 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
805 ", cnt %u, removed %u, start %u",
808 AppLayerFrameDumpForFrames(
"post_slide", frames);
810 if (frames->
cnt > 0) {
811 BUG_ON(frames_le_start > le);
813 BUG_ON(x != start - removed);
821 if (frames_container == NULL)
826 if (p->
proto == IPPROTO_UDP) {
829 frames = &frames_container->
toserver;
831 frames = &frames_container->
toclient;
847 frames = &frames_container->
toserver;
850 frames = &frames_container->
toclient;
855 FramePrune(frames, stream, eof);