From: Victor Julien Date: Thu, 28 Apr 2016 08:53:49 +0000 (+0200) Subject: stream: add tcp.overlap and tcp.overlap_diff_data counters X-Git-Tag: suricata-4.0.0-beta1~180 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f02dc377efd7f5b1aa8a961f18cbe0ef49bc395e;p=thirdparty%2Fsuricata.git stream: add tcp.overlap and tcp.overlap_diff_data counters --- diff --git a/src/stream-tcp-list.c b/src/stream-tcp-list.c index 532ba79eab..e3327763ac 100644 --- a/src/stream-tcp-list.c +++ b/src/stream-tcp-list.c @@ -214,6 +214,9 @@ static int DoInsertSegment (TcpStream *stream, TcpSegment *seg, Packet *p) * * \param buf stack allocated buffer sized p->payload_len that will be * inserted into the stream buffer + * + * \retval 1 if data was different + * \retval 0 data was the same or we didn't check for differences */ static int DoHandleDataOverlap(TcpStream *stream, TcpSegment *list, TcpSegment *seg, uint8_t *buf, Packet *p) { @@ -244,7 +247,6 @@ static int DoHandleDataOverlap(TcpStream *stream, TcpSegment *list, TcpSegment * if (StreamTcpInlineSegmentCompare(stream, p, list) != 0) { SCLogDebug("data is different from what is in the list"); data_is_different = 1; - StreamTcpSetEvent(p, STREAM_REASSEMBLY_OVERLAP_DIFFERENT_DATA); } } else { /* if we're not checking, assume it's different */ @@ -256,7 +258,7 @@ static int DoHandleDataOverlap(TcpStream *stream, TcpSegment *list, TcpSegment * if (stream->os_policy == OS_POLICY_LAST) { /* buf will start with LAST data (from the segment), * so if policy is LAST we're now done here. */ - return 0; + return (check_overlap_different_data && data_is_different); } /* start at the same seq */ @@ -400,7 +402,7 @@ static int DoHandleDataOverlap(TcpStream *stream, TcpSegment *list, TcpSegment * memcpy(buf + seg_offset, list_data + list_offset, list_len); //PrintRawDataFp(stdout, buf, p->payload_len); } - return 0; + return (check_overlap_different_data && data_is_different); } #define MAX_IP_DATA (uint32_t)(65536 - 40) // min ip header and min tcp header @@ -413,6 +415,8 @@ static int DoHandleDataOverlap(TcpStream *stream, TcpSegment *list, TcpSegment * */ static int DoHandleDataCheckBackwards(TcpStream *stream, TcpSegment *seg, uint8_t *buf, Packet *p) { + int retval = 0; + SCLogDebug("check list backwards: insert data for segment %p seq %u len %u re %u", seg, seg->seq, TCP_SEG_LEN(seg), SEG_SEQ_RIGHT_EDGE(seg)); @@ -433,13 +437,13 @@ static int DoHandleDataCheckBackwards(TcpStream *stream, TcpSegment *seg, uint8_ SEG_SEQ_RIGHT_EDGE(list), overlap ? "yes" : "no"); if (overlap) { - DoHandleDataOverlap(stream, list, seg, buf, p); + retval |= DoHandleDataOverlap(stream, list, seg, buf, p); } list = list->prev; } while (list != NULL); - return 0; + return retval; } /** \internal @@ -450,6 +454,8 @@ static int DoHandleDataCheckBackwards(TcpStream *stream, TcpSegment *seg, uint8_ */ static int DoHandleDataCheckForward(TcpStream *stream, TcpSegment *seg, uint8_t *buf, Packet *p) { + int retval = 0; + uint32_t seg_re = SEG_SEQ_RIGHT_EDGE(seg); SCLogDebug("check list forward: insert data for segment %p seq %u len %u re %u", @@ -470,17 +476,20 @@ static int DoHandleDataCheckForward(TcpStream *stream, TcpSegment *seg, uint8_t TCP_SEG_LEN(list), SEG_SEQ_RIGHT_EDGE(list), overlap ? "yes" : "no"); if (overlap) { - DoHandleDataOverlap(stream, list, seg, buf, p); + retval |= DoHandleDataOverlap(stream, list, seg, buf, p); } list = list->next; } while (list != NULL); - return 0; + return retval; } -static int DoHandleData(TcpStream *stream, TcpSegment *seg, Packet *p) +static int DoHandleData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, + TcpStream *stream, TcpSegment *seg, Packet *p) { + int result = 0; + SCLogDebug("insert data for segment %p seq %u len %u re %u", seg, seg->seq, TCP_SEG_LEN(seg), SEG_SEQ_RIGHT_EDGE(seg)); @@ -492,16 +501,22 @@ static int DoHandleData(TcpStream *stream, TcpSegment *seg, Packet *p) /* new list head */ if (seg->next != NULL && seg->prev == NULL) { - DoHandleDataCheckForward(stream, seg, buf, p); + result = DoHandleDataCheckForward(stream, seg, buf, p); /* new list tail */ } else if (seg->next == NULL && seg->prev != NULL) { - DoHandleDataCheckBackwards(stream, seg, buf, p); + result = DoHandleDataCheckBackwards(stream, seg, buf, p); /* middle of the list */ } else if (seg->next != NULL && seg->prev != NULL) { - DoHandleDataCheckBackwards(stream, seg, buf, p); - DoHandleDataCheckForward(stream, seg, buf, p); + result = DoHandleDataCheckBackwards(stream, seg, buf, p); + result |= DoHandleDataCheckForward(stream, seg, buf, p); + } + + /* we had an overlap with different data */ + if (result) { + StreamTcpSetEvent(p, STREAM_REASSEMBLY_OVERLAP_DIFFERENT_DATA); + StatsIncr(tv, ra_ctx->counter_tcp_reass_overlap_diff_data); } /* insert the temp buffer now that we've (possibly) updated @@ -511,7 +526,6 @@ static int DoHandleData(TcpStream *stream, TcpSegment *seg, Packet *p) } return 0; - } /** @@ -547,8 +561,11 @@ int StreamTcpReassembleInsertSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ } } else if (r == 1) { + /* XXX should we exclude 'retransmissions' here? */ + StatsIncr(tv, ra_ctx->counter_tcp_reass_overlap); + /* now let's consider the data in the overlap case */ - int res = DoHandleData(stream, seg, p); + int res = DoHandleData(tv, ra_ctx, stream, seg, p); if (res < 0) { StreamTcpRemoveSegmentFromStream(stream, seg); StreamTcpSegmentReturntoPool(seg); diff --git a/src/stream-tcp-reassemble.h b/src/stream-tcp-reassemble.h index 7dd4c666f2..3162ca7132 100644 --- a/src/stream-tcp-reassemble.h +++ b/src/stream-tcp-reassemble.h @@ -59,6 +59,11 @@ typedef struct TcpReassemblyThreadCtx_ { uint16_t counter_tcp_stream_depth; /** count number of streams with a unrecoverable stream gap (missing pkts) */ uint16_t counter_tcp_reass_gap; + + /** count packet data overlaps */ + uint16_t counter_tcp_reass_overlap; + /** count overlaps with different data */ + uint16_t counter_tcp_reass_overlap_diff_data; } TcpReassemblyThreadCtx; #define OS_POLICY_DEFAULT OS_POLICY_BSD diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 9329c4ff2a..b77975cd4d 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -4954,6 +4954,8 @@ TmEcode StreamTcpThreadInit(ThreadVars *tv, void *initdata, void **data) stt->ra_ctx->counter_tcp_segment_memcap = StatsRegisterCounter("tcp.segment_memcap_drop", tv); stt->ra_ctx->counter_tcp_stream_depth = StatsRegisterCounter("tcp.stream_depth_reached", tv); stt->ra_ctx->counter_tcp_reass_gap = StatsRegisterCounter("tcp.reassembly_gap", tv); + stt->ra_ctx->counter_tcp_reass_overlap = StatsRegisterCounter("tcp.overlap", tv); + stt->ra_ctx->counter_tcp_reass_overlap_diff_data = StatsRegisterCounter("tcp.overlap_diff_data", tv); SCLogDebug("StreamTcp thread specific ctx online at %p, reassembly ctx %p", stt, stt->ra_ctx);