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);
265 BUG_ON(frame_offset > app_progress);
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 const uint16_t start = frames->
cnt;
338 uint16_t removed = 0;
340 for (uint16_t i = 0; i < frames->
cnt; i++) {
344 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
346 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
351 FrameCopy(nframe, frame);
352 if (frame != nframe) {
355 le =
MIN(le, FrameLeftEdge(stream, nframe));
362 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
364 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
374 FrameCopy(nframe, frame);
375 if (frame != nframe) {
378 le =
MIN(le, FrameLeftEdge(stream, nframe));
390 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
391 " (+slide), cnt %u, removed %u, start %u",
395 snprintf(pf,
sizeof(pf),
"%s:post_slide", ds);
396 AppLayerFrameDumpForFrames(pf, frames);
398 BUG_ON(x != start - removed);
405 if (frames_container == NULL)
410 if (direction == STREAM_TOSERVER) {
412 frames = &frames_container->
toserver;
413 FrameSlide(
"toserver", frames, stream, slide);
416 frames = &frames_container->
toclient;
417 FrameSlide(
"toclient", frames, stream, slide);
421 static void FrameFreeSingleFrame(
Frames *frames,
Frame *r)
427 static void FramesClear(
Frames *frames)
432 for (uint16_t i = 0; i < frames->
cnt; i++) {
436 FrameFreeSingleFrame(frames, r);
441 FrameFreeSingleFrame(frames, r);
458 const uint8_t *frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
460 SCLogDebug(
"frame_start:%p stream_slice->input:%p stream_slice->offset:%" PRIu64, frame_start,
461 stream_slice->input, stream_slice->offset);
463 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
467 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
470 if (frame_start < stream_slice->input ||
471 frame_start > stream_slice->input + stream_slice->input_len)
474 BUG_ON(frame_start < stream_slice->input);
475 BUG_ON(stream_slice->input == NULL);
478 ptrdiff_t ptr_offset = frame_start - stream_slice->input;
480 uint64_t
offset = ptr_offset + stream_slice->offset;
481 SCLogDebug(
"flow %p direction %s frame %p starting at %" PRIu64
" len %" PRIi64
482 " (offset %" PRIu64
")",
483 f, dir == 0 ?
"toserver" :
"toclient", frame_start,
offset,
len, stream_slice->offset);
488 if (frames_container == NULL)
493 frames = &frames_container->
toserver;
495 frames = &frames_container->
toclient;
498 uint64_t abs_frame_offset = stream_slice->offset + ptr_offset;
500 Frame *r = FrameNew(frames, abs_frame_offset,
len);
502 r->
type = frame_type;
508 static Frame *AppLayerFrameUdp(
509 Flow *f,
const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
513 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
517 if (frames_container == NULL)
522 frames = &frames_container->
toserver;
524 frames = &frames_container->
toclient;
527 Frame *r = FrameNew(frames, frame_start_rel,
len);
529 r->
type = frame_type;
537 const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
539 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
543 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
546 if (stream_slice->input == NULL)
549 BUG_ON(stream_slice->input == NULL);
554 if (f->
proto == IPPROTO_UDP) {
555 return AppLayerFrameUdp(f, frame_start_rel,
len, dir, frame_type);
559 if (frames_container == NULL)
564 frames = &frames_container->
toserver;
566 frames = &frames_container->
toclient;
569 const uint64_t frame_abs_offset = (uint64_t)frame_start_rel + stream_slice->offset;
570 #ifdef DEBUG_VALIDATION
572 const TcpStream *stream = dir == 0 ? &ssn->client : &ssn->server;
576 Frame *r = FrameNew(frames, frame_abs_offset,
len);
578 r->
type = frame_type;
588 if (frames_container != NULL) {
589 AppLayerFrameDumpForFrames(
"toserver::dump", &frames_container->
toserver);
590 AppLayerFrameDumpForFrames(
"toclient::dump", &frames_container->
toclient);
599 const uint64_t frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
601 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
605 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
608 if (stream_slice->input == NULL)
611 BUG_ON(stream_slice->input == NULL);
616 BUG_ON(frame_start - stream_slice->offset >= (uint64_t)INT_MAX);
619 if (frames_container == NULL)
624 frames = &frames_container->
toserver;
626 frames = &frames_container->
toclient;
629 SCLogDebug(
"flow %p direction %s frame type %u offset %" PRIu64
" len %" PRIi64
630 " (slice offset %" PRIu64
")",
631 f, dir == 0 ?
"toserver" :
"toclient", frame_type, frame_start,
len,
632 stream_slice->offset);
633 Frame *r = FrameNew(frames, frame_start,
len);
635 r->
type = frame_type;
697 SCLogDebug(
"get frame_id %" PRIi64
" direction %u/%s frames_container %p", frame_id, dir,
698 dir == 0 ?
"toserver" :
"toclient", frames_container);
699 if (frames_container == NULL)
704 frames = &frames_container->
toserver;
706 frames = &frames_container->
toclient;
714 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
718 SCLogDebug(
"get frame_type %" PRIu8
" direction %u/%s frames_container %p", frame_type, dir,
719 dir == 0 ?
"toserver" :
"toclient", frames_container);
720 if (frames_container == NULL)
725 frames = &frames_container->
toserver;
727 frames = &frames_container->
toclient;
733 static inline bool FrameIsDone(
const Frame *frame,
const uint64_t abs_right_edge)
739 const int64_t frame_abs_offset = frame->
offset;
740 const int64_t frame_right_edge = frame_abs_offset + frame->
len;
741 if ((uint64_t)frame_right_edge <= abs_right_edge) {
742 SCLogDebug(
"frame %p id %" PRIi64
" is done", frame, frame->
id);
748 static void FramePrune(
Frames *frames,
const TcpStream *stream,
const bool eof)
751 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64,
757 const uint16_t start = frames->
cnt;
758 uint16_t removed = 0;
760 for (uint16_t i = 0; i < frames->
cnt; i++) {
764 if (eof || FrameIsDone(frame, acked)) {
766 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
771 const uint64_t fle = FrameLeftEdge(stream, frame);
773 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
775 FrameCopy(nframe, frame);
776 if (frame != nframe) {
785 if (eof || FrameIsDone(frame, acked)) {
787 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
792 const uint64_t fle = FrameLeftEdge(stream, frame);
794 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
801 FrameCopy(nframe, frame);
802 if (frame != nframe) {
814 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
815 ", cnt %u, removed %u, start %u",
818 AppLayerFrameDumpForFrames(
"post_slide", frames);
820 if (frames->
cnt > 0) {
821 BUG_ON(frames_le_start > le);
823 BUG_ON(x != start - removed);
831 if (frames_container == NULL)
836 if (p->
proto == IPPROTO_UDP) {
839 frames = &frames_container->
toserver;
841 frames = &frames_container->
toclient;
857 frames = &frames_container->
toserver;
860 frames = &frames_container->
toclient;
865 FramePrune(frames, stream, eof);