]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #702 in SNORT/snort3 from ooofin to master
authorShawn Turner (shaturne) <shaturne@cisco.com>
Fri, 11 Nov 2016 15:25:35 +0000 (10:25 -0500)
committerShawn Turner (shaturne) <shaturne@cisco.com>
Fri, 11 Nov 2016 15:25:35 +0000 (10:25 -0500)
Squashed commit of the following:

commit 295c5f1b4c1936e3758dce727d3f2f4097d8a193
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Mon Sep 12 16:24:08 2016 -0400

    ooofin changes

12 files changed:
src/stream/libtcp/tcp_state_machine.cc
src/stream/libtcp/tcp_stream_tracker.cc
src/stream/libtcp/tcp_stream_tracker.h
src/stream/tcp/tcp_reassembler.cc
src/stream/tcp/tcp_session.cc
src/stream/tcp/tcp_session.h
src/stream/tcp/tcp_state_close_wait.cc
src/stream/tcp/tcp_state_closing.cc
src/stream/tcp/tcp_state_established.cc
src/stream/tcp/tcp_state_syn_sent.cc
src/stream/tcp/tcp_state_time_wait.cc
src/stream/tcp/tcp_tracker.cc

index 11576fae6cb5171ceda97fd6d68b9499dec32f23..952b6828c4c2e91327ed58d51a87d658accc2c12 100644 (file)
@@ -56,6 +56,15 @@ bool TcpStateMachine::eval(TcpSegmentDescriptor& tsd, TcpStreamTracker& talker,
             listener.set_tcp_event(tsd);
             tcp_state_handlers[ tcp_state ]->eval(tsd, listener);
             tcp_state_handlers[ tcp_state ]->do_post_sm_packet_actions(tsd, listener);
+            if( listener.process_inorder_fin() )
+            {
+                //FIN is in order or we need to process FIN from state_queue
+                tcp_state_handlers[ tcp_state ]->eval(tsd, listener);
+                tcp_state = talker.get_tcp_state( );
+                tcp_state_handlers[ tcp_state ]->eval(tsd, talker);
+                tcp_state_handlers[ tcp_state ]->do_post_sm_packet_actions(tsd, listener);
+                listener.inorder_fin = false;
+            }
             return true;
         }
 
index 866fdae4e90094dc4eca50f3ccea0d6791338e92..88ccbbf8b2bf84d35d8190c2e63aa92aec1c518d 100644 (file)
@@ -75,7 +75,7 @@ TcpStreamTracker::TcpEvent TcpStreamTracker::set_tcp_event(TcpSegmentDescriptor&
             tcp_event = TCP_SYN_ACK_SENT_EVENT;
         else if ( tcph->is_rst() )
             tcp_event = TCP_RST_SENT_EVENT;
-       else if ( tcph->is_fin( ) )
+        else if ( tcph->is_fin( ) )
             tcp_event = TCP_FIN_SENT_EVENT;
         else if ( tcph->is_ack() || tcph->is_psh() )
         {
index 90f879e3081c99871c0ecec90685b364d840c225..7640562364e16f4f31504d8ed5419570a01cc10b 100644 (file)
@@ -323,6 +323,11 @@ public:
         return rst_pkt_sent;
     }
 
+    bool process_inorder_fin() const
+    {
+        return inorder_fin;
+    }
+
     virtual void init_tcp_state() =  0;
     virtual void init_toolbox() = 0;
 
@@ -373,6 +378,7 @@ public:
 
     uint32_t fin_final_seq = 0;
     bool rst_pkt_sent = false;
+    bool inorder_fin = false;
 
 // FIXIT-L make these non-public
 public:
index a81add4c926e79ac8f25625c7e280a06613df1c3..1874bf5ee24186692ffe5ba799cfaff269984d11 100644 (file)
@@ -523,7 +523,7 @@ int TcpReassembler::flush_data_segments(Packet* p, uint32_t toSeq)
                 seglist.next = tsn->next;
 
             // FIXIT-L this is suboptimal - better to exclude fin from toSeq
-            if ( !tracker->fin_set() or SEQ_LT(toSeq, tracker->fin_final_seq) )
+            if ( !tracker->fin_set() or SEQ_LEQ(toSeq, tracker->fin_final_seq) )
                 tracker->set_tf_flags(TF_MISSING_PKT);
 
             break;
index fd590da874f2d4758f02ebd3ed68b738452d73b1..507271b87540800b20fd4b5362341fc9a8bda565 100644 (file)
@@ -357,6 +357,17 @@ void TcpSession::process_tcp_stream(TcpSegmentDescriptor& tsd)
         listener->reassembler->set_overlap_count(0);
     }
 }
+void TcpSession::check_fin_transition_status(TcpSegmentDescriptor& tsd)
+{
+    if((tsd.get_seg_len() != 0) && 
+            SEQ_EQ(listener->get_fin_final_seq(), listener->r_nxt_ack))
+    {
+        listener->set_tcp_event(TcpStreamTracker::TCP_FIN_RECV_EVENT);
+        talker->set_tcp_event(TcpStreamTracker::TCP_FIN_SENT_EVENT);
+        listener->inorder_fin = true;
+    }
+}
+
 
 int TcpSession::process_tcp_data(TcpSegmentDescriptor& tsd)
 {
@@ -803,6 +814,8 @@ void TcpSession::handle_data_segment(TcpSegmentDescriptor& tsd)
                 or (config->policy == StreamPolicy::OS_PROXY))
         {
             process_tcp_data(tsd);
+            //Check if all segments are received. Process FIN transition
+            check_fin_transition_status(tsd);
         }
         else
         {
index e9d8dfa3eecebcc3d2c79f36dd5bb71e7cb0dc66..fe758f6f628cf2c7dc04174939aaf0cc7db6b207 100644 (file)
@@ -77,6 +77,7 @@ public:
 private:
     void set_os_policy() override;
     bool flow_exceeds_config_thresholds(TcpSegmentDescriptor&);
+    void check_fin_transition_status(TcpSegmentDescriptor&);
     void process_tcp_stream(TcpSegmentDescriptor&);
     int process_tcp_data(TcpSegmentDescriptor&);
     void process_tcp_packet(TcpSegmentDescriptor&);
index abace5fccb27ee246e975cd237f554995e38a2e9..e7115330375318f17b145e44e1716c5f1597bffd 100644 (file)
@@ -107,9 +107,15 @@ bool TcpStateCloseWait::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tr
 bool TcpStateCloseWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     Flow* flow = tsd.get_flow();
+    if( trk.process_inorder_fin() )
+    {
+        trk.update_on_fin_recv(tsd);
+        return default_state_action(tsd, trk);
+    }
 
     trk.update_tracker_ack_recv(tsd);
-    if ( SEQ_GEQ(tsd.get_seg_seq(), trk.get_fin_final_seq() ) )
+
+    if ( SEQ_GT(tsd.get_seg_seq(), trk.get_fin_final_seq() ) )
     {
         DebugMessage(DEBUG_STREAM_STATE, "FIN beyond previous, ignoring\n");
         trk.session->tel.set_tcp_event(EVENT_BAD_FIN);
index 80b6d948d8e9c1df98c32e45c8e380a37ad3e16e..e5ecf2233cd1dc2d2822951c7eb11bbe30bef452 100644 (file)
@@ -112,7 +112,7 @@ bool TcpStateClosing::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
     Flow* flow = tsd.get_flow();
 
     trk.update_tracker_ack_recv(tsd);
-    if ( SEQ_GEQ(tsd.get_seg_seq(), trk.get_fin_final_seq() ) )
+    if ( SEQ_GT(tsd.get_seg_seq(), trk.get_fin_final_seq() ) )
     {
         DebugMessage(DEBUG_STREAM_STATE, "FIN beyond previous, ignoring\n");
         trk.session->tel.set_tcp_event(EVENT_BAD_FIN);
@@ -160,7 +160,6 @@ bool TcpStateClosing::do_post_sm_packet_actions(TcpSegmentDescriptor& tsd, TcpSt
 {
     trk.session->update_paws_timestamps(tsd);
     trk.session->check_for_window_slam(tsd);
-
     return true;
 }
 
index 8b26d448dc2525e57b4b4a157cdc93a69e6bccbc..3da4897b860e1613b3208595c4032a74cb02c0dc 100644 (file)
@@ -104,9 +104,20 @@ bool TcpStateEstablished::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTrac
 
 bool TcpStateEstablished::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
+    TcpStreamTracker* listener = nullptr;
+
+    if ( tsd.get_pkt()->is_from_client() )
+        listener = trk.session->server;
+    else
+        listener = trk.session->client;
     trk.update_on_fin_sent(tsd);
-    trk.session->eof_handle(tsd.get_pkt());
-    trk.set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT1);
+
+    if( SEQ_EQ(tsd.get_end_seq(), (listener->r_nxt_ack +  tsd.get_seg_len())) || listener->process_inorder_fin() 
+            || !listener->is_segment_seq_valid(tsd) )
+    {
+        trk.session->eof_handle(tsd.get_pkt());
+        trk.set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT1);
+    }
 
     return default_state_action(tsd, trk);
 }
@@ -116,13 +127,22 @@ bool TcpStateEstablished::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
     trk.update_tracker_ack_recv(tsd);
     if ( tsd.get_seg_len() > 0 )
     {
-        trk.session->handle_data_segment(tsd);
-        trk.flush_data_on_fin_recv(tsd);
+         trk.session->handle_data_segment(tsd);
+         trk.flush_data_on_fin_recv(tsd);
     }
-    if ( trk.update_on_fin_recv(tsd) )
+    if( (tsd.get_end_seq() == trk.r_nxt_ack) || !trk.is_segment_seq_valid(tsd) )
     {
-        trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
-        trk.set_tcp_state(TcpStreamTracker::TCP_CLOSE_WAIT);
+        if ( trk.update_on_fin_recv(tsd) )
+        {
+            trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+            trk.set_tcp_state(TcpStreamTracker::TCP_CLOSE_WAIT);
+        }
+    }
+    else
+    {
+        //Out of Order FIN received
+        if ( trk.fin_final_seq == 0 )
+            trk.fin_final_seq = tsd.get_seg_seq();
     }
 
     return default_state_action(tsd, trk);
index 881e8b0e30b2214b50cb9af32799ebc8850aecbd..4a1e04064679c2457a76c72746327c7d9caccc40 100644 (file)
@@ -89,6 +89,7 @@ bool TcpStateSynSent::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
     trk.session->update_timestamp_tracking(tsd);
     trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
     trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    trk.r_nxt_ack = tsd.get_seg_ack();
 
     return default_state_action(tsd, trk);
 }
index 0900b7fe07c6d45fdbecc6d4452f7920c40d7fd0..241489db538922e35c17b6811b81062888316e9f 100644 (file)
@@ -103,7 +103,7 @@ bool TcpStateTimeWait::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
 bool TcpStateTimeWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.update_tracker_ack_recv(tsd);
-    if ( SEQ_GEQ(tsd.get_seg_seq(), trk.get_fin_final_seq() ) )
+    if ( SEQ_GT(tsd.get_seg_seq(), trk.get_fin_final_seq() ) )
     {
         DebugMessage(DEBUG_STREAM_STATE, "FIN beyond previous, ignoring\n");
         trk.session->tel.set_tcp_event(EVENT_BAD_FIN);
index 9f21b89c40febab58b559a7414f03c302b26e450..107f40eafd4a44d9b6cc970e9daef4f1e9f32d30 100644 (file)
@@ -492,7 +492,7 @@ bool TcpTracker::update_on_fin_recv(TcpSegmentDescriptor& tsd)
 
     // set final seq # any packet rx'ed with seq > is bad
     if ( !fin_set() )
-        fin_final_seq = tsd.get_end_seq() + 1;
+        fin_final_seq = tsd.get_end_seq();
 
     return true;
 }