]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4154: stream_tcp: correct labeling of in-sequence and out-of-sequence...
authorJuweria Ali Imran (jaliimra) <jaliimra@cisco.com>
Tue, 23 Jan 2024 20:36:01 +0000 (20:36 +0000)
committerSteven Baigal (sbaigal) <sbaigal@cisco.com>
Tue, 23 Jan 2024 20:36:01 +0000 (20:36 +0000)
Merge in SNORT/snort3 from ~JALIIMRA/snort3:ins_oos to master

Squashed commit of the following:

commit 1868eda57a7b465d0ff589f40a93672eafc2cc5b
Author: Juweria Ali Imran <jaliimra@cisco.com>
Date:   Wed Dec 6 08:16:24 2023 -0500

    stream_tcp: correct labeling of in-sequence and out-of-sequence packets

src/stream/tcp/tcp_reassembler.cc
src/stream/tcp/tcp_session.cc
src/stream/tcp/tcp_stream_tracker.cc
src/stream/tcp/tcp_stream_tracker.h

index b31c79559f73da94e4148fd45af4ac788cf7b9ad..1c1d2a49819a41beb62df72a97c45de468860d6b 100644 (file)
@@ -910,6 +910,7 @@ int32_t TcpReassembler::scan_data_pre_ack(TcpReassemblerState& trs, uint32_t* fl
     }
 
     trs.sos.seglist.cur_sseg = tsn;
+
     if ( tsn )
         update_rcv_nxt(trs, *tsn);
     
@@ -984,9 +985,6 @@ void TcpReassembler::update_rcv_nxt(TcpReassemblerState& trs, TcpSegmentNode& ts
 {
     uint32_t temp = (tsn.i_seq + tsn.i_len);
 
-    if (!trs.tracker->ooo_packet_seen and SEQ_LT(trs.tracker->rcv_nxt, temp))
-        trs.tracker->ooo_packet_seen = true;
-
     if ( SEQ_GT(temp, trs.tracker->rcv_nxt) )
         trs.tracker->rcv_nxt = temp;
 }
index 0c212be911c6c0de9129e92d3e2914d88add7064..ddd516545df6176d6b66a5d47f5955a8825cf2b6 100644 (file)
@@ -178,9 +178,6 @@ void TcpSession::clear_session(bool free_flow_data, bool flush_segments, bool re
     tcp_init = false;
     tcpStats.released++;
 
-    client.ooo_packet_seen = false;
-    server.ooo_packet_seen = false;
-
     if ( flush_segments )
     {
         client.reassembler.flush_queued_segments(flow, true, p);
@@ -437,33 +434,50 @@ void TcpSession::process_tcp_stream(TcpSegmentDescriptor& tsd)
 void TcpSession::update_stream_order(const TcpSegmentDescriptor& tsd, bool aligned)
 {
     TcpStreamTracker* listener = tsd.get_listener();
+    uint32_t seq = tsd.get_seq();
 
     switch ( listener->order )
     {
-    case 0:
-        if ( aligned )
-            tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
-        else
-            listener->order = 1;
-        break;
+        case TcpStreamTracker::IN_SEQUENCE:
+            if ( aligned )
+                tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
+            else if ( SEQ_GT(seq, listener->rcv_nxt) )
+            {
+                listener->order = TcpStreamTracker::NONE;
+                           listener->hole_left_edge = listener->rcv_nxt;
+                           listener->hole_right_edge = seq - 1;
+            }
+            break;
 
-    case 1:
-        if ( aligned )
-        {
-            tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
-            listener->order = 2;
-        }
-        break;
+        case TcpStreamTracker::NONE:
+            if ( aligned )
+            {
+                tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
+                if ( SEQ_GT(tsd.get_end_seq(), listener->hole_right_edge) )
+                               listener->order = TcpStreamTracker::OUT_OF_SEQUENCE;
+                           else
+                               listener->hole_left_edge = tsd.get_end_seq();
+            }
+            else
+            {
+                if ( SEQ_LEQ(seq, listener->hole_right_edge) )
+                           {
+                               if ( SEQ_GT(seq, listener->hole_left_edge) )
+                                   listener->hole_right_edge = seq - 1;
+                    else if ( SEQ_GT(tsd.get_end_seq(), listener->hole_left_edge) )
+                    {
+                        listener->hole_left_edge = tsd.get_end_seq();
+                        tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
+                    }
+                           }
+                // accounting for overlaps when not aligned
+                if ( SEQ_GT(listener->hole_left_edge, listener->hole_right_edge) )
+                    listener->order = TcpStreamTracker::OUT_OF_SEQUENCE;
+            }
+            break;
 
-    default:
-        if ( aligned )
-            tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
-        else
-        {
-            if ( !(flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD) )
-                flow->set_session_flags(SSNFLAG_STREAM_ORDER_BAD);
+        case TcpStreamTracker::OUT_OF_SEQUENCE:
             tsd.set_packet_flags(PKT_STREAM_ORDER_BAD);
-        }
     }
 }
 
@@ -502,7 +516,7 @@ int TcpSession::process_tcp_data(TcpSegmentDescriptor& tsd)
 
         if ( tsd.is_data_segment() )
         {
-            update_stream_order(tsd, !listener->ooo_packet_seen);
+            update_stream_order(tsd, true);
             process_tcp_stream(tsd);
             return STREAM_ALIGNED;
         }
index e06eec19d944c1024a4df3149b2a943866216760..f2cc11a2d5af10aa7f6c58052d3113465f098692 100644 (file)
@@ -242,7 +242,7 @@ void TcpStreamTracker::init_tcp_state()
     fin_seq_status = TcpStreamTracker::FIN_NOT_SEEN;
     fin_seq_set = false;
     rst_pkt_sent = false;
-    order = 0;
+    order = TcpStreamTracker::IN_SEQUENCE;
     held_packet = null_iterator;
     flush_policy = STREAM_FLPOLICY_IGNORE;
     reassembler.reset();
index 0c6dc3d9c1b4149dc907d38c31b8bad84a5617db..d7c41760bb601750a64c15744b359f7c1f2d4d2e 100644 (file)
@@ -85,6 +85,8 @@ public:
         TCP_MAX_EVENTS
     };
 
+    enum PacketOrder : uint8_t { OUT_OF_SEQUENCE, IN_SEQUENCE, NONE };
+
     enum FinSeqNumStatus : uint8_t { FIN_NOT_SEEN, FIN_WITH_SEQ_SEEN, FIN_WITH_SEQ_ACKED };
 
     TcpStreamTracker(bool client);
@@ -325,13 +327,15 @@ public:
     uint16_t rcv_up = 0;  // RCV.UP  - receive urgent pointer
 
     uint32_t held_pkt_seq = 0;
+    uint32_t hole_left_edge = 0;   // First left hole
+    uint32_t hole_right_edge = 0;
+
     TcpState tcp_state;
     TcpEvent tcp_event = TCP_MAX_EVENTS;
 
     bool client_tracker;
     bool require_3whs = false;
     bool rst_pkt_sent = false;
-    bool ooo_packet_seen = false;
     bool midstream_initial_ack_flush = false;
 
 // FIXIT-L make these non-public
@@ -344,7 +348,7 @@ public:
     uint32_t small_seg_count = 0;
     uint32_t max_queue_seq_nxt = 0; // next expected sequence once queue limit is exceeded
     uint8_t max_queue_exceeded = MQ_NONE;
-    uint8_t order = 0;
+    uint8_t order = IN_SEQUENCE;
     FinSeqNumStatus fin_seq_status = TcpStreamTracker::FIN_NOT_SEEN;
 
 protected: