]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
stream: add tcp.overlap and tcp.overlap_diff_data counters
authorVictor Julien <victor@inliniac.net>
Thu, 28 Apr 2016 08:53:49 +0000 (10:53 +0200)
committerVictor Julien <victor@inliniac.net>
Thu, 20 Apr 2017 15:41:11 +0000 (17:41 +0200)
src/stream-tcp-list.c
src/stream-tcp-reassemble.h
src/stream-tcp.c

index 532ba79eabb377de321f8c76a707d4f6ec2f2e28..e3327763ac6916215ed1db391c3d2c1ab40c9450 100644 (file)
@@ -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);
index 7dd4c666f2a562ad954dd014089a975b94d32938..3162ca7132e76149dfc0fa4eaa857727952660a0 100644 (file)
@@ -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
index 9329c4ff2aa5355d3c7770963053720b6a828d25..b77975cd4df442fa43baf2504ac1407acae57c0e 100644 (file)
@@ -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);