32 static void FrameDebug(
const char *prefix,
const Frames *frames,
const Frame *frame)
35 const char *type_name =
38 SCLogDebug(
"[%s] %p: frame: %p type %u/%s id %" PRIi64
" flags %02x rel_offset:%" PRIi64
39 ", len:%" PRIi64
", events:%u %u/%u/%u/%u",
40 prefix, frames, frame, frame->
type, type_name, frame->
id, frame->
flags,
48 for (uint16_t i = 0; i < frames->
cnt; i++) {
65 if (idx >= frames->
cnt)
70 FrameDebug(
"get_by_idx(s)", frames, frame);
75 FrameDebug(
"get_by_idx(d)", frames, frame);
83 static Frame *FrameNew(
Frames *frames, int64_t rel_offset, int64_t
len)
94 }
else if (frames->
dframes == NULL) {
115 if (dyn_cnt < frames->dyn_size) {
121 SCLogDebug(
"limit reached! 256 dynamic frames already");
128 uint16_t new_dyn_size = frames->
dyn_size * 2;
129 uint32_t new_alloc_size = new_dyn_size *
sizeof(
Frame);
136 memset((uint8_t *)ptr + (frames->
dyn_size *
sizeof(
Frame)), 0x00,
146 return &frames->
dframes[dyn_cnt];
150 static void FrameClean(
Frame *frame)
152 memset(frame, 0,
sizeof(*frame));
160 static void AppLayerFrameDumpForFrames(
const char *prefix,
const Frames *frames)
163 for (uint16_t i = 0; i < frames->
cnt; i++) {
166 FrameDebug(prefix, frames, frame);
170 FrameDebug(prefix, frames, frame);
176 static inline uint64_t FrameLeftEdge(
177 const TcpStream *stream,
const Frame *frame,
const int64_t base_offset)
180 BUG_ON(base_offset > app_progress);
182 const int64_t frame_offset = base_offset + frame->
rel_offset;
183 const int64_t frame_data = app_progress - frame_offset;
185 SCLogDebug(
"base_offset %" PRIi64
", app_progress %" PRIi64, base_offset, app_progress);
186 SCLogDebug(
"frame_offset %" PRIi64
", frame_data %" PRIi64
", frame->len %" PRIi64,
187 frame_offset, frame_data, frame->
len);
189 BUG_ON(frame_offset > app_progress);
192 if (frame->
len < 0) {
193 if (frame_data <= 2500) {
194 SCLogDebug(
"got <= 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
198 SCLogDebug(
"got > 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
199 (frame_offset + (frame_data - 2500)));
200 return frame_offset + (frame_data - 2500);
206 if (frame->
len <= frame_data) {
207 uint64_t x = frame_offset + frame_data;
216 }
else if (frame_data < 2500) {
217 uint64_t x = frame_offset;
221 uint64_t x = frame_offset + (frame_data - 2500);
251 static int FrameSlide(
const char *ds,
Frames *frames,
const TcpStream *stream,
const uint32_t slide)
253 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
258 SCLogDebug(
"%s frames %p: sliding %u bytes", ds, frames, slide);
261 const uint16_t start = frames->
cnt;
262 uint16_t removed = 0;
264 for (uint16_t i = 0; i < frames->
cnt; i++) {
267 FrameDebug(
"slide(s)", frames, frame);
268 if (frame->
len >= 0 &&
271 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
276 FrameCopy(nframe, frame);
278 if (frame != nframe) {
281 le =
MIN(le, FrameLeftEdge(stream, nframe, next_base));
287 FrameDebug(
"slide(d)", frames, frame);
290 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
300 FrameCopy(nframe, frame);
302 if (frame != nframe) {
305 le =
MIN(le, FrameLeftEdge(stream, nframe, next_base));
315 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
316 " (+slide), cnt %u, removed %u, start %u",
320 snprintf(pf,
sizeof(pf),
"%s:post_slide", ds);
321 AppLayerFrameDumpForFrames(pf, frames);
324 BUG_ON(x != start - removed);
331 if (frames_container == NULL)
336 if (direction == STREAM_TOSERVER) {
338 frames = &frames_container->
toserver;
339 FrameSlide(
"toserver", frames, stream, slide);
342 frames = &frames_container->
toclient;
343 FrameSlide(
"toclient", frames, stream, slide);
347 static void FrameFreeSingleFrame(
Frames *frames,
Frame *r)
349 FrameDebug(
"free", frames, r);
353 static void FramesClear(
Frames *frames)
358 for (uint16_t i = 0; i < frames->
cnt; i++) {
362 FrameFreeSingleFrame(frames, r);
367 FrameFreeSingleFrame(frames, r);
384 const uint8_t *frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
386 SCLogDebug(
"stream_slice offset %" PRIu64, stream_slice->offset);
387 SCLogDebug(
"frame_start %p stream_slice->input %p", frame_start, stream_slice->input);
390 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
393 if (frame_start < stream_slice->input ||
394 frame_start >= stream_slice->input + stream_slice->input_len)
397 BUG_ON(frame_start < stream_slice->input);
398 BUG_ON(stream_slice->input == NULL);
401 ptrdiff_t ptr_offset = frame_start - stream_slice->input;
403 uint64_t
offset = ptr_offset + stream_slice->offset;
404 SCLogDebug(
"flow %p direction %s frame %p starting at %" PRIu64
" len %" PRIi64
405 " (offset %" PRIu64
")",
406 f, dir == 0 ?
"toserver" :
"toclient", frame_start,
offset,
len, stream_slice->offset);
411 if (frames_container == NULL)
418 frames = &frames_container->
toserver;
421 frames = &frames_container->
toclient;
425 int64_t abs_frame_offset = stream_slice->offset + (int64_t)ptr_offset;
428 Frame *r = FrameNew(frames, rel_offset,
len);
430 r->
type = frame_type;
435 static Frame *AppLayerFrameUdp(
Flow *f,
const StreamSlice *stream_slice,
436 const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
441 if (frames_container == NULL)
446 frames = &frames_container->
toserver;
448 frames = &frames_container->
toclient;
451 Frame *r = FrameNew(frames, frame_start_rel,
len);
453 r->
type = frame_type;
461 const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
464 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
467 if (stream_slice->input == NULL)
470 BUG_ON(stream_slice->input == NULL);
474 if (f->
proto == IPPROTO_UDP) {
475 return AppLayerFrameUdp(f, stream_slice, frame_start_rel,
len, dir, frame_type);
479 if (frames_container == NULL)
486 frames = &frames_container->
toserver;
489 frames = &frames_container->
toclient;
496 const uint64_t app_offset = app - base;
497 const uint64_t slice_offset = stream_slice->offset - base;
499 SCLogDebug(
"app %" PRIu64
", base %" PRIu64
", slice %" PRIu64, app, base, slice_offset);
500 SCLogDebug(
"app_offset %" PRIu64
", slice_offset %" PRIu64, app_offset, slice_offset);
502 const uint64_t frame_abs_offset = (uint64_t)frame_start_rel + stream_slice->offset;
503 const uint64_t frame_base_offset = frame_abs_offset - base;
505 SCLogDebug(
"frame_start_rel %u frame_abs_offset %" PRIu64
", frame_base_offset %" PRIu64,
506 frame_start_rel, frame_abs_offset, frame_base_offset);
508 int64_t rel_offset = frame_base_offset;
511 SCLogDebug(
"flow %p direction %s frame offset %u rel_offset %" PRIi64
" (abs %" PRIu64
512 ") starting at %" PRIu64
" len %" PRIi64
" (offset %" PRIu64
") type %u/%s",
513 f, dir == 0 ?
"toserver" :
"toclient", frame_start_rel, rel_offset, frame_abs_offset,
514 frame_abs_offset,
len, stream_slice->offset, frame_type, type_name);
517 Frame *r = FrameNew(frames, rel_offset,
len);
519 r->
type = frame_type;
528 if (frames_container != NULL) {
529 AppLayerFrameDumpForFrames(
"toserver::dump", &frames_container->
toserver);
530 AppLayerFrameDumpForFrames(
"toclient::dump", &frames_container->
toclient);
538 const uint64_t frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
541 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
544 if (stream_slice->input == NULL)
547 BUG_ON(stream_slice->input == NULL);
551 BUG_ON(frame_start - stream_slice->offset >= (uint64_t)INT_MAX);
554 if (frames_container == NULL)
562 frames = &frames_container->
toserver;
565 frames = &frames_container->
toclient;
570 SCLogDebug(
"flow %p direction %s frame offset %" PRIu64
" (abs %" PRIu64
571 ") starting at %" PRIu64
" len %" PRIi64
" (offset %" PRIu64
")",
572 f, dir == 0 ?
"toserver" :
"toclient", frame_start_rel, frame_start, frame_start,
len,
573 stream_slice->offset);
575 Frame *r = FrameNew(frames, (uint32_t)frame_start_rel,
len);
577 r->
type = frame_type;
588 FrameDebug(
"add_event", NULL, r);
611 FrameDebug(
"set_length", NULL, frame);
626 FrameDebug(
"set_txid", NULL, r);
639 if (frames_container == NULL)
644 frames = &frames_container->
toserver;
646 frames = &frames_container->
toclient;
651 static inline bool FrameIsDone(
652 const Frame *frame,
const uint64_t abs_offset,
const uint64_t abs_right_edge)
658 const int64_t frame_abs_offset = (int64_t)abs_offset + frame->
rel_offset;
659 const int64_t frame_right_edge = frame_abs_offset + frame->
len;
660 if ((uint64_t)frame_right_edge <= abs_right_edge) {
661 SCLogDebug(
"frame %p id %" PRIi64
" is done", frame, frame->
id);
667 static void FramePrune(
Frames *frames,
const TcpStream *stream,
const bool eof)
670 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64,
677 const uint16_t start = frames->
cnt;
678 uint16_t removed = 0;
680 for (uint16_t i = 0; i < frames->
cnt; i++) {
683 FrameDebug(
"prune(s)", frames, frame);
684 if (eof || FrameIsDone(frame, abs_offset, acked)) {
686 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
687 FrameDebug(
"remove(s)", frames, frame);
693 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
695 FrameCopy(nframe, frame);
696 if (frame != nframe) {
704 FrameDebug(
"prune(d)", frames, frame);
705 if (eof || FrameIsDone(frame, abs_offset, acked)) {
707 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
708 FrameDebug(
"remove(d)", frames, frame);
714 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
721 FrameCopy(nframe, frame);
722 if (frame != nframe) {
732 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
733 ", cnt %u, removed %u, start %u",
736 AppLayerFrameDumpForFrames(
"post_slide", frames);
739 if (frames->
cnt > 0) {
740 BUG_ON(frames_le_start > le);
742 BUG_ON(x != start - removed);
750 if (frames_container == NULL)
755 if (p->
proto == IPPROTO_UDP) {
758 frames = &frames_container->
toserver;
760 frames = &frames_container->
toclient;
776 frames = &frames_container->
toserver;
779 frames = &frames_container->
toclient;
784 FramePrune(frames, stream, eof);