From 391652049805a7fdf8dcabab9be1d082c1c863cf Mon Sep 17 00:00:00 2001 From: "Davis McPherson -X (davmcphe - XORIANT CORPORATION at Cisco)" Date: Tue, 7 Jan 2025 21:25:03 +0000 Subject: [PATCH] Pull request #4552: stream_tcp: evaluate flush policy on asymmetric connections when the connection closes or the tcp session is cleared Merge in SNORT/snort3 from ~DAVMCPHE/snort3:tcp_asymmetric_ids_tweaks to master Squashed commit of the following: commit 9f263828231d4721e508406852f0d3292c0d6075 Author: davis mcpherson 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 | 19 +++++++++++++++++-- src/stream/tcp/tcp_reassembler.h | 2 -- src/stream/tcp/tcp_stream_tracker.cc | 9 ++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/stream/tcp/tcp_reassembler.cc b/src/stream/tcp/tcp_reassembler.cc index ffaaae66e..6e4595f3b 100644 --- a/src/stream/tcp/tcp_reassembler.cc +++ b/src/stream/tcp/tcp_reassembler.cc @@ -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); diff --git a/src/stream/tcp/tcp_reassembler.h b/src/stream/tcp/tcp_reassembler.h index 1999632f9..5c5d7ec2d 100644 --- a/src/stream/tcp/tcp_reassembler.h +++ b/src/stream/tcp/tcp_reassembler.h @@ -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; diff --git a/src/stream/tcp/tcp_stream_tracker.cc b/src/stream/tcp/tcp_stream_tracker.cc index 554f3d997..89a9c0735 100644 --- a/src/stream/tcp/tcp_stream_tracker.cc +++ b/src/stream/tcp/tcp_stream_tracker.cc @@ -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() -- 2.47.3