38 static int check_overlap_different_data = 0;
42 check_overlap_different_data = 1;
76 static inline int InsertSegmentDataCustom(
TcpStream *stream,
TcpSegment *seg, uint8_t *data, uint16_t data_len)
90 SCLogDebug(
"stream %p buffer %p, stream_offset %"PRIu64
", "
91 "data_offset %"PRIu16
", SEQ %u BASE %u, data_len %u",
95 if (data_len <= data_offset) {
106 const uint8_t *mydata;
108 uint64_t mydata_offset;
111 SCLogDebug(
"stream %p seg %p data in buffer %p of len %u and offset %"PRIu64,
112 stream, seg, &stream->
sb, mydata_len, mydata_offset);
124 static inline bool CheckOverlap(
struct TCPSEG *tree,
TcpSegment *seg)
127 SCLogDebug(
"start. SEQ %u payload_len %u. Right edge: %u. Seg %p",
174 SCLogDebug(
"empty tree, inserting seg %p seq %" PRIu32
", "
176 TCPSEG_RB_INSERT(&stream->
seg_tree, seg);
184 SCLogDebug(
"seg has a duplicate in the tree seq %u/%u",
194 if (CheckOverlap(&stream->
seg_tree, seg) ==
true) {
224 SCLogDebug(
"handle overlap for segment %p seq %u len %u re %u, "
225 "list segment %p seq %u len %u re %u", seg, seg->
seq,
229 int data_is_different = 0;
230 int use_new_data = 0;
235 SCLogDebug(
"already accepted data not the same as packet data, rewrite packet");
237 data_is_different = 1;
241 if (check_overlap_different_data) {
248 if (check_overlap_different_data) {
250 SCLogDebug(
"data is different from what is in the list");
251 data_is_different = 1;
255 data_is_different = 1;
263 return (check_overlap_different_data && data_is_different);
271 SCLogDebug(
"seg ends before list end, end overlapped by list");
274 SCLogDebug(
"seg ends beyond list end, list overlapped and more");
277 if (data_is_different) {
290 if (data_is_different) {
302 SCLogDebug(
"seg ends before list end, end overlapped by list");
305 SCLogDebug(
"seg starts before and fully overlaps list and beyond");
307 SCLogDebug(
"seg starts before and fully overlaps list");
313 if (data_is_different) {
329 if (data_is_different) {
340 SCLogDebug(
"seg after and is fully overlapped by list");
342 SCLogDebug(
"seg starts after list and ends after list");
347 if (data_is_different) {
353 SCLogDebug(
"seg starts after list and ends before list end");
359 SCLogDebug(
"data_is_different %s, use_new_data %s",
360 data_is_different ?
"yes" :
"no",
361 use_new_data ?
"yes" :
"no");
365 if (data_is_different && !use_new_data) {
367 uint32_t list_offset = 0;
368 uint32_t seg_offset = 0;
371 uint32_t list_seq = list->
seq;
373 const uint8_t *list_data;
376 if (list_data == NULL || list_len == 0 || list_len > USHRT_MAX)
389 seg_offset = list_seq - seg->
seq;
390 seg_len -= seg_offset;
392 list_offset = seg->
seq - list_seq;
393 list_len -= list_offset;
396 if (
SEQ_LT(seg->
seq + seg_offset + seg_len, list_seq + list_offset + list_len)) {
397 list_len -= (list_seq + list_offset + list_len) - (seg->
seq + seg_offset + seg_len);
399 SCLogDebug(
"here goes nothing: list %u %u, seg %u %u", list_offset, list_len, seg_offset, seg_len);
404 memcpy(buf + seg_offset, list_data + list_offset, list_len);
407 return (check_overlap_different_data && data_is_different);
416 static int DoHandleDataCheckBackwards(
TcpStream *stream,
421 SCLogDebug(
"check tree backwards: insert data for segment %p seq %u len %u re %u",
435 SCLogDebug(
"list segment too far to the left, no more overlap will be found");
441 SCLogDebug(
"(back) tree seg %u len %u re %u overlap? %s",
446 retval |= DoHandleDataOverlap(stream, tree_seg, seg, buf, p);
461 static int DoHandleDataCheckForward(
TcpStream *stream,
468 SCLogDebug(
"check list forward: insert data for segment %p seq %u len %u re %u",
481 "no more overlaps can happen", tree_seg->
seq);
485 SCLogDebug(
"(fwd) in-tree seg %u len %u re %u overlap? %s",
490 retval |= DoHandleDataOverlap(stream, tree_seg, seg, buf, p);
506 SCLogDebug(
"insert data for segment %p seq %u len %u re %u",
517 DoHandleDataOverlap(stream, tree_seg, seg, buf, p);
521 const bool is_head = !(TCPSEG_RB_PREV(handle));
522 const bool is_tail = !(TCPSEG_RB_NEXT(handle));
525 if (is_head && !is_tail) {
526 result = DoHandleDataCheckForward(stream, handle, buf, p);
529 }
else if (!is_head && is_tail) {
530 result = DoHandleDataCheckBackwards(stream, handle, buf, p);
533 }
else if (!is_head && !is_tail) {
534 result = DoHandleDataCheckBackwards(stream, handle, buf, p);
535 result |= DoHandleDataCheckForward(stream, handle, buf, p);
546 int res = InsertSegmentDataCustom(stream, handle, buf, p->
payload_len);
582 if (tmp_pkt_hdr == NULL) {
611 static void StreamTcpSegmentAddPacketData(
618 if (PacketIsTunnelChild(p)) {
620 StreamTcpSegmentAddPacketDataDo(seg, rp, p);
622 StreamTcpSegmentAddPacketDataDo(seg, p, p);
642 int r = DoInsertSegment (stream, seg, &dup_seg, p);
645 StreamTcpSegmentAddPacketData(seg, p,
tv, ra_ctx);
650 int res = InsertSegmentDataCustom(stream, seg, pkt_data, pkt_datalen);
653 StreamTcpRemoveSegmentFromStream(stream, seg);
662 }
else if (r == 1 || r == 2) {
663 SCLogDebug(
"overlap (%s%s)", r == 1 ?
"normal" :
"", r == 2 ?
"duplicate" :
"");
673 int res = DoHandleData(
tv, ra_ctx, stream, seg, dup_seg, p);
678 StreamTcpRemoveSegmentFromStream(stream, seg);
684 SCLogDebug(
"duplicate segment %u/%u, discard it",
693 SCLogDebug(
"tree: seg %p, SEQ %"PRIu32
", LEN %"PRIu16
", SUM %"PRIu32
"%s%s%s",
696 s->
seq == seg->
seq ?
" DUPLICATE" :
"",
697 TCPSEG_RB_PREV(s) == NULL ?
" HEAD" :
"",
698 TCPSEG_RB_NEXT(s) == NULL ?
" TAIL" :
"");
736 static inline bool StreamTcpReturnSegmentCheck(
const TcpStream *stream,
const TcpSegment *seg)
738 if (SegmentInUse(stream, seg)) {
752 if (frames_container == NULL)
762 "%s: frames left edge: %" PRIu64, &ssn->
client == stream ?
"toserver" :
"toclient", o);
768 uint64_t left_edge = 0;
772 SCLogDebug(
"use_app %d use_raw %d use_log %d tcp win %u", use_app, use_raw, use_log,
779 uint32_t chunk_size = (stream == &ssn->
client) ?
782 if (raw_progress < (uint64_t)chunk_size) {
785 raw_progress -= (uint64_t)chunk_size;
792 if (raw_progress < stream->min_inspect_depth)
797 SCLogDebug(
"stream->min_inspect_depth %u, raw_progress %"PRIu64,
802 const uint64_t app_le = GetLeftEdgeForApp(f, ssn, stream);
803 left_edge =
MIN(app_le, raw_progress);
804 SCLogDebug(
"left_edge %" PRIu64
", using both app:%" PRIu64
", raw:%" PRIu64, left_edge,
805 app_le, raw_progress);
807 left_edge = raw_progress;
808 SCLogDebug(
"left_edge %"PRIu64
", using only raw:%"PRIu64,
809 left_edge, raw_progress);
811 }
else if (use_app) {
812 const uint64_t app_le = GetLeftEdgeForApp(f, ssn, stream);
814 SCLogDebug(
"left_edge %" PRIu64
", using only app:%" PRIu64, left_edge, app_le);
816 left_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
817 SCLogDebug(
"no app & raw: left_edge %"PRIu64
" (full stream)", left_edge);
821 if (use_app || use_raw) {
829 if (STREAM_LASTACK_GT_BASESEQ(stream)) {
835 left_edge =
MIN(left_edge, last_ack_abs);
841 const uint32_t window = stream->
window ? stream->
window : 4096;
842 if (window < left_edge)
847 SCLogDebug(
"stream:%p left_edge %"PRIu64, stream, left_edge);
857 SCLogDebug(
"seg beyond left_edge, we're done");
861 if (SegmentInUse(stream, seg)) {
863 SCLogDebug(
"in-use seg before left_edge, adjust to %"PRIu64
" and bail", left_edge);
890 if (f == NULL || f->
protoctx == NULL) {
897 if (
flags & STREAM_TOSERVER) {
899 }
else if (
flags & STREAM_TOCLIENT) {
911 SCLogDebug(
"ssn %p / stream %p: reassembly depth reached, "
912 "STREAMTCP_STREAM_FLAG_NOREASSEMBLY set", ssn, stream);
919 SCLogDebug(
"ssn %p / stream %p: both app and raw are done, "
920 "STREAMTCP_STREAM_FLAG_NOREASSEMBLY set", ssn, stream);
927 const uint64_t left_edge = GetLeftEdge(f, ssn, stream);
928 SCLogDebug(
"buffer left_edge %" PRIu64, left_edge);
932 SCLogDebug(
"buffer sliding %u to offset %"PRIu64, slide, left_edge);
940 if (slide <= stream->app_progress_rel) {
945 if (slide <= stream->raw_progress_rel) {
950 if (slide <= stream->log_progress_rel) {
956 SCLogDebug(
"stream base_seq %u at stream offset %"PRIu64,
964 SCLogDebug(
"seg %p, SEQ %"PRIu32
", LEN %"PRIu16
", SUM %"PRIu32,
968 if (StreamTcpReturnSegmentCheck(stream, seg) == 0) {
973 StreamTcpRemoveSegmentFromStream(stream, seg);