From: Juweria Ali Imran (jaliimra) Date: Tue, 23 Jan 2024 20:36:01 +0000 (+0000) Subject: Pull request #4154: stream_tcp: correct labeling of in-sequence and out-of-sequence... X-Git-Tag: 3.1.79.0~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2727dd29b85fae993a9f6a66eccb0f298bd80d1f;p=thirdparty%2Fsnort3.git Pull request #4154: stream_tcp: correct labeling of in-sequence and out-of-sequence packets Merge in SNORT/snort3 from ~JALIIMRA/snort3:ins_oos to master Squashed commit of the following: commit 1868eda57a7b465d0ff589f40a93672eafc2cc5b Author: Juweria Ali Imran Date: Wed Dec 6 08:16:24 2023 -0500 stream_tcp: correct labeling of in-sequence and out-of-sequence packets --- diff --git a/src/stream/tcp/tcp_reassembler.cc b/src/stream/tcp/tcp_reassembler.cc index b31c79559..1c1d2a498 100644 --- a/src/stream/tcp/tcp_reassembler.cc +++ b/src/stream/tcp/tcp_reassembler.cc @@ -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; } diff --git a/src/stream/tcp/tcp_session.cc b/src/stream/tcp/tcp_session.cc index 0c212be91..ddd516545 100644 --- a/src/stream/tcp/tcp_session.cc +++ b/src/stream/tcp/tcp_session.cc @@ -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; } diff --git a/src/stream/tcp/tcp_stream_tracker.cc b/src/stream/tcp/tcp_stream_tracker.cc index e06eec19d..f2cc11a2d 100644 --- a/src/stream/tcp/tcp_stream_tracker.cc +++ b/src/stream/tcp/tcp_stream_tracker.cc @@ -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(); diff --git a/src/stream/tcp/tcp_stream_tracker.h b/src/stream/tcp/tcp_stream_tracker.h index 0c6dc3d9c..d7c41760b 100644 --- a/src/stream/tcp/tcp_stream_tracker.h +++ b/src/stream/tcp/tcp_stream_tracker.h @@ -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: