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);
636 uint32_t pkt_seq, uint8_t *pkt_data, uint16_t pkt_datalen)
643 int r = DoInsertSegment (stream, seg, &dup_seg, p);
646 StreamTcpSegmentAddPacketData(seg, p,
tv, ra_ctx);
651 int res = InsertSegmentDataCustom(stream, seg, pkt_data, pkt_datalen);
654 StreamTcpRemoveSegmentFromStream(stream, seg);
663 }
else if (r == 1 || r == 2) {
664 SCLogDebug(
"overlap (%s%s)", r == 1 ?
"normal" :
"", r == 2 ?
"duplicate" :
"");
674 int res = DoHandleData(
tv, ra_ctx, stream, seg, dup_seg, p);
679 StreamTcpRemoveSegmentFromStream(stream, seg);
685 SCLogDebug(
"duplicate segment %u/%u, discard it",
694 SCLogDebug(
"tree: seg %p, SEQ %"PRIu32
", LEN %"PRIu16
", SUM %"PRIu32
"%s%s%s",
697 s->
seq == seg->
seq ?
" DUPLICATE" :
"",
698 TCPSEG_RB_PREV(s) == NULL ?
" HEAD" :
"",
699 TCPSEG_RB_NEXT(s) == NULL ?
" TAIL" :
"");
737 static inline bool StreamTcpReturnSegmentCheck(
const TcpStream *stream,
const TcpSegment *seg)
739 if (SegmentInUse(stream, seg)) {
753 if (frames_container == NULL)
763 "%s: frames left edge: %" PRIu64, &ssn->
client == stream ?
"toserver" :
"toclient", o);
769 uint64_t left_edge = 0;
773 SCLogDebug(
"use_app %d use_raw %d use_log %d tcp win %u", use_app, use_raw, use_log,
780 uint32_t chunk_size = (stream == &ssn->
client) ?
783 if (raw_progress < (uint64_t)chunk_size) {
786 raw_progress -= (uint64_t)chunk_size;
793 if (raw_progress < stream->min_inspect_depth)
798 SCLogDebug(
"stream->min_inspect_depth %u, raw_progress %"PRIu64,
803 const uint64_t app_le = GetLeftEdgeForApp(f, ssn, stream);
804 left_edge =
MIN(app_le, raw_progress);
805 SCLogDebug(
"left_edge %" PRIu64
", using both app:%" PRIu64
", raw:%" PRIu64, left_edge,
806 app_le, raw_progress);
808 left_edge = raw_progress;
809 SCLogDebug(
"left_edge %"PRIu64
", using only raw:%"PRIu64,
810 left_edge, raw_progress);
812 }
else if (use_app) {
813 const uint64_t app_le = GetLeftEdgeForApp(f, ssn, stream);
815 SCLogDebug(
"left_edge %" PRIu64
", using only app:%" PRIu64, left_edge, app_le);
817 left_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->
sb);
818 SCLogDebug(
"no app & raw: left_edge %"PRIu64
" (full stream)", left_edge);
822 if (use_app || use_raw) {
830 if (STREAM_LASTACK_GT_BASESEQ(stream)) {
836 left_edge =
MIN(left_edge, last_ack_abs);
842 const uint32_t window = stream->
window ? stream->
window : 4096;
843 if (window < left_edge)
848 SCLogDebug(
"stream:%p left_edge %"PRIu64, stream, left_edge);
858 SCLogDebug(
"seg beyond left_edge, we're done");
862 if (SegmentInUse(stream, seg)) {
864 SCLogDebug(
"in-use seg before left_edge, adjust to %"PRIu64
" and bail", left_edge);
891 if (f == NULL || f->
protoctx == NULL) {
898 if (
flags & STREAM_TOSERVER) {
900 }
else if (
flags & STREAM_TOCLIENT) {
912 SCLogDebug(
"ssn %p / stream %p: reassembly depth reached, "
913 "STREAMTCP_STREAM_FLAG_NOREASSEMBLY set", ssn, stream);
920 SCLogDebug(
"ssn %p / stream %p: both app and raw are done, "
921 "STREAMTCP_STREAM_FLAG_NOREASSEMBLY set", ssn, stream);
928 const uint64_t left_edge = GetLeftEdge(f, ssn, stream);
929 SCLogDebug(
"buffer left_edge %" PRIu64, left_edge);
933 SCLogDebug(
"buffer sliding %u to offset %"PRIu64, slide, left_edge);
941 if (slide <= stream->app_progress_rel) {
946 if (slide <= stream->raw_progress_rel) {
951 if (slide <= stream->log_progress_rel) {
957 SCLogDebug(
"stream base_seq %u at stream offset %"PRIu64,
965 SCLogDebug(
"seg %p, SEQ %"PRIu32
", LEN %"PRIu16
", SUM %"PRIu32,
969 if (StreamTcpReturnSegmentCheck(stream, seg) == 0) {
974 StreamTcpRemoveSegmentFromStream(stream, seg);