]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4552: stream_tcp: evaluate flush policy on asymmetric connections when...
authorDavis McPherson -X (davmcphe - XORIANT CORPORATION at Cisco) <davmcphe@cisco.com>
Tue, 7 Jan 2025 21:25:03 +0000 (21:25 +0000)
committerSteven Baigal (sbaigal) <sbaigal@cisco.com>
Tue, 7 Jan 2025 21:25:03 +0000 (21:25 +0000)
Merge in SNORT/snort3 from ~DAVMCPHE/snort3:tcp_asymmetric_ids_tweaks to master

Squashed commit of the following:

commit 9f263828231d4721e508406852f0d3292c0d6075
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Thu Nov 21 13:57:05 2024 -0500

    stream_tcp: evaluate flush policy on asymmetric connections when the connection closes or the tcp session is cleared

    check for asymmetric connection when doing a final flush

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

index ffaaae66e726225c7ace03be5dcda53e060f9fa1..6e4595f3bb70ad9fa1afa859448079720a9a0d70 100644 (file)
@@ -453,13 +453,23 @@ void TcpReassemblerBase::final_flush(Packet* p, uint32_t dir)
 {
     tracker.set_tf_flags(TF_FORCE_FLUSH);
 
-    if ( flush_stream(p, dir, true) )
+    // if the flow is one-way (asymmetric) then eval flush on asymmetric connection first
+    if ( !p->flow->two_way_traffic() )
+    {
+        eval_asymmetric_flush(p);
+    }
+
+    uint32_t flushed = flush_stream(p, dir, true);
+    if ( flushed  )
     {
         if ( server_side )
             tcpStats.server_cleanups++;
         else
             tcpStats.client_cleanups++;
 
+        if ( !p->flow->two_way_traffic() )
+            tcpStats.flush_on_asymmetric_flow++;
+
         purge_flushed_ackd();
     }
     tracker.clear_tf_flags(TF_FORCE_FLUSH);
@@ -536,6 +546,10 @@ void TcpReassemblerBase::flush_queued_segments(Flow* flow, bool clear, Packet* p
     }
     else
     {
+        // if this is an asymmetric flow and no data has been scanned then initialize paf
+        if ( !flow->two_way_traffic() and !paf.paf_initialized() )
+            initialize_paf();
+
         Packet* pdu = get_packet(flow, packet_dir, server_side);
 
         bool pending = clear and paf.paf_initialized();
@@ -600,7 +614,8 @@ bool TcpReassemblerBase::final_flush_on_fin(int32_t flush_amt, Packet *p, FinSeq
 
 bool TcpReassemblerBase::asymmetric_flow_flushed(uint32_t flushed, snort::Packet *p)
 {
-    bool asymmetric = flushed && seglist.seg_count && !p->flow->two_way_traffic() && !p->ptrs.tcph->is_syn();
+    bool asymmetric = flushed && seglist.seg_count && !p->flow->two_way_traffic()
+        && ( !p->ptrs.tcph or !p->ptrs.tcph->is_syn() );
     if ( asymmetric )
     {
         TcpStreamTracker::TcpState peer = tracker.session->get_peer_state(tracker);
index 1999632f9368ad2a8ffa31be25edc902fb4d5b0e..5c5d7ec2db480f1ab549cefb920051334bf19ff1 100644 (file)
@@ -178,8 +178,6 @@ public:
 
     virtual void initialize_paf() override
     {
-        assert( get_flush_policy() != STREAM_FLPOLICY_IGNORE );
-
         // only initialize if we have a data segment queued
         if ( !seglist.head )
             return;
index 554f3d997b21cc9c8b107f14f1e6fa3e063a6beb..89a9c07356f367bd7f7b5beedf045cb80f7b7945 100644 (file)
@@ -834,7 +834,7 @@ int32_t TcpStreamTracker::kickstart_asymmetric_flow(const TcpSegmentDescriptor&
     else
         reassembler->reset_paf();
 
-    reassembler->eval_flush_policy_on_data(tsd.get_pkt());
+    reassembler->eval_asymmetric_flush(tsd.get_pkt());
 
     int32_t space_left = max_queued_bytes - seglist.get_seg_bytes_total();
 
@@ -860,9 +860,12 @@ void TcpStreamTracker::perform_fin_recv_flush(TcpSegmentDescriptor& tsd)
     if ( tsd.is_data_segment() )
         session->handle_data_segment(tsd);
 
+    Packet* p = tsd.get_pkt();
     if ( flush_policy == STREAM_FLPOLICY_ON_DATA and SEQ_EQ(tsd.get_end_seq(), rcv_nxt)
-         and !tsd.get_flow()->searching_for_service() )
-        reassembler->finish_and_final_flush(tsd.get_flow(), true, tsd.get_pkt());
+         and !p->flow->searching_for_service() )
+        reassembler->finish_and_final_flush(p->flow, true, p);
+    else if ( !p->flow->two_way_traffic() )
+        reassembler->eval_asymmetric_flush(p);
 }
 
 uint32_t TcpStreamTracker::perform_partial_flush()