47 const uint64_t bits = UINT64_MAX;
61 static inline bool FrameConfigTypeIsEnabled(
const AppProto p,
const uint8_t
type)
69 static void FrameDebug(
const char *prefix,
const Frames *frames,
const Frame *frame)
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,
88 SCLogDebug(
"frames %p cnt %u, looking for %" PRIi64, frames, frames->
cnt,
id);
89 for (uint16_t i = 0; i < frames->
cnt; i++) {
92 FrameDebug(
"get_by_id(static)", frames, frame);
98 FrameDebug(
"get_by_id(dynamic)", frames, frame);
108 if (idx >= frames->
cnt)
113 FrameDebug(
"get_by_idx(s)", frames, frame);
118 FrameDebug(
"get_by_idx(d)", frames, frame);
134 }
else if (frames->
dframes == NULL) {
155 if (dyn_cnt < frames->dyn_size) {
161 SCLogDebug(
"limit reached! 256 dynamic frames already");
168 uint16_t new_dyn_size = frames->
dyn_size * 2;
169 uint32_t new_alloc_size = new_dyn_size *
sizeof(
Frame);
176 memset((uint8_t *)ptr + (frames->
dyn_size *
sizeof(
Frame)), 0x00,
186 return &frames->
dframes[dyn_cnt];
190 static void FrameClean(
Frame *frame)
192 memset(frame, 0,
sizeof(*frame));
200 static void AppLayerFrameDumpForFrames(
const char *prefix,
const Frames *frames)
203 for (uint16_t i = 0; i < frames->
cnt; i++) {
206 FrameDebug(prefix, frames, frame);
210 FrameDebug(prefix, frames, frame);
216 static inline uint64_t FrameLeftEdge(
const TcpStream *stream,
const Frame *frame)
220 const int64_t frame_offset = frame->
offset;
221 const int64_t frame_data = app_progress - frame_offset;
223 SCLogDebug(
"frame_offset %" PRIi64
", frame_data %" PRIi64
", frame->len %" PRIi64,
224 frame_offset, frame_data, frame->
len);
225 BUG_ON(frame_offset > app_progress);
228 if (frame->
len < 0) {
229 if (frame_data <= 2500) {
230 SCLogDebug(
"got <= 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
234 SCLogDebug(
"got > 2500 bytes (%" PRIu64
"), returning offset %" PRIu64, frame_data,
235 (frame_offset + (frame_data - 2500)));
236 return frame_offset + (frame_data - 2500);
242 if (frame->
len <= frame_data) {
243 uint64_t x = frame_offset + frame_data;
252 }
else if (frame_data < 2500) {
253 uint64_t x = frame_offset;
257 uint64_t x = frame_offset + (frame_data - 2500);
287 static int FrameSlide(
const char *ds,
Frames *frames,
const TcpStream *stream,
const uint32_t slide)
289 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
294 SCLogDebug(
"%s frames %p: sliding %u bytes", ds, frames, slide);
297 const uint16_t start = frames->
cnt;
298 uint16_t removed = 0;
300 for (uint16_t i = 0; i < frames->
cnt; i++) {
303 FrameDebug(
"slide(s)", frames, frame);
304 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
306 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
311 FrameCopy(nframe, frame);
312 if (frame != nframe) {
315 le =
MIN(le, FrameLeftEdge(stream, nframe));
321 FrameDebug(
"slide(d)", frames, frame);
322 if (frame->
len >= 0 && frame->
offset + frame->
len <= next_base) {
324 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
334 FrameCopy(nframe, frame);
335 if (frame != nframe) {
338 le =
MIN(le, FrameLeftEdge(stream, nframe));
348 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
349 " (+slide), cnt %u, removed %u, start %u",
353 snprintf(pf,
sizeof(pf),
"%s:post_slide", ds);
354 AppLayerFrameDumpForFrames(pf, frames);
357 BUG_ON(x != start - removed);
364 if (frames_container == NULL)
369 if (direction == STREAM_TOSERVER) {
371 frames = &frames_container->
toserver;
372 FrameSlide(
"toserver", frames, stream, slide);
375 frames = &frames_container->
toclient;
376 FrameSlide(
"toclient", frames, stream, slide);
380 static void FrameFreeSingleFrame(
Frames *frames,
Frame *r)
382 FrameDebug(
"free", frames, r);
386 static void FramesClear(
Frames *frames)
391 for (uint16_t i = 0; i < frames->
cnt; i++) {
395 FrameFreeSingleFrame(frames, r);
400 FrameFreeSingleFrame(frames, r);
417 const uint8_t *frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
419 SCLogDebug(
"frame_start:%p stream_slice->input:%p stream_slice->offset:%" PRIu64, frame_start,
420 stream_slice->input, stream_slice->offset);
422 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
426 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
429 if (frame_start < stream_slice->input ||
430 frame_start >= stream_slice->input + stream_slice->input_len)
433 BUG_ON(frame_start < stream_slice->input);
434 BUG_ON(stream_slice->input == NULL);
437 ptrdiff_t ptr_offset = frame_start - stream_slice->input;
439 uint64_t
offset = ptr_offset + stream_slice->offset;
440 SCLogDebug(
"flow %p direction %s frame %p starting at %" PRIu64
" len %" PRIi64
441 " (offset %" PRIu64
")",
442 f, dir == 0 ?
"toserver" :
"toclient", frame_start,
offset,
len, stream_slice->offset);
447 if (frames_container == NULL)
452 frames = &frames_container->
toserver;
454 frames = &frames_container->
toclient;
457 uint64_t abs_frame_offset = stream_slice->offset + ptr_offset;
459 Frame *r = FrameNew(frames, abs_frame_offset,
len);
461 r->
type = frame_type;
462 FrameDebug(
"new_by_ptr", frames, r);
467 static Frame *AppLayerFrameUdp(
Flow *f,
const StreamSlice *stream_slice,
468 const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
472 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
476 if (frames_container == NULL)
481 frames = &frames_container->
toserver;
483 frames = &frames_container->
toclient;
486 Frame *r = FrameNew(frames, frame_start_rel,
len);
488 r->
type = frame_type;
496 const uint32_t frame_start_rel,
const int64_t
len,
int dir, uint8_t frame_type)
498 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
502 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
505 if (stream_slice->input == NULL)
508 BUG_ON(stream_slice->input == NULL);
513 if (f->
proto == IPPROTO_UDP) {
514 return AppLayerFrameUdp(f, stream_slice, frame_start_rel,
len, dir, frame_type);
518 if (frames_container == NULL)
523 frames = &frames_container->
toserver;
525 frames = &frames_container->
toclient;
528 const uint64_t frame_abs_offset = (uint64_t)frame_start_rel + stream_slice->offset;
529 #ifdef DEBUG_VALIDATION
531 const TcpStream *stream = dir == 0 ? &ssn->client : &ssn->server;
535 Frame *r = FrameNew(frames, frame_abs_offset,
len);
537 r->
type = frame_type;
546 if (frames_container != NULL) {
547 AppLayerFrameDumpForFrames(
"toserver::dump", &frames_container->
toserver);
548 AppLayerFrameDumpForFrames(
"toclient::dump", &frames_container->
toclient);
556 const uint64_t frame_start,
const int64_t
len,
int dir, uint8_t frame_type)
558 if (!(FrameConfigTypeIsEnabled(f->
alproto, frame_type)))
562 #if defined(UNITTESTS) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
565 if (stream_slice->input == NULL)
568 BUG_ON(stream_slice->input == NULL);
573 BUG_ON(frame_start - stream_slice->offset >= (uint64_t)INT_MAX);
576 if (frames_container == NULL)
581 frames = &frames_container->
toserver;
583 frames = &frames_container->
toclient;
586 SCLogDebug(
"flow %p direction %s frame type %u offset %" PRIu64
" len %" PRIi64
587 " (slice offset %" PRIu64
")",
588 f, dir == 0 ?
"toserver" :
"toclient", frame_type, frame_start,
len,
589 stream_slice->offset);
590 Frame *r = FrameNew(frames, frame_start,
len);
592 r->
type = frame_type;
603 FrameDebug(
"add_event", NULL, r);
626 FrameDebug(
"set_length", NULL, frame);
641 FrameDebug(
"set_txid", NULL, r);
654 SCLogDebug(
"get frame_id %" PRIi64
" direction %u/%s frames_container %p", frame_id, dir,
655 dir == 0 ?
"toserver" :
"toclient", frames_container);
656 if (frames_container == NULL)
661 frames = &frames_container->
toserver;
663 frames = &frames_container->
toclient;
669 static inline bool FrameIsDone(
670 const Frame *frame,
const uint64_t abs_offset,
const uint64_t abs_right_edge)
676 const int64_t frame_abs_offset = frame->
offset;
677 const int64_t frame_right_edge = frame_abs_offset + frame->
len;
678 if ((uint64_t)frame_right_edge <= abs_right_edge) {
679 SCLogDebug(
"frame %p id %" PRIi64
" is done", frame, frame->
id);
685 static void FramePrune(
Frames *frames,
const TcpStream *stream,
const bool eof)
688 SCLogDebug(
"start: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64,
695 const uint16_t start = frames->
cnt;
696 uint16_t removed = 0;
698 for (uint16_t i = 0; i < frames->
cnt; i++) {
701 FrameDebug(
"prune(s)", frames, frame);
702 if (eof || FrameIsDone(frame, abs_offset, acked)) {
704 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
705 FrameDebug(
"remove(s)", frames, frame);
709 const uint64_t fle = FrameLeftEdge(stream, frame);
711 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
713 FrameCopy(nframe, frame);
714 if (frame != nframe) {
722 FrameDebug(
"prune(d)", frames, frame);
723 if (eof || FrameIsDone(frame, abs_offset, acked)) {
725 SCLogDebug(
"removing %p id %" PRIi64, frame, frame->
id);
726 FrameDebug(
"remove(d)", frames, frame);
730 const uint64_t fle = FrameLeftEdge(stream, frame);
732 SCLogDebug(
"le %" PRIu64
", frame fle %" PRIu64, le, fle);
739 FrameCopy(nframe, frame);
740 if (frame != nframe) {
750 SCLogDebug(
"end: left edge %" PRIu64
", left_edge_rel %u, stream base %" PRIu64
751 ", cnt %u, removed %u, start %u",
754 AppLayerFrameDumpForFrames(
"post_slide", frames);
757 if (frames->
cnt > 0) {
758 BUG_ON(frames_le_start > le);
760 BUG_ON(x != start - removed);
768 if (frames_container == NULL)
773 if (p->
proto == IPPROTO_UDP) {
776 frames = &frames_container->
toserver;
778 frames = &frames_container->
toclient;
794 frames = &frames_container->
toserver;
797 frames = &frames_container->
toclient;
802 FramePrune(frames, stream, eof);