From: Russ Combs (rucombs) Date: Mon, 15 Jul 2019 14:01:02 +0000 (-0400) Subject: Merge pull request #1649 in SNORT/snort3 from ~STECHEW/snort3:noack_policy1 to master X-Git-Tag: 3.0.0-258~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c0f5ab1c18d4326bc7b0d3cff457cdcdd0367537;p=thirdparty%2Fsnort3.git Merge pull request #1649 in SNORT/snort3 from ~STECHEW/snort3:noack_policy1 to master Squashed commit of the following: commit 96cde40bbaef426256e5d5607c4f042033df22a9 Author: Steve Chew Date: Tue Jun 18 04:23:40 2019 -0400 stream_tcp: Add no-ack policy to handle flows that have no ACKs for data. no_ack: Purge segment list withouth waiting for ack when using no_ack feature. updated purge segment list fix for no_ack feature updated some comments --- diff --git a/src/stream/libtcp/tcp_stream_tracker.cc b/src/stream/libtcp/tcp_stream_tracker.cc index 5312adf8c..a2070b58a 100644 --- a/src/stream/libtcp/tcp_stream_tracker.cc +++ b/src/stream/libtcp/tcp_stream_tracker.cc @@ -474,6 +474,18 @@ void TcpStreamTracker::update_tracker_ack_recv(TcpSegmentDescriptor& tsd) } } +// In no-ack policy, data is implicitly acked immediately. +void TcpStreamTracker::update_tracker_no_ack_recv(TcpSegmentDescriptor& tsd) +{ + snd_una = snd_nxt = tsd.get_end_seq(); +} + +void TcpStreamTracker::update_tracker_no_ack_sent(TcpSegmentDescriptor& tsd) +{ + r_win_base = tsd.get_end_seq(); + reassembler.flush_on_ack_policy(tsd.get_pkt()); +} + void TcpStreamTracker::update_tracker_ack_sent(TcpSegmentDescriptor& tsd) { // ** this is how we track the last seq number sent diff --git a/src/stream/libtcp/tcp_stream_tracker.h b/src/stream/libtcp/tcp_stream_tracker.h index 945b9276b..f9db25f46 100644 --- a/src/stream/libtcp/tcp_stream_tracker.h +++ b/src/stream/libtcp/tcp_stream_tracker.h @@ -276,6 +276,8 @@ public: virtual void update_tracker_ack_recv(TcpSegmentDescriptor&); virtual void update_tracker_ack_sent(TcpSegmentDescriptor&); + virtual void update_tracker_no_ack_recv(TcpSegmentDescriptor&); + virtual void update_tracker_no_ack_sent(TcpSegmentDescriptor&); virtual bool update_on_3whs_ack(TcpSegmentDescriptor&); virtual bool update_on_rst_recv(TcpSegmentDescriptor&); virtual void update_on_rst_sent(); diff --git a/src/stream/tcp/tcp_module.cc b/src/stream/tcp/tcp_module.cc index 642fcddec..7b03e3858 100644 --- a/src/stream/tcp/tcp_module.cc +++ b/src/stream/tcp/tcp_module.cc @@ -169,6 +169,11 @@ static const Parameter s_params[] = { "max_pdu", Parameter::PT_INT, "1460:32768", "16384", "maximum reassembled PDU size" }, + // FIXIT-H: This should become an API call so that + // an inspector can enable no-ack processing on specific flows + { "no_ack", Parameter::PT_BOOL, nullptr, "false", + "received data is implicitly acked immediately" }, + { "policy", Parameter::PT_ENUM, TCP_POLICIES, "bsd", "determines operating system characteristics like reassembly" }, @@ -280,6 +285,9 @@ bool StreamTcpModule::set(const char*, Value& v, SnortConfig*) else if ( v.is("max_pdu") ) config->paf_max = v.get_uint16(); + else if ( v.is("no_ack") ) + config->no_ack = v.get_bool(); + else if ( v.is("policy") ) config->policy = static_cast< StreamPolicy >( v.get_uint8() + 1 ); diff --git a/src/stream/tcp/tcp_session.cc b/src/stream/tcp/tcp_session.cc index cd7cc283f..390521e4d 100644 --- a/src/stream/tcp/tcp_session.cc +++ b/src/stream/tcp/tcp_session.cc @@ -747,6 +747,8 @@ void TcpSession::handle_data_segment(TcpSegmentDescriptor& tsd) st->normalizer.trim_win_payload( tsd, (st->r_win_base + st->get_snd_wnd() - st->rcv_nxt)); + // FIXIT-H: MSS is not being set on client so packets sent + // to client are not trimmed. if (st->get_mss()) st->normalizer.trim_mss_payload(tsd, st->get_mss()); diff --git a/src/stream/tcp/tcp_state_established.cc b/src/stream/tcp/tcp_state_established.cc index fcf554e8c..ad97cb3b1 100644 --- a/src/stream/tcp/tcp_state_established.cc +++ b/src/stream/tcp/tcp_state_established.cc @@ -79,6 +79,8 @@ bool TcpStateEstablished::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& bool TcpStateEstablished::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk) { trk.update_tracker_ack_sent(tsd); + if ( trk.session->config->no_ack ) + trk.update_tracker_no_ack_recv(tsd); return true; } @@ -86,6 +88,8 @@ bool TcpStateEstablished::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTrac { trk.update_tracker_ack_recv(tsd); trk.session->handle_data_segment(tsd); + if ( trk.session->config->no_ack ) + trk.update_tracker_no_ack_sent(tsd); return true; } diff --git a/src/stream/tcp/tcp_stream_config.h b/src/stream/tcp/tcp_stream_config.h index 5bbf98196..6409ad5a5 100644 --- a/src/stream/tcp/tcp_stream_config.h +++ b/src/stream/tcp/tcp_stream_config.h @@ -69,8 +69,10 @@ public: uint32_t max_consec_small_segs = STREAM_DEFAULT_CONSEC_SMALL_SEGS; uint32_t max_consec_small_seg_size = STREAM_DEFAULT_MAX_SMALL_SEG_SIZE; - int hs_timeout = -1; uint32_t paf_max = 16384; + int hs_timeout = -1; + + bool no_ack; }; #endif