]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1187 in SNORT/snort3 from stream_perf_optimization to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 13 Apr 2018 15:42:18 +0000 (11:42 -0400)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 13 Apr 2018 15:42:18 +0000 (11:42 -0400)
Squashed commit of the following:

commit aba95f74f79e56d0752ceab71a6da315596d0aad
Author: Russ Combs <rucombs@cisco.com>
Date:   Fri Mar 30 17:09:05 2018 -0400

    stream_tcp: refactor tcp normalizer and reassembler to eliminate dynamic heap allocations per flow

40 files changed:
src/stream/libtcp/tcp_state_handler.cc
src/stream/libtcp/tcp_state_handler.h
src/stream/libtcp/tcp_stream_session.cc
src/stream/libtcp/tcp_stream_session.h
src/stream/libtcp/tcp_stream_tracker.cc
src/stream/libtcp/tcp_stream_tracker.h
src/stream/tcp/CMakeLists.txt
src/stream/tcp/ips_stream_reassemble.cc
src/stream/tcp/ips_stream_size.cc
src/stream/tcp/segment_overlap_editor.cc
src/stream/tcp/segment_overlap_editor.h
src/stream/tcp/tcp_debug_trace.h
src/stream/tcp/tcp_module.h
src/stream/tcp/tcp_normalizer.cc
src/stream/tcp/tcp_normalizer.h
src/stream/tcp/tcp_normalizers.cc
src/stream/tcp/tcp_normalizers.h
src/stream/tcp/tcp_reassembler.cc
src/stream/tcp/tcp_reassembler.h
src/stream/tcp/tcp_reassemblers.cc
src/stream/tcp/tcp_reassemblers.h
src/stream/tcp/tcp_segment_node.cc
src/stream/tcp/tcp_segment_node.h
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_closed.cc
src/stream/tcp/tcp_state_closing.cc
src/stream/tcp/tcp_state_established.cc
src/stream/tcp/tcp_state_fin_wait1.cc
src/stream/tcp/tcp_state_fin_wait2.cc
src/stream/tcp/tcp_state_last_ack.cc
src/stream/tcp/tcp_state_listen.cc
src/stream/tcp/tcp_state_none.cc
src/stream/tcp/tcp_state_syn_recv.cc
src/stream/tcp/tcp_state_time_wait.cc
src/stream/tcp/tcp_stream_state_machine.h
src/stream/tcp/tcp_tracker.cc [deleted file]
src/stream/tcp/tcp_tracker.h [deleted file]
src/stream/tcp/test/tcp_normalizer_test.cc

index 7392b88a7f2934d8ad97268344075d7ec0c1e3ed..a89e9ecfbaf4148a2e30a232d1592405710e0d08 100644 (file)
@@ -28,7 +28,7 @@
 #include <iostream>
 
 #include "main/snort_debug.h"
-
+#include "tcp_segment_descriptor.h"
 #include "tcp_state_machine.h"
 
 #ifdef UNIT_TEST
index fe5380243d52ccf5ad92da32efeed2bae062c82d..6b8d0c8babfa6457c937e9d4bd92deb0386f947e 100644 (file)
@@ -23,9 +23,9 @@
 #define TCP_STATE_HANDLER_H
 
 #include "protocols/tcp.h"
-#include "stream/libtcp/tcp_segment_descriptor.h"
 #include "stream/libtcp/tcp_stream_tracker.h"
 
+class TcpSegmentDescriptor;
 class TcpStateMachine;
 
 class TcpStateHandler
index 7f07e60f004dc20e7e75210dca67c7c88d347ede..df9bc4099849aa24b5cf3eb5abb1052cb407adc5 100644 (file)
@@ -40,14 +40,12 @@ const char* const flush_policy_names[] =
 };
 #endif
 
+TcpStreamSession::TcpStreamSession(Flow* f)
+    : Session(f), client(true), server(false)
+{ }
+
 TcpStreamSession::~TcpStreamSession()
-{
-    if (tcp_init)
-    {
-        delete client;
-        delete server;
-    }
-}
+{ }
 
 void TcpStreamSession::init_new_tcp_session(TcpSegmentDescriptor& tsd)
 {
@@ -96,8 +94,8 @@ void TcpStreamSession::update_session_on_server_packet(TcpSegmentDescriptor& tsd
     DebugMessage(DEBUG_STREAM_STATE, "Stream: Updating on packet from server\n");
 
     flow->set_session_flags(SSNFLAG_SEEN_SERVER);
-    talker = server;
-    listener = client;
+    talker = &server;
+    listener = &client;
 
     /* If we picked this guy up midstream, finish the initialization */
     if ( !( flow->session_state & STREAM_STATE_ESTABLISHED )
@@ -126,8 +124,8 @@ void TcpStreamSession::update_session_on_client_packet(TcpSegmentDescriptor& tsd
 
     /* if we got here we had to see the SYN already... */
     flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
-    talker = client;
-    listener = server;
+    talker = &client;
+    listener = &server;
 
     if ( !( flow->session_state & STREAM_STATE_ESTABLISHED )
         && ( flow->session_state & STREAM_STATE_MIDSTREAM ) )
@@ -148,10 +146,10 @@ uint8_t TcpStreamSession::get_reassembly_direction()
 {
     uint8_t dir = SSN_DIR_NONE;
 
-    if (server->flush_policy != STREAM_FLPOLICY_IGNORE)
+    if (server.get_flush_policy() != STREAM_FLPOLICY_IGNORE)
         dir |= SSN_DIR_FROM_CLIENT;
 
-    if (client->flush_policy != STREAM_FLPOLICY_IGNORE)
+    if (client.get_flush_policy() != STREAM_FLPOLICY_IGNORE)
         dir |= SSN_DIR_FROM_SERVER;
 
     return dir;
@@ -161,13 +159,13 @@ bool TcpStreamSession::is_sequenced(uint8_t dir)
 {
     if (dir & SSN_DIR_FROM_CLIENT)
     {
-        if ( server->get_tf_flags() & ( TF_MISSING_PREV_PKT | TF_PKT_MISSED ) )
+        if ( server.get_tf_flags() & ( TF_MISSING_PREV_PKT | TF_PKT_MISSED ) )
             return false;
     }
 
     if ( dir & SSN_DIR_FROM_SERVER )
     {
-        if ( client->get_tf_flags() & ( TF_MISSING_PREV_PKT | TF_PKT_MISSED ) )
+        if ( client.get_tf_flags() & ( TF_MISSING_PREV_PKT | TF_PKT_MISSED ) )
             return false;
     }
 
@@ -180,22 +178,22 @@ uint8_t TcpStreamSession::missing_in_reassembled(uint8_t dir)
 {
     if (dir & SSN_DIR_FROM_CLIENT)
     {
-        if ( (server->get_tf_flags() & TF_MISSING_PKT)
-            && (server->get_tf_flags() & TF_MISSING_PREV_PKT))
+        if ( (server.get_tf_flags() & TF_MISSING_PKT)
+            && (server.get_tf_flags() & TF_MISSING_PREV_PKT))
             return SSN_MISSING_BOTH;
-        else if (server->get_tf_flags() & TF_MISSING_PREV_PKT)
+        else if (server.get_tf_flags() & TF_MISSING_PREV_PKT)
             return SSN_MISSING_BEFORE;
-        else if (server->get_tf_flags() & TF_MISSING_PKT)
+        else if (server.get_tf_flags() & TF_MISSING_PKT)
             return SSN_MISSING_AFTER;
     }
     else if (dir & SSN_DIR_FROM_SERVER)
     {
-        if ((client->get_tf_flags() & TF_MISSING_PKT)
-            && (client->get_tf_flags() & TF_MISSING_PREV_PKT))
+        if ((client.get_tf_flags() & TF_MISSING_PKT)
+            && (client.get_tf_flags() & TF_MISSING_PREV_PKT))
             return SSN_MISSING_BOTH;
-        else if (client->get_tf_flags() & TF_MISSING_PREV_PKT)
+        else if (client.get_tf_flags() & TF_MISSING_PREV_PKT)
             return SSN_MISSING_BEFORE;
-        else if (client->get_tf_flags() & TF_MISSING_PKT)
+        else if (client.get_tf_flags() & TF_MISSING_PKT)
             return SSN_MISSING_AFTER;
     }
 
@@ -206,13 +204,13 @@ bool TcpStreamSession::are_packets_missing(uint8_t dir)
 {
     if (dir & SSN_DIR_FROM_CLIENT)
     {
-        if (server->get_tf_flags() & TF_PKT_MISSED)
+        if (server.get_tf_flags() & TF_PKT_MISSED)
             return true;
     }
 
     if (dir & SSN_DIR_FROM_SERVER)
     {
-        if (client->get_tf_flags() & TF_PKT_MISSED)
+        if (client.get_tf_flags() & TF_PKT_MISSED)
             return true;
     }
 
@@ -223,7 +221,6 @@ void TcpStreamSession::update_direction(char dir, const SfIp* ip, uint16_t port)
 {
     SfIp tmpIp;
     uint16_t tmpPort;
-    TcpStreamTracker* tracker;
 
     if (flow->client_ip.equals(*ip) && (flow->client_port == port))
     {
@@ -251,7 +248,7 @@ void TcpStreamSession::update_direction(char dir, const SfIp* ip, uint16_t port)
     flow->server_port = tmpPort;
 
     SwapPacketHeaderFoo( );
-    tracker = client;
+    TcpStreamTracker& tracker = client;
     client = server;
     server = tracker;
 }
@@ -260,25 +257,20 @@ void TcpStreamSession::update_direction(char dir, const SfIp* ip, uint16_t port)
 // packet / PDU split because PDU rules won't run on raw packets
 bool TcpStreamSession::add_alert(Packet* p, uint32_t gid, uint32_t sid)
 {
-    TcpStreamTracker* st;
+    TcpStreamTracker& st = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ? server : client;
     StreamAlertInfo* ai;
 
-    if (p->ptrs.ip_api.get_src()->equals(flow->client_ip))
-        st = server;
-    else
-        st = client;
-
-    if (st->alert_count >= MAX_SESSION_ALERTS)
+    if (st.alert_count >= MAX_SESSION_ALERTS)
         return false;
 
-    ai = st->alerts + st->alert_count;
+    ai = st.alerts + st.alert_count;
     ai->gid = gid;
     ai->sid = sid;
     ai->seq = 0;
     ai->event_id = 0;
     ai->event_second = 0;
 
-    st->alert_count++;
+    st.alert_count++;
 
     return true;
 }
@@ -289,22 +281,14 @@ bool TcpStreamSession::check_alerted(Packet* p, uint32_t gid, uint32_t sid)
     if (!(p->packet_flags & PKT_REBUILT_STREAM))
         return false;
 
-    TcpStreamTracker* st;
-
-    if (p->ptrs.ip_api.get_src()->equals(flow->client_ip))
-        st = server;
-    else
-        st = client;
-
-    for (int i = 0; i < st->alert_count; i++)
+    TcpStreamTracker& st = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ? server : client;
+    for (int i = 0; i < st.alert_count; i++)
     {
         /*  This is a rebuilt packet and if we've seen this alert before,
          *  return that we have previously alerted on original packet.
          */
-        if (st->alerts[i].gid == gid && st->alerts[i].sid == sid)
-        {
+        if (st.alerts[i].gid == gid && st.alerts[i].sid == sid)
             return true;
-        }
     }
 
     return false;
@@ -313,20 +297,12 @@ bool TcpStreamSession::check_alerted(Packet* p, uint32_t gid, uint32_t sid)
 int TcpStreamSession::update_alert(Packet* p, uint32_t gid, uint32_t sid,
     uint32_t event_id, uint32_t event_second)
 {
-    TcpStreamTracker* st;
-    int i;
-    uint32_t seq_num;
+    uint32_t seq_num = 0;
+    TcpStreamTracker& st = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ? server : client;
 
-    if (p->ptrs.ip_api.get_src()->equals(flow->client_ip))
-        st = server;
-    else
-        st = client;
-
-    seq_num = 0;
-
-    for (i = 0; i < st->alert_count; i++)
+    for (unsigned i = 0; i < st.alert_count; i++)
     {
-        StreamAlertInfo* ai = st->alerts + i;
+        StreamAlertInfo* ai = st.alerts + i;
 
         if (ai->gid == gid && ai->sid == sid && SEQ_EQ(ai->seq, seq_num))
         {
@@ -424,11 +400,8 @@ void TcpStreamSession::reset()
 
 bool TcpStreamSession::setup(Packet*)
 {
-    // FIXIT-L this it should not be necessary to reset here
-    reset();
-
-    client->init_tcp_state();
-    server->init_tcp_state();
+    client.init_tcp_state();
+    server.init_tcp_state();
     lws_init = tcp_init = false;
     generate_3whs_alert = true;
     pkt_action_mask = ACTION_NOTHING;
@@ -444,6 +417,8 @@ bool TcpStreamSession::setup(Packet*)
 void TcpStreamSession::cleanup(Packet* p)
 {
     clear_session(true, true, false, p);
+    client.normalizer.reset();
+    server.reassembler.reset();
 }
 
 void TcpStreamSession::clear()
@@ -451,36 +426,37 @@ void TcpStreamSession::clear()
     if ( tcp_init )
         // this does NOT flush data
         clear_session( true, false, false );
+
     TcpHAManager::process_deletion(flow);
 }
 
 void TcpStreamSession::set_splitter(bool to_server, StreamSplitter* ss)
 {
-    TcpStreamTracker* trk = ( to_server ) ? server : client;
+    TcpStreamTracker& trk = ( to_server ) ? server : client;
 
-    trk->set_splitter(ss);
+    trk.set_splitter(ss);
 }
 
 uint16_t TcpStreamSession::get_mss(bool to_server) const
 {
-    TcpStreamTracker* trk = (to_server) ? client : server;
+    const TcpStreamTracker& trk = (to_server) ? client : server;
 
-    return trk->get_mss();
+    return trk.get_mss();
 }
 
 uint8_t TcpStreamSession::get_tcp_options_len(bool to_server) const
 {
-    TcpStreamTracker* trk = (to_server) ? client : server;
+    const TcpStreamTracker& trk = (to_server) ? client : server;
 
-    return trk->get_tcp_options_len();
+    return trk.get_tcp_options_len();
 }
 
 StreamSplitter* TcpStreamSession::get_splitter(bool to_server)
 {
     if ( to_server )
-        return server->splitter;
+        return server.get_splitter();
     else
-        return client->splitter;
+        return client.get_splitter();
 }
 
 void TcpStreamSession::start_proxy()
@@ -513,9 +489,9 @@ void TcpStreamSession::print()
     LogMessage("    client port:        %d\n", flow->client_port);
     LogMessage("    flags:              0x%X\n", flow->get_session_flags());
     LogMessage("Client Tracker:\n");
-    client->print();
+    client.print();
     LogMessage("Server Tracker:\n");
-    server->print();
+    server.print();
 }
 
 
index 9bcfd30c50d58f425c1313eb1576efb55073f414..b106c4df986450bdbb21c5f13cdbd4438473ac55 100644 (file)
@@ -25,6 +25,7 @@
 #include "detection/detection_engine.h"
 #include "flow/session.h"
 #include "protocols/ipv6.h"
+
 #include "stream/libtcp/tcp_stream_tracker.h"
 #include "stream/tcp/tcp_stream_config.h"
 
@@ -38,7 +39,6 @@ extern const char* const flush_policy_names[];
 class TcpStreamSession : public Session
 {
 public:
-    TcpStreamSession(snort::Flow* flow) : Session(flow) { }
     ~TcpStreamSession() override;
 
     bool setup(snort::Packet*) override;
@@ -130,8 +130,8 @@ public:
     virtual void handle_data_segment(TcpSegmentDescriptor&) { }
     virtual bool validate_packet_established_session(TcpSegmentDescriptor&) { return true; }
 
-    TcpStreamTracker* client = nullptr;
-    TcpStreamTracker* server = nullptr;
+    TcpStreamTracker client;
+    TcpStreamTracker server;
     bool lws_init = false;
     bool tcp_init = false;
     uint32_t pkt_action_mask = ACTION_NOTHING;
@@ -153,6 +153,7 @@ private:
     uint16_t real_dst_port = 0;
 
 protected:
+    TcpStreamSession(snort::Flow*);
     virtual void set_os_policy() = 0;
 
     TcpStreamTracker* talker = nullptr;
index 7a83f488a2846ce27ea0b24446c77dd344c29e28..47ddc23a06dd8bdd65b9ab0bfd251b71a1d2cd05 100644 (file)
 
 #include "tcp_stream_tracker.h"
 
+#include "log/messages.h"
+#include "profiler/profiler_defs.h"
 #include "protocols/eth.h"
 #include "stream/stream.h"
 #include "stream/tcp/tcp_module.h"
+#include "stream/tcp/tcp_normalizers.h"
+#include "stream/tcp/tcp_reassemblers.h"
+#include "stream/tcp/segment_overlap_editor.h"
 
 using namespace snort;
 
@@ -51,7 +56,11 @@ const char* tcp_event_names[] = {
 
 TcpStreamTracker::TcpStreamTracker(bool client) :
     client_tracker(client), tcp_state(client ? TCP_STATE_NONE : TCP_LISTEN)
+{ }
+
+TcpStreamTracker::~TcpStreamTracker()
 {
+    delete splitter;
 }
 
 TcpStreamTracker::TcpEvent TcpStreamTracker::set_tcp_event(TcpSegmentDescriptor& tsd)
@@ -173,3 +182,503 @@ void TcpStreamTracker::cache_mac_address(TcpSegmentDescriptor& tsd, uint8_t dire
     }
 }
 
+void TcpStreamTracker::init_tcp_state()
+{
+    tcp_state = ( client_tracker ) ?
+        TcpStreamTracker::TCP_STATE_NONE : TcpStreamTracker::TCP_LISTEN;
+    flush_policy = STREAM_FLPOLICY_IGNORE;
+    memset(&paf_state, 0, sizeof(paf_state));
+    snd_una = snd_nxt = snd_wnd = 0;
+    r_nxt_ack = r_win_base = iss = ts_last = ts_last_packet = 0;
+    small_seg_count = wscale = mss = 0;
+    tf_flags = 0;
+    alert_count = 0;
+    mac_addr_valid = false;
+    fin_final_seq = 0;
+    fin_seq_status = TcpStreamTracker::FIN_NOT_SEEN;
+    fin_seq_set = false;
+    rst_pkt_sent = false;
+}
+
+//-------------------------------------------------------------------------
+// flush policy stuff
+//-------------------------------------------------------------------------
+
+void TcpStreamTracker::init_flush_policy()
+{
+    if ( splitter == nullptr )
+        flush_policy = STREAM_FLPOLICY_IGNORE;
+    else if ( normalizer.is_tcp_ips_enabled() )
+        flush_policy = STREAM_FLPOLICY_ON_DATA;
+    else
+        flush_policy = STREAM_FLPOLICY_ON_ACK;
+}
+
+void TcpStreamTracker::set_splitter(StreamSplitter* ss)
+{
+    if ( splitter )
+        delete splitter;
+
+    splitter = ss;
+
+    if ( ss )
+        paf_setup(&paf_state);
+    else
+        flush_policy = STREAM_FLPOLICY_IGNORE;
+}
+
+void TcpStreamTracker::set_splitter(const Flow* flow)
+{
+    Inspector* ins = flow->gadget;
+
+    if ( !ins )
+        ins = flow->clouseau;
+
+    if ( ins )
+        set_splitter(ins->get_splitter(!client_tracker) );
+    else
+        set_splitter(new AtomSplitter(!client_tracker) );
+}
+
+void TcpStreamTracker::reset_splitter( )
+{
+    if ( splitter )
+        splitter->reset();
+}
+
+void TcpStreamTracker::init_on_syn_sent(TcpSegmentDescriptor& tsd)
+{
+    Profile profile(s5TcpNewSessPerfStats);
+
+    tsd.get_flow()->set_session_flags(SSNFLAG_SEEN_CLIENT);
+    if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
+        tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
+
+    iss = tsd.get_seg_seq();
+    snd_una = iss;
+    snd_nxt = tsd.get_end_seq();
+    snd_wnd =  tsd.get_seg_wnd();
+
+    ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+    tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
+    ts_last = tsd.get_ts();
+    if (ts_last == 0)
+        tf_flags |= TF_TSTAMP_ZERO;
+    tf_flags |= tsd.init_mss(&mss);
+    tf_flags |= tsd.init_wscale(&wscale);
+
+    cache_mac_address(tsd, FROM_CLIENT);
+    tcp_state = TcpStreamTracker::TCP_SYN_SENT;
+    tcpStats.sessions_on_syn++;
+}
+
+void TcpStreamTracker::init_on_syn_recv(TcpSegmentDescriptor& tsd)
+{
+    Profile profile(s5TcpNewSessPerfStats);
+
+    irs = tsd.get_seg_seq();
+    // FIXIT-H can we really set the vars below now?
+    r_nxt_ack = tsd.get_seg_seq() + 1;
+    r_win_base = tsd.get_seg_seq() + 1;
+    reassembler.set_seglist_base_seq(tsd.get_seg_seq() + 1);
+
+    cache_mac_address(tsd, FROM_CLIENT);
+    tcp_state = TcpStreamTracker::TCP_SYN_RECV;
+}
+
+void TcpStreamTracker::init_on_synack_sent(TcpSegmentDescriptor& tsd)
+{
+    Profile profile(s5TcpNewSessPerfStats);
+
+    DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on SYN_ACK!\n");
+
+    tsd.get_flow()->set_session_flags(SSNFLAG_SEEN_SERVER);
+    if (tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE))
+        tsd.get_flow()->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
+
+    iss = tsd.get_seg_seq();
+    irs = tsd.get_seg_ack() - 1;
+    snd_una = tsd.get_seg_seq();
+    snd_nxt = tsd.get_end_seq();
+    snd_wnd = tsd.get_seg_wnd();
+
+    r_win_base = tsd.get_seg_ack();
+    r_nxt_ack = tsd.get_seg_ack();
+    reassembler.set_seglist_base_seq(tsd.get_seg_ack() );
+
+    ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+    tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
+    ts_last = tsd.get_ts();
+    if ( ts_last == 0 )
+        tf_flags |= TF_TSTAMP_ZERO;
+    tf_flags |= tsd.init_mss(&mss);
+    tf_flags |= tsd.init_wscale(&wscale);
+
+    cache_mac_address(tsd, FROM_SERVER);
+    tcp_state = TcpStreamTracker::TCP_SYN_RECV;
+    tcpStats.sessions_on_syn_ack++;
+}
+
+void TcpStreamTracker::init_on_synack_recv(TcpSegmentDescriptor& tsd)
+{
+    Profile profile(s5TcpNewSessPerfStats);
+
+    iss = tsd.get_seg_ack() - 1;
+    irs = tsd.get_seg_seq();
+    snd_una = tsd.get_seg_ack();
+    snd_nxt = snd_una;
+
+    r_nxt_ack = tsd.get_seg_seq() + 1;
+    r_win_base = tsd.get_seg_seq() + 1;
+    reassembler.set_seglist_base_seq(tsd.get_seg_seq() + 1);
+
+    cache_mac_address(tsd, FROM_SERVER);
+    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+}
+
+void TcpStreamTracker::init_on_3whs_ack_sent(TcpSegmentDescriptor& tsd)
+{
+    Profile profile(s5TcpNewSessPerfStats);
+
+    tsd.get_flow()->set_session_flags(SSNFLAG_SEEN_CLIENT);
+
+    if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
+        tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
+
+    iss = tsd.get_seg_seq();
+    snd_una = tsd.get_seg_seq();
+    snd_nxt = snd_una;
+    snd_wnd = tsd.get_seg_wnd();
+
+    r_win_base = tsd.get_seg_ack();
+    r_nxt_ack = tsd.get_seg_ack();
+
+    ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+    tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
+    ts_last = tsd.get_ts();
+    if (ts_last == 0)
+        tf_flags |= TF_TSTAMP_ZERO;
+    tf_flags |= tsd.init_mss(&mss);
+    tf_flags |= tsd.init_wscale(&wscale);
+
+    cache_mac_address(tsd, FROM_CLIENT);
+    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+}
+
+void TcpStreamTracker::init_on_3whs_ack_recv(TcpSegmentDescriptor& tsd)
+{
+    Profile profile(s5TcpNewSessPerfStats);
+
+    iss = tsd.get_seg_ack() - 1;
+    irs = tsd.get_seg_seq();
+    snd_una = tsd.get_seg_ack();
+    snd_nxt = snd_una;
+
+    r_nxt_ack = tsd.get_seg_seq();
+    r_win_base = tsd.get_seg_seq();
+    reassembler.set_seglist_base_seq(tsd.get_seg_seq() + 1);
+
+    cache_mac_address(tsd, FROM_CLIENT);
+    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+    tcpStats.sessions_on_3way++;
+}
+
+void TcpStreamTracker::init_on_data_seg_sent(TcpSegmentDescriptor& tsd)
+{
+    Profile profile(s5TcpNewSessPerfStats);
+
+    Flow* flow = tsd.get_flow();
+
+    if ( flow->ssn_state.direction == FROM_CLIENT )
+        flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
+    else
+        flow->set_session_flags(SSNFLAG_SEEN_SERVER);
+
+    // FIXIT-H should we init these?
+    iss = tsd.get_seg_seq();
+    irs = tsd.get_seg_ack();
+    snd_una = tsd.get_seg_seq();
+    snd_nxt = snd_una + tsd.get_seg_len();
+    snd_wnd = tsd.get_seg_wnd();
+
+    r_win_base = tsd.get_seg_ack();
+    r_nxt_ack = tsd.get_seg_ack();
+    reassembler.set_seglist_base_seq(tsd.get_seg_ack());
+
+    ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+    tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
+    ts_last = tsd.get_ts();
+    if (ts_last == 0)
+        tf_flags |= TF_TSTAMP_ZERO;
+    tf_flags |= ( tsd.init_mss(&mss) | tsd.init_wscale(&wscale) );
+
+    cache_mac_address(tsd, tsd.get_direction() );
+    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+}
+
+void TcpStreamTracker::init_on_data_seg_recv(TcpSegmentDescriptor& tsd)
+{
+    Profile profile(s5TcpNewSessPerfStats);
+
+    iss = tsd.get_seg_ack();
+    irs = tsd.get_seg_seq();
+    snd_una = tsd.get_seg_ack();
+    snd_nxt = snd_una;
+    snd_wnd = 0; /* reset later */
+
+    r_nxt_ack = tsd.get_seg_seq();
+    r_win_base = tsd.get_seg_seq();
+    reassembler.set_seglist_base_seq(tsd.get_seg_seq());
+
+    cache_mac_address(tsd, tsd.get_direction() );
+    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+    tcpStats.sessions_on_data++;
+}
+
+void TcpStreamTracker::finish_server_init(TcpSegmentDescriptor& tsd)
+{
+    iss = tsd.get_seg_seq();
+    snd_una = tsd.get_seg_seq();
+    snd_nxt = tsd.get_end_seq();
+    snd_wnd = tsd.get_seg_wnd();
+
+    // FIXIT-H move this to fin handler for syn_recv state ..
+    //if ( tcph->is_fin() )
+    //    server->set_snd_nxt(server->get_snd_nxt() - 1);
+
+    tf_flags |= normalizer.get_tcp_timestamp(tsd, false);
+    ts_last = tsd.get_ts();
+    if ( ts_last != 0 )
+        ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+    else
+        tf_flags |= TF_TSTAMP_ZERO;
+
+    tf_flags |= ( tsd.init_mss(&mss) | tsd.init_wscale(&wscale) );
+}
+
+void TcpStreamTracker::finish_client_init(TcpSegmentDescriptor& tsd)
+{
+    Flow* flow = tsd.get_flow();
+
+    r_nxt_ack = tsd.get_end_seq();
+
+    if ( !( flow->session_state & STREAM_STATE_MIDSTREAM ) )
+    {
+        reassembler.set_seglist_base_seq(tsd.get_seg_seq() + 1);
+        r_win_base = tsd.get_end_seq();
+    }
+    else
+    {
+        reassembler.set_seglist_base_seq(tsd.get_seg_seq() );
+        r_win_base = tsd.get_seg_seq();
+    }
+}
+
+void TcpStreamTracker::update_tracker_ack_recv(TcpSegmentDescriptor& tsd)
+{
+    if ( SEQ_GT(tsd.get_seg_ack(), snd_una) )
+    {
+        snd_una = tsd.get_seg_ack();
+        if ( snd_nxt < snd_una )
+            snd_nxt = snd_una;
+    }
+}
+
+void TcpStreamTracker::update_tracker_ack_sent(TcpSegmentDescriptor& tsd)
+{
+    // ** this is how we track the last seq number sent
+    // as is l_unackd is the "last left" seq recvd
+    //snd_una = tsd.get_seg_seq();
+
+    // FIXIT-H add check to validate ack...
+
+    if ( SEQ_GT(tsd.get_end_seq(), snd_nxt) )
+        snd_nxt = tsd.get_end_seq();
+
+    if ( !SEQ_EQ(r_win_base, tsd.get_seg_ack() ) )
+        small_seg_count = 0;
+
+    if ( SEQ_GT(tsd.get_seg_ack(), r_win_base) )
+        r_win_base = tsd.get_seg_ack();
+
+    if ( ( fin_seq_status == TcpStreamTracker::FIN_WITH_SEQ_SEEN )
+        && SEQ_EQ(r_win_base, fin_final_seq) )
+    {
+        fin_seq_status = TcpStreamTracker::FIN_WITH_SEQ_ACKED;
+    }
+
+    snd_wnd = tsd.get_seg_wnd();
+    reassembler.flush_on_ack_policy(tsd.get_pkt() );
+}
+
+bool TcpStreamTracker::update_on_3whs_ack(TcpSegmentDescriptor& tsd)
+{
+    bool good_ack = true;
+
+    if ( is_ack_valid(tsd.get_seg_ack()) )
+    {
+        Flow* flow = tsd.get_flow();
+
+        irs = tsd.get_seg_seq();
+        finish_client_init(tsd);
+        update_tracker_ack_recv(tsd);
+        flow->set_session_flags(SSNFLAG_ESTABLISHED);
+        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+        tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
+    }
+    else
+    {
+        DebugFormat(DEBUG_STREAM_STATE,
+            "Pkt Ack is Out of Bounds (%X, %X, %X) = (snd_una, snd_nxt, cur)\n",
+            snd_una, snd_nxt, tsd.get_seg_ack());
+        inc_tcp_discards();
+        normalizer.trim_win_payload(tsd);
+        good_ack = false;
+    }
+
+    return good_ack;
+}
+
+bool TcpStreamTracker::update_on_rst_recv(TcpSegmentDescriptor& tsd)
+{
+    bool good_rst = true;
+
+    normalizer.trim_rst_payload(tsd);
+    if ( normalizer.validate_rst(tsd) )
+    {
+        Flow* flow = tsd.get_flow();
+
+        DebugMessage(DEBUG_STREAM_STATE, "Received Valid RST, bailing\n");
+        flow->set_session_flags(SSNFLAG_RESET);
+        if ( normalizer.is_tcp_ips_enabled() )
+            tcp_state = TcpStreamTracker::TCP_CLOSED;
+    }
+    else
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "Received RST with bad sequence number, bailing\n");
+        inc_tcp_discards();
+        normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
+        good_rst = false;
+    }
+
+    return good_rst;
+}
+
+void TcpStreamTracker::update_on_rst_sent()
+{
+    tcp_state = TcpStreamTracker::TCP_CLOSED;
+    rst_pkt_sent = true;
+}
+
+void TcpStreamTracker::flush_data_on_fin_recv(TcpSegmentDescriptor& tsd)
+{
+    if ( (flush_policy != STREAM_FLPOLICY_ON_ACK)
+        && (flush_policy != STREAM_FLPOLICY_ON_DATA)
+        && normalizer.is_tcp_ips_enabled())
+    {
+        tsd.get_pkt()->packet_flags |= PKT_PDU_TAIL;
+    }
+
+    reassembler.flush_on_data_policy(tsd.get_pkt());
+}
+
+bool TcpStreamTracker::update_on_fin_recv(TcpSegmentDescriptor& tsd)
+{
+    if ( SEQ_LT(tsd.get_end_seq(), r_win_base) )
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "FIN inside r_win_base, bailing\n");
+        return false;
+    }
+
+    //--------------------------------------------------
+    // FIXIT-L don't bump r_nxt_ack unless FIN is in seq
+    // because it causes bogus 129:5 cases
+    // but doing so causes extra gaps
+    //if ( SEQ_EQ(tsd.end_seq, r_nxt_ack) )
+    r_nxt_ack++;
+
+    // set final seq # any packet rx'ed with seq > is bad
+    if ( !fin_seq_set )
+    {
+        fin_final_seq = tsd.get_end_seq();
+        fin_seq_set = true;
+        if( tsd.get_seg_len() == 0 )
+            fin_seq_status = TcpStreamTracker::FIN_WITH_SEQ_SEEN;
+    }
+
+    return true;
+}
+
+bool TcpStreamTracker::update_on_fin_sent(TcpSegmentDescriptor& tsd)
+{
+    update_tracker_ack_sent(tsd);
+    snd_nxt++;
+    return true;
+}
+
+bool TcpStreamTracker::is_segment_seq_valid(TcpSegmentDescriptor& tsd)
+{
+    bool valid_seq = true;
+
+    int right_ok;
+    uint32_t left_seq;
+
+    DebugFormat(DEBUG_STREAM_STATE,
+        "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
+        tsd.get_end_seq(), r_win_base, tsd.get_seg_seq(),
+        r_nxt_ack + normalizer.get_stream_window(tsd));
+
+    if ( SEQ_LT(r_nxt_ack, r_win_base) )
+        left_seq = r_nxt_ack;
+    else
+        left_seq = r_win_base;
+
+    if ( tsd.get_seg_len() )
+        right_ok = SEQ_GT(tsd.get_end_seq(), left_seq);
+    else
+        right_ok = SEQ_GEQ(tsd.get_end_seq(), left_seq);
+
+    if ( right_ok )
+    {
+        uint32_t win = normalizer.get_stream_window(tsd);
+
+        if ( SEQ_LEQ(tsd.get_seg_seq(), r_win_base + win) )
+        {
+            DebugMessage(DEBUG_STREAM_STATE, "seq is within window!\n");
+        }
+        else
+        {
+            DebugMessage(DEBUG_STREAM_STATE, "seq is past the end of the window!\n");
+            valid_seq = false;
+        }
+    }
+    else
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "end_seq is before win_base\n");
+        valid_seq = false;
+    }
+
+    if ( !valid_seq )
+    {
+        inc_tcp_discards();
+        normalizer.trim_win_payload(tsd);
+    }
+
+    return valid_seq;
+}
+
+void TcpStreamTracker::print()
+{
+    LogMessage(" + TcpTracker +\n");
+    LogMessage("    state:              %s\n", tcp_state_names[ tcp_state ]);
+    LogMessage("    iss:                0x%X\n", iss);
+    LogMessage("    ts_last:            %u\n", ts_last);
+    LogMessage("    wscale:             %u\n", wscale);
+    LogMessage("    mss:                0x%08X\n", mss);
+    LogMessage("    snd_una:            %X\n", snd_una);
+    LogMessage("    snd_nxt:            %X\n", snd_nxt);
+    LogMessage("    snd_win:            %u\n", snd_wnd);
+    LogMessage("    rcv_nxt:            %X\n", rcv_nxt);
+    LogMessage("    r_win_base:         %X\n", r_win_base);
+}
+
index 6a96840ba1f893cee003ffc26affbbc1220acbee..dc93572e89338106b353ac61ab623452d4c1a53c 100644 (file)
 #ifndef TCP_STREAM_TRACKER_H
 #define TCP_STREAM_TRACKER_H
 
-#include "stream/libtcp/tcp_segment_descriptor.h"
 #include "stream/paf.h"
+#include "stream/tcp/segment_overlap_editor.h"
 #include "stream/tcp/tcp_defs.h"
+#include "stream/tcp/tcp_normalizers.h"
+#include "stream/tcp/tcp_reassemblers.h"
+#include "stream/libtcp/tcp_segment_descriptor.h"
 
 /* Only track a maximum number of alerts per session */
 #define MAX_SESSION_ALERTS 8
@@ -42,9 +45,9 @@ struct StreamAlertInfo
 extern const char* tcp_state_names[];
 extern const char* tcp_event_names[];
 
-class TcpNormalizer;
 class TcpReassembler;
 class TcpSession;
+struct TcpSegmentNode;
 
 class TcpStreamTracker
 {
@@ -85,175 +88,109 @@ public:
 
     enum FinSeqNumStatus { FIN_NOT_SEEN, FIN_WITH_SEQ_SEEN, FIN_WITH_SEQ_ACKED };
 
-    TcpStreamTracker(bool);
-    virtual ~TcpStreamTracker() = default;
+    TcpStreamTracker(bool client);
+    virtual ~TcpStreamTracker();
 
     bool is_client_tracker() const
-    {
-        return client_tracker;
-    }
+    { return client_tracker; }
 
     bool is_server_tracker() const
-    {
-        return !client_tracker;
-    }
+    { return !client_tracker; }
 
     TcpState get_tcp_state() const
-    {
-        return tcp_state;
-    }
+    { return tcp_state; }
 
     void set_tcp_state(TcpState tcp_state)
-    {
-        this->tcp_state = tcp_state;
-    }
+    { this->tcp_state = tcp_state; }
 
     TcpEvent get_tcp_event() const
-    {
-        return tcp_event;
-    }
+    { return tcp_event; }
 
     TcpEvent set_tcp_event(TcpSegmentDescriptor&);
 
     void set_tcp_event(TcpEvent tcp_event)
-    {
-        this->tcp_event = tcp_event;
-    }
+    { this->tcp_event = tcp_event; }
 
     uint32_t get_rcv_nxt() const
-    {
-        return rcv_nxt;
-    }
+    { return rcv_nxt; }
 
     void set_rcv_nxt(uint32_t rcv_nxt)
-    {
-        this->rcv_nxt = rcv_nxt;
-    }
+    {  this->rcv_nxt = rcv_nxt; }
 
     uint32_t get_rcv_wnd() const
-    {
-        return rcv_wnd;
-    }
+    { return rcv_wnd; }
 
     void set_rcv_wnd(uint32_t rcv_wnd)
-    {
-        this->rcv_wnd = rcv_wnd;
-    }
+    { this->rcv_wnd = rcv_wnd; }
 
     uint16_t get_rcv_up() const
-    {
-        return rcv_up;
-    }
+    { return rcv_up; }
 
     void set_rcv_up(uint16_t rcv_up)
-    {
-        this->rcv_up = rcv_up;
-    }
+    { this->rcv_up = rcv_up; }
 
     uint32_t get_irs() const
-    {
-        return irs;
-    }
+    { return irs; }
 
     void set_irs(uint32_t irs)
-    {
-        this->irs = irs;
-    }
+    { this->irs = irs; }
 
     uint32_t get_snd_una() const
-    {
-        return snd_una;
-    }
+    { return snd_una; }
 
     void set_snd_una(uint32_t snd_una)
-    {
-        this->snd_una = snd_una;
-    }
+    { this->snd_una = snd_una; }
 
     uint32_t get_snd_nxt() const
-    {
-        return snd_nxt;
-    }
+    { return snd_nxt; }
 
     void set_snd_nxt(uint32_t snd_nxt)
-    {
-        this->snd_nxt = snd_nxt;
-    }
+    { this->snd_nxt = snd_nxt; }
 
     uint16_t get_snd_up() const
-    {
-        return snd_up;
-    }
+    { return snd_up; }
 
     void set_snd_up(uint16_t snd_up)
-    {
-        this->snd_up = snd_up;
-    }
+    { this->snd_up = snd_up; }
 
     uint32_t get_snd_wl1() const
-    {
-        return snd_wl1;
-    }
+    { return snd_wl1; }
 
     void set_snd_wl1(uint32_t snd_wl1)
-    {
-        this->snd_wl1 = snd_wl1;
-    }
+    { this->snd_wl1 = snd_wl1; }
 
     uint32_t get_snd_wl2() const
-    {
-        return snd_wl2;
-    }
+    { return snd_wl2; }
 
     void set_snd_wl2(uint32_t snd_wl2)
-    {
-        this->snd_wl2 = snd_wl2;
-    }
+    { this->snd_wl2 = snd_wl2; }
 
     uint32_t get_snd_wnd() const
-    {
-        return snd_wnd;
-    }
+    { return snd_wnd; }
 
     void set_snd_wnd(uint32_t snd_wnd)
-    {
-        this->snd_wnd = snd_wnd;
-    }
+    { this->snd_wnd = snd_wnd; }
 
     uint32_t get_iss() const
-    {
-        return iss;
-    }
+    { return iss; }
 
     void set_iss(uint32_t iss)
-    {
-        this->iss = iss;
-    }
+    { this->iss = iss; }
 
     uint32_t get_fin_final_seq() const
-    {
-        return fin_final_seq;
-    }
+    { return fin_final_seq; }
 
     void set_fin_final_seq(uint32_t fin_final_seq = 0)
-    {
-        this->fin_final_seq = fin_final_seq;
-    }
+    { this->fin_final_seq = fin_final_seq; }
 
     bool is_fin_seq_set() const
-    {
-        return fin_seq_set;
-    }
+    { return fin_seq_set; }
 
     uint32_t get_ts_last_packet() const
-    {
-        return ts_last_packet;
-    }
+    { return ts_last_packet; }
 
     void set_ts_last_packet(uint32_t ts_last_packet)
-    {
-        this->ts_last_packet = ts_last_packet;
-    }
+    { this->ts_last_packet = ts_last_packet; }
 
     bool is_ack_valid(uint32_t cur)
     {
@@ -267,107 +204,83 @@ public:
 
     // ack number must ack syn
     bool is_rst_valid_in_syn_sent(TcpSegmentDescriptor& tsd)
-    {
-        return tsd.get_seg_ack() == snd_una;
-    }
+    { return tsd.get_seg_ack() == snd_una; }
 
     uint32_t get_ts_last() const
-    {
-        return ts_last;
-    }
+    { return ts_last; }
 
     void set_ts_last(uint32_t ts_last)
-    {
-        this->ts_last = ts_last;
-    }
+    { this->ts_last = ts_last; }
 
     uint16_t get_tf_flags() const
-    {
-        return tf_flags;
-    }
+    { return tf_flags; }
 
     void set_tf_flags(uint16_t flags)
-    {
-        this->tf_flags |= flags;
-    }
+    { this->tf_flags |= flags; }
 
     void clear_tf_flags(uint16_t flags)
-    {
-        this->tf_flags &= ~flags;
-    }
+    { this->tf_flags &= ~flags; }
 
     uint16_t get_wscale() const
-    {
-        return wscale;
-    }
+    { return wscale; }
 
     void set_wscale(uint16_t wscale)
-    {
-        this->wscale = wscale;
-    }
+    { this->wscale = wscale; }
 
     uint16_t get_mss() const
-    {
-        return mss;
-    }
+    { return mss; }
 
     void set_mss(uint16_t mss)
-    {
-        this->mss = mss;
-    }
+    { this->mss = mss; }
 
     uint8_t get_tcp_options_len() const
-    {
-        return tcp_options_len;
-    }
+    { return tcp_options_len; }
 
     void set_tcp_options_len(uint8_t tcp_options_len)
-    {
-        this->tcp_options_len = tcp_options_len;
-    }
+    { this->tcp_options_len = tcp_options_len; }
 
     void cache_mac_address(TcpSegmentDescriptor&, uint8_t direction);
     bool compare_mac_addresses(const uint8_t eth_addr[]);
 
     bool is_rst_pkt_sent() const
-    {
-        return rst_pkt_sent;
-    }
+    { return rst_pkt_sent; }
 
     bool process_inorder_fin() const
-    {
-        return inorder_fin;
-    }
-
-    virtual void init_tcp_state() =  0;
-    virtual void init_toolbox() = 0;
-
-    virtual void print() =  0;
-    virtual void init_flush_policy() =  0;
-    virtual void set_splitter(snort::StreamSplitter* ss) =  0;
-    virtual void set_splitter(const snort::Flow* flow) =  0;
-    virtual void reset_splitter( ) = 0;
-
-    virtual void init_on_syn_sent(TcpSegmentDescriptor&) =  0;
-    virtual void init_on_syn_recv(TcpSegmentDescriptor&) =  0;
-    virtual void init_on_synack_sent(TcpSegmentDescriptor&) =  0;
-    virtual void init_on_synack_recv(TcpSegmentDescriptor&) =  0;
-    virtual void init_on_3whs_ack_sent(TcpSegmentDescriptor&) =  0;
-    virtual void init_on_3whs_ack_recv(TcpSegmentDescriptor&) =  0;
-    virtual void init_on_data_seg_sent(TcpSegmentDescriptor&) =  0;
-    virtual void init_on_data_seg_recv(TcpSegmentDescriptor&) =  0;
-    virtual void finish_server_init(TcpSegmentDescriptor&) =  0;
-    virtual void finish_client_init(TcpSegmentDescriptor&) =  0;
-
-    virtual void update_tracker_ack_recv(TcpSegmentDescriptor&) =  0;
-    virtual void update_tracker_ack_sent(TcpSegmentDescriptor&) =  0;
-    virtual bool update_on_3whs_ack(TcpSegmentDescriptor&) =  0;
-    virtual bool update_on_rst_recv(TcpSegmentDescriptor&) =  0;
-    virtual void update_on_rst_sent() =  0;
-    virtual bool update_on_fin_recv(TcpSegmentDescriptor&) =  0;
-    virtual bool update_on_fin_sent(TcpSegmentDescriptor&) =  0;
-    virtual bool is_segment_seq_valid(TcpSegmentDescriptor&) =  0;
-    virtual void flush_data_on_fin_recv(TcpSegmentDescriptor&) =  0;
+    { return inorder_fin; }
+
+    snort::StreamSplitter* get_splitter()
+    { return splitter; }
+
+    FlushPolicy get_flush_policy()
+    { return flush_policy; }
+
+    virtual void init_tcp_state();
+    virtual void print();
+    virtual void init_flush_policy();
+    virtual void set_splitter(snort::StreamSplitter* ss);
+    virtual void set_splitter(const snort::Flow* flow);
+    virtual void reset_splitter( );
+
+    virtual void init_on_syn_sent(TcpSegmentDescriptor&);
+    virtual void init_on_syn_recv(TcpSegmentDescriptor&);
+    virtual void init_on_synack_sent(TcpSegmentDescriptor&);
+    virtual void init_on_synack_recv(TcpSegmentDescriptor&);
+    virtual void init_on_3whs_ack_sent(TcpSegmentDescriptor&);
+    virtual void init_on_3whs_ack_recv(TcpSegmentDescriptor&);
+    virtual void init_on_data_seg_sent(TcpSegmentDescriptor&);
+    virtual void init_on_data_seg_recv(TcpSegmentDescriptor&);
+    virtual void finish_server_init(TcpSegmentDescriptor&);
+    virtual void finish_client_init(TcpSegmentDescriptor&);
+
+    virtual void update_tracker_ack_recv(TcpSegmentDescriptor&);
+    virtual void update_tracker_ack_sent(TcpSegmentDescriptor&);
+    virtual bool update_on_3whs_ack(TcpSegmentDescriptor&);
+    virtual bool update_on_rst_recv(TcpSegmentDescriptor&);
+    virtual void update_on_rst_sent();
+    virtual bool update_on_fin_recv(TcpSegmentDescriptor&);
+    virtual bool update_on_fin_sent(TcpSegmentDescriptor&);
+    virtual bool is_segment_seq_valid(TcpSegmentDescriptor&);
+    virtual void flush_data_on_fin_recv(TcpSegmentDescriptor&);
 
     bool client_tracker;
     TcpState tcp_state;
@@ -396,10 +309,10 @@ public:
     uint32_t r_win_base = 0; /* remote side window base sequence number
      * (i.e. the last ack we got) */
 
-    snort::StreamSplitter* splitter = nullptr;
-    TcpNormalizer* normalizer = nullptr;
-    TcpReassembler* reassembler = nullptr;
     TcpSession* session = nullptr;
+    TcpNormalizerPolicy normalizer;
+    TcpReassemblerPolicy reassembler;
+    snort::StreamSplitter* splitter = nullptr;
 
     uint32_t small_seg_count = 0;
     uint8_t alert_count = 0;
index 24eeaa1e477d63e6a46083529afe18c15735bd95..ad4d30b3116a6e0c3037765cb4be81be73f529b1 100644 (file)
@@ -24,8 +24,6 @@ add_library( stream_tcp OBJECT
     tcp_reassembler.cc
     tcp_reassemblers.h
     tcp_reassemblers.cc
-    tcp_tracker.cc
-    tcp_tracker.h
     tcp_session.cc
     tcp_session.h
     tcp_state_closed.cc
index f9e51b4ea4ca6bc72665146f60967797758ee5d0..1b3fb6d8b63dc8041bc01d32bcd4c83b8f5210b5 100644 (file)
@@ -122,13 +122,13 @@ IpsOption::EvalStatus ReassembleOption::eval(Cursor&, Packet* pkt)
         {
             if ( srod.direction & SSN_DIR_FROM_SERVER )
             {
-                tcpssn->server->flush_policy = STREAM_FLPOLICY_IGNORE;
+                tcpssn->server.flush_policy = STREAM_FLPOLICY_IGNORE;
                 Stream::set_splitter(lwssn, true);
             }
 
             if ( srod.direction & SSN_DIR_FROM_CLIENT )
             {
-                tcpssn->client->flush_policy = STREAM_FLPOLICY_IGNORE;
+                tcpssn->client.flush_policy = STREAM_FLPOLICY_IGNORE;
                 Stream::set_splitter(lwssn, false);
             }
         }
@@ -138,13 +138,13 @@ IpsOption::EvalStatus ReassembleOption::eval(Cursor&, Packet* pkt)
             // FIXIT-M PAF need to check for ips / on-data
             if ( srod.direction & SSN_DIR_FROM_SERVER )
             {
-                tcpssn->server->flush_policy = STREAM_FLPOLICY_ON_ACK;
+                tcpssn->server.flush_policy = STREAM_FLPOLICY_ON_ACK;
                 Stream::set_splitter(lwssn, true, new AtomSplitter(true));
             }
 
             if ( srod.direction & SSN_DIR_FROM_CLIENT )
             {
-                tcpssn->client->flush_policy = STREAM_FLPOLICY_ON_ACK;
+                tcpssn->client.flush_policy = STREAM_FLPOLICY_ON_ACK;
                 Stream::set_splitter(lwssn, false, new AtomSplitter(false));
             }
         }
index 63030d1098472438057463030333343f5172953b..96b2d843b006a95a210b95032257dc509677a52a 100644 (file)
@@ -105,26 +105,26 @@ IpsOption::EvalStatus SizeOption::eval(Cursor&, Packet* pkt)
     uint32_t client_size;
     uint32_t server_size;
 
-    if (tcpssn->client->get_snd_nxt() > tcpssn->client->get_iss())
+    if (tcpssn->client.get_snd_nxt() > tcpssn->client.get_iss())
     {
         /* the normal case... */
-        client_size = tcpssn->client->get_snd_nxt() - tcpssn->client->get_iss();
+        client_size = tcpssn->client.get_snd_nxt() - tcpssn->client.get_iss();
     }
     else
     {
         /* the seq num wrapping case... */
-        client_size = tcpssn->client->get_iss() - tcpssn->client->get_snd_nxt();
+        client_size = tcpssn->client.get_iss() - tcpssn->client.get_snd_nxt();
     }
 
-    if (tcpssn->server->get_snd_nxt() > tcpssn->server->get_iss())
+    if (tcpssn->server.get_snd_nxt() > tcpssn->server.get_iss())
     {
         /* the normal case... */
-        server_size = tcpssn->server->get_snd_nxt() - tcpssn->server->get_iss();
+        server_size = tcpssn->server.get_snd_nxt() - tcpssn->server.get_iss();
     }
     else
     {
         /* the seq num wrapping case... */
-        server_size = tcpssn->server->get_iss() - tcpssn->server->get_snd_nxt();
+        server_size = tcpssn->server.get_iss() - tcpssn->server.get_snd_nxt();
     }
 
     switch ( direction )
index d4b9b0bbdf6e945fda8f812be6500f03eba3e127..43db0bc74b6cea98c6eb64c27ee59c742938aabe 100644 (file)
 #include "log/messages.h"
 
 #include "tcp_module.h"
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
+#include "tcp_session.h"
 
-bool SegmentOverlapEditor::is_segment_retransmit(bool* full_retransmit)
+void SegmentOverlapState::init_sos(TcpSession* ssn, ReassemblyPolicy pol)
+{
+
+    session = ssn;
+    reassembly_policy = pol;
+
+    seglist.reset();
+
+    seglist_base_seq = 0;
+    seg_count = 0;
+    seg_bytes_total = 0;
+    seg_bytes_logical = 0;
+    total_bytes_queued = 0;
+    total_segs_queued = 0;
+    overlap_count = 0;
+
+    tsd = nullptr;
+    left = nullptr;
+    right = nullptr;
+    rdata = nullptr;
+
+    seq = 0;
+    seq_end = 0;
+    len = 0;
+    overlap = 0;
+    slide = 0;
+    trunc_len = 0;
+    rsize = 0;
+    rseq = 0;
+    keep_segment = true;
+
+    tcp_ips_data = Normalize_GetMode(NORM_TCP_IPS);
+}
+
+void SegmentOverlapState::init_soe(
+    TcpSegmentDescriptor& tsd, TcpSegmentNode* left, TcpSegmentNode* right)
+{
+    this->tsd = &tsd;
+    this->left = left;
+    this->right = right;
+
+    seq = tsd.get_seg_seq();
+    seq_end = tsd.get_end_seq();
+    len = tsd.get_seg_len();
+
+    overlap = 0;
+    slide = 0;
+    trunc_len = 0;
+
+    rdata = tsd.get_pkt()->data;
+    rsize = tsd.get_seg_len();
+    rseq = tsd.get_seg_seq();
+
+    keep_segment = true;
+}
+
+bool SegmentOverlapEditor::is_segment_retransmit(
+    TcpReassemblerState& trs, bool* full_retransmit)
 {
     // Don't want to count retransmits as overlaps or do anything
     // else with them.  Account for retransmits of multiple PDUs
     // in one segment.
-    bool* pb = (rseq == tsd->get_seg_seq()) ? full_retransmit : nullptr;
+    bool* pb = (trs.sos.rseq == trs.sos.tsd->get_seg_seq()) ? full_retransmit : nullptr;
 
-    if ( right->is_retransmit(rdata, rsize, rseq, right->orig_dsize, pb) )
+    if ( trs.sos.right->is_retransmit(
+        trs.sos.rdata, trs.sos.rsize, trs.sos.rseq, trs.sos.right->orig_dsize, pb) )
     {
         if ( !(*full_retransmit) )
         {
-            rdata += right->payload_size;
-            rsize -= right->payload_size;
-            rseq += right->payload_size;
-            seq += right->payload_size;
-            left = right;
-            right = right->next;
+            trs.sos.rdata += trs.sos.right->payload_size;
+            trs.sos.rsize -= trs.sos.right->payload_size;
+            trs.sos.rseq += trs.sos.right->payload_size;
+            trs.sos.seq += trs.sos.right->payload_size;
+            trs.sos.left = trs.sos.right;
+            trs.sos.right = trs.sos.right->next;
         }
         else
-            rsize = 0;
+            trs.sos.rsize = 0;
 
-        if ( rsize == 0 )
+        if ( trs.sos.rsize == 0 )
         {
             // All data was retransmitted
-            session->retransmit_process(tsd->get_pkt());
-            keep_segment = false;
+            trs.sos.session->retransmit_process(trs.sos.tsd->get_pkt());
+            trs.sos.keep_segment = false;
         }
 
         return true;
@@ -64,45 +123,46 @@ bool SegmentOverlapEditor::is_segment_retransmit(bool* full_retransmit)
     return false;
 }
 
-int SegmentOverlapEditor::eval_left()
+int SegmentOverlapEditor::eval_left(TcpReassemblerState& trs)
 {
     int rc = STREAM_INSERT_OK;
 
-    if ( left )
-        rc = insert_left_overlap();
+    if ( trs.sos.left )
+        rc = insert_left_overlap(trs);
 
     return rc;
 }
 
-int SegmentOverlapEditor::eval_right()
+int SegmentOverlapEditor::eval_right(TcpReassemblerState& trs)
 {
-    while ( right && SEQ_LT(right->seq, seq_end) )
+    while ( trs.sos.right && SEQ_LT(trs.sos.right->seq, trs.sos.seq_end) )
     {
-        trunc_len = 0;
+        trs.sos.trunc_len = 0;
 
-        assert(SEQ_LEQ(seq, right->seq));
-        overlap = ( int )( seq_end - right->seq );
+        assert(SEQ_LEQ(trs.sos.seq, trs.sos.right->seq));
+        trs.sos.overlap = ( int )( trs.sos.seq_end - trs.sos.right->seq );
 
         DebugFormat(DEBUG_STREAM_STATE, "right overlap(%d): len: %d right->seq: 0x%X seq: 0x%X\n",
-            overlap, len, right->seq, seq);
+            trs.sos.overlap, trs.sos.len, trs.sos.right->seq, trs.sos.seq);
 
         // Treat sequence number overlap as a retransmission, only check right side since
         //  left side happens rarely
-        session->retransmit_handle(tsd->get_pkt());
+        trs.sos.session->retransmit_handle(trs.sos.tsd->get_pkt());
 
-        if ( overlap < right->payload_size )
+        if ( trs.sos.overlap < trs.sos.right->payload_size )
         {
-            if ( right->is_retransmit(rdata, rsize, rseq, right->orig_dsize, nullptr) )
+            if ( trs.sos.right->is_retransmit(
+                trs.sos.rdata, trs.sos.rsize, trs.sos.rseq, trs.sos.right->orig_dsize, nullptr) )
             {
                 // All data was retransmitted
-                session->retransmit_process(tsd->get_pkt());
-                keep_segment = false;
+                trs.sos.session->retransmit_process(trs.sos.tsd->get_pkt());
+                trs.sos.keep_segment = false;
             }
             else
             {
                 tcpStats.overlaps++;
-                overlap_count++;
-                insert_right_overlap();
+                trs.sos.overlap_count++;
+                insert_right_overlap(trs);
             }
 
             break;
@@ -113,7 +173,7 @@ int SegmentOverlapEditor::eval_right()
             // Don't want to count retransmits as overlaps or do anything
             // else with them.  Account for retransmits of multiple PDUs
             // in one segment.
-            if ( is_segment_retransmit(&full_retransmit) )
+            if ( is_segment_retransmit(trs, &full_retransmit) )
             {
                 if ( full_retransmit )
                     break;
@@ -121,8 +181,8 @@ int SegmentOverlapEditor::eval_right()
             }
 
             tcpStats.overlaps++;
-            overlap_count++;
-            int rc = insert_full_overlap();
+            trs.sos.overlap_count++;
+            int rc = insert_full_overlap(trs);
             if ( rc != STREAM_INSERT_OK )
                 return rc;
         }
@@ -131,91 +191,94 @@ int SegmentOverlapEditor::eval_right()
     return STREAM_INSERT_OK;
 }
 
-void SegmentOverlapEditor::drop_old_segment()
+void SegmentOverlapEditor::drop_old_segment(TcpReassemblerState& trs)
 {
     DebugFormat(DEBUG_STREAM_STATE,
         "full right overlap, dropping old segment at seq %u, size %hu\n",
-        right->seq, right->payload_size);
+        trs.sos.right->seq, trs.sos.right->payload_size);
 
-    TcpSegmentNode* drop_seg = right;
-    right = right->next;
-    delete_reassembly_segment(drop_seg);
+    TcpSegmentNode* drop_seg = trs.sos.right;
+    trs.sos.right = trs.sos.right->next;
+    delete_reassembly_segment(trs, drop_seg);
 }
 
-int SegmentOverlapEditor::left_overlap_keep_first()
+int SegmentOverlapEditor::left_overlap_keep_first(TcpReassemblerState& trs)
 {
-    DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", overlap);
+    DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", trs.sos.overlap);
 
     // NOTE that overlap will always be less than left->size since
     // seq is always greater than left->seq
-    assert(SEQ_GT(seq, left->seq));
+    assert(SEQ_GT(trs.sos.seq, trs.sos.left->seq));
 
-    len = tsd->get_seg_len();
-    overlap = left->seq + left->payload_size - seq;
+    trs.sos.len = trs.sos.tsd->get_seg_len();
+    trs.sos.overlap = trs.sos.left->seq + trs.sos.left->payload_size - trs.sos.seq;
 
-    if ( len < overlap )
-        overlap = len;
+    if ( trs.sos.len < trs.sos.overlap )
+        trs.sos.overlap = trs.sos.len;
 
-    if ( overlap > 0 )
+    if ( trs.sos.overlap > 0 )
     {
         tcpStats.overlaps++;
-        overlap_count++;
+        trs.sos.overlap_count++;
 
         DebugMessage(DEBUG_STREAM_STATE, "left overlap, honoring old data\n");
 
-        if ( SEQ_GT(left->seq + left->payload_size, seq_end) )
+        if ( SEQ_GT(trs.sos.left->seq + trs.sos.left->payload_size, trs.sos.seq_end) )
         {
-            if (tcp_ips_data == NORM_MODE_ON)
+            if (trs.sos.tcp_ips_data == NORM_MODE_ON)
             {
-                unsigned offset = tsd->get_seg_seq() - left->seq;
-                memcpy(const_cast<uint8_t*>(tsd->get_pkt()->data), left->payload()+offset, tsd->get_seg_len());
-                tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
+                unsigned offset = trs.sos.tsd->get_seg_seq() - trs.sos.left->seq;
+                memcpy(const_cast<uint8_t*>(trs.sos.tsd->get_pkt()->data),
+                    trs.sos.left->payload()+offset, trs.sos.tsd->get_seg_len());
+                trs.sos.tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
             }
-            tcp_norm_stats[PC_TCP_IPS_DATA][tcp_ips_data]++;
+            tcp_norm_stats[PC_TCP_IPS_DATA][trs.sos.tcp_ips_data]++;
         }
         else
         {
-            if ( tcp_ips_data == NORM_MODE_ON )
+            if ( trs.sos.tcp_ips_data == NORM_MODE_ON )
             {
-                unsigned offset = tsd->get_seg_seq() - left->seq;
-                unsigned length = left->seq + left->payload_size - tsd->get_seg_seq();
-                memcpy(const_cast<uint8_t*>(tsd->get_pkt()->data), left->payload()+offset, length);
-                tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
+                unsigned offset = trs.sos.tsd->get_seg_seq() - trs.sos.left->seq;
+                unsigned length = trs.sos.left->seq + trs.sos.left->payload_size -
+                    trs.sos.tsd->get_seg_seq();
+                memcpy(const_cast<uint8_t*>(trs.sos.tsd->get_pkt()->data),
+                    trs.sos.left->payload()+offset, length);
+                trs.sos.tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
             }
 
-            tcp_norm_stats[PC_TCP_IPS_DATA][tcp_ips_data]++;
+            tcp_norm_stats[PC_TCP_IPS_DATA][trs.sos.tcp_ips_data]++;
         }
 
-        seq += overlap;
+        trs.sos.seq += trs.sos.overlap;
     }
 
     return STREAM_INSERT_OK;
 }
 
-int SegmentOverlapEditor::left_overlap_trim_first()
+int SegmentOverlapEditor::left_overlap_trim_first(TcpReassemblerState& trs)
 {
-    DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", overlap);
-    assert(SEQ_GT(seq, left->seq));
+    DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", trs.sos.overlap);
+    assert(SEQ_GT(trs.sos.seq, trs.sos.left->seq));
 
-    len = tsd->get_seg_len();
-    overlap = left->seq + left->payload_size - seq;
+    trs.sos.len = trs.sos.tsd->get_seg_len();
+    trs.sos.overlap = trs.sos.left->seq + trs.sos.left->payload_size - trs.sos.seq;
 
-    if ( overlap > 0 )
+    if ( trs.sos.overlap > 0 )
     {
         tcpStats.overlaps++;
-        overlap_count++;
+        trs.sos.overlap_count++;
 
-        if ( SEQ_GEQ(left->seq + left->payload_size, seq + len)  )
+        if ( SEQ_GEQ(trs.sos.left->seq + trs.sos.left->payload_size, trs.sos.seq + trs.sos.len)  )
         {
             // existing packet overlaps new on both sides.  Drop the new data.
             DebugMessage(DEBUG_STREAM_STATE, "left overlap, honoring old data\n");
-            seq += len;
+            trs.sos.seq += trs.sos.len;
         }
         else
         {
             /* Otherwise, trim the old data accordingly */
-            left->payload_size -= ( int16_t )overlap;
-            seg_bytes_logical -= overlap;
+            trs.sos.left->payload_size -= ( int16_t )trs.sos.overlap;
+            trs.sos.seg_bytes_logical -= trs.sos.overlap;
             DebugMessage(DEBUG_STREAM_STATE, "left overlap, honoring new data\n");
         }
     }
@@ -223,130 +286,134 @@ int SegmentOverlapEditor::left_overlap_trim_first()
     return STREAM_INSERT_OK;
 }
 
-int SegmentOverlapEditor::left_overlap_keep_last()
+int SegmentOverlapEditor::left_overlap_keep_last(TcpReassemblerState& trs)
 {
-    DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", overlap);
-    assert(SEQ_GT(seq, left->seq));
+    DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", trs.sos.overlap);
+    assert(SEQ_GT(trs.sos.seq, trs.sos.left->seq));
 
-    len = tsd->get_seg_len();
-    overlap = left->seq + left->payload_size - seq;
+    trs.sos.len = trs.sos.tsd->get_seg_len();
+    trs.sos.overlap = trs.sos.left->seq + trs.sos.left->payload_size - trs.sos.seq;
 
-    if ( overlap > 0 )
+    if ( trs.sos.overlap > 0 )
     {
         tcpStats.overlaps++;
-        overlap_count++;
+        trs.sos.overlap_count++;
 
         /* True "Last" policy" */
-        if ( SEQ_GT(left->seq + left->payload_size, seq + len) )
+        if ( SEQ_GT(trs.sos.left->seq + trs.sos.left->payload_size, trs.sos.seq + trs.sos.len) )
         {
             /* New data is overlapped on both sides by existing data.  Existing data needs to be
              * split and the new data inserted in the middle.
              * Need to duplicate left. Adjust that seq by + (seq + len) and
              * size by - (seq + len - left->seq).
              */
-            int rc = dup_reassembly_segment(left, &right);
+            int rc = dup_reassembly_segment(trs, trs.sos.left, &trs.sos.right);
 
             if ( rc != STREAM_INSERT_OK )
                 return rc;
 
-            left->payload_size -= ( int16_t )overlap;
+            trs.sos.left->payload_size -= ( int16_t )trs.sos.overlap;
 
-            right->seq = seq + len;
-            uint16_t delta = ( int16_t )( right->seq - left->seq );
-            right->payload_size -= delta;
-            right->offset += delta;
+            trs.sos.right->seq = trs.sos.seq + trs.sos.len;
+            uint16_t delta = ( int16_t )( trs.sos.right->seq - trs.sos.left->seq );
+            trs.sos.right->payload_size -= delta;
+            trs.sos.right->offset += delta;
 
-            seg_bytes_logical -= len;
+            trs.sos.seg_bytes_logical -= trs.sos.len;
         }
         else
         {
-            left->payload_size -= (int16_t)overlap;
-            seg_bytes_logical -= overlap;
+            trs.sos.left->payload_size -= (int16_t)trs.sos.overlap;
+            trs.sos.seg_bytes_logical -= trs.sos.overlap;
         }
     }
 
     return STREAM_INSERT_OK;
 }
 
-void SegmentOverlapEditor::right_overlap_truncate_existing()
+void SegmentOverlapEditor::right_overlap_truncate_existing(TcpReassemblerState& trs)
 {
     DebugMessage(DEBUG_STREAM_STATE, "Got partial right overlap\n");
-    if ( SEQ_EQ(right->seq, seq) && ( reassembly_policy != ReassemblyPolicy::OS_LAST ) )
+    if ( SEQ_EQ(trs.sos.right->seq, trs.sos.seq) && ( trs.sos.reassembly_policy != ReassemblyPolicy::OS_LAST ) )
     {
-        slide = ( right->seq + right->payload_size - seq );
-        seq += slide;
+        trs.sos.slide = ( trs.sos.right->seq + trs.sos.right->payload_size - trs.sos.seq );
+        trs.sos.seq += trs.sos.slide;
     }
     else
     {
         /* partial overlap */
-        right->seq += overlap;
-        right->offset += overlap;
-        right->payload_size -= (int16_t)overlap;
-        seg_bytes_logical -= overlap;
-        total_bytes_queued -= overlap;
+        trs.sos.right->seq += trs.sos.overlap;
+        trs.sos.right->offset += trs.sos.overlap;
+        trs.sos.right->payload_size -= (int16_t)trs.sos.overlap;
+        trs.sos.seg_bytes_logical -= trs.sos.overlap;
+        trs.sos.total_bytes_queued -= trs.sos.overlap;
     }
 }
 
-void SegmentOverlapEditor::right_overlap_truncate_new()
+void SegmentOverlapEditor::right_overlap_truncate_new(TcpReassemblerState& trs)
 {
-    if (tcp_ips_data == NORM_MODE_ON)
+    if (trs.sos.tcp_ips_data == NORM_MODE_ON)
     {
-        unsigned offset = right->seq - tsd->get_seg_seq();
-        unsigned length = tsd->get_seg_seq() + tsd->get_seg_len() - right->seq;
-        memcpy(const_cast<uint8_t*>(tsd->get_pkt()->data) + offset, right->payload(), length);
-        tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
+        unsigned offset = trs.sos.right->seq - trs.sos.tsd->get_seg_seq();
+        unsigned length = trs.sos.tsd->get_seg_seq() + trs.sos.tsd->get_seg_len() -
+            trs.sos.right->seq;
+        memcpy(const_cast<uint8_t*>(trs.sos.tsd->get_pkt()->data) + offset,
+            trs.sos.right->payload(), length);
+        trs.sos.tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
     }
 
-    tcp_norm_stats[PC_TCP_IPS_DATA][tcp_ips_data]++;
-    trunc_len = overlap;
+    tcp_norm_stats[PC_TCP_IPS_DATA][trs.sos.tcp_ips_data]++;
+    trs.sos.trunc_len = trs.sos.overlap;
 }
 
 // REASSEMBLY_POLICY_FIRST:
 // REASSEMBLY_POLICY_VISTA:
-int SegmentOverlapEditor::full_right_overlap_truncate_new()
+int SegmentOverlapEditor::full_right_overlap_truncate_new(TcpReassemblerState& trs)
 {
     DebugMessage(DEBUG_STREAM_STATE, "Got full right overlap, truncating new\n");
 
-    if ( tcp_ips_data == NORM_MODE_ON )
+    if ( trs.sos.tcp_ips_data == NORM_MODE_ON )
     {
-        unsigned offset = right->seq - tsd->get_seg_seq();
-        memcpy(const_cast<uint8_t*>(tsd->get_pkt()->data) + offset, right->payload(), right->payload_size);
-        tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
+        unsigned offset = trs.sos.right->seq - trs.sos.tsd->get_seg_seq();
+        memcpy(const_cast<uint8_t*>(trs.sos.tsd->get_pkt()->data) + offset,
+            trs.sos.right->payload(), trs.sos.right->payload_size);
+        trs.sos.tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
     }
 
-    tcp_norm_stats[PC_TCP_IPS_DATA][tcp_ips_data]++;
+    tcp_norm_stats[PC_TCP_IPS_DATA][trs.sos.tcp_ips_data]++;
 
-    if ( SEQ_EQ(right->seq, seq) )
+    if ( SEQ_EQ(trs.sos.right->seq, trs.sos.seq) )
     {
         /* Overlap is greater than or equal to right->size
          * slide gets set before insertion */
-        seq += right->payload_size;
-        left = right;
-        right = right->next;
+        trs.sos.seq += trs.sos.right->payload_size;
+        trs.sos.left = trs.sos.right;
+        trs.sos.right = trs.sos.right->next;
 
         /* Adjusted seq is fully overlapped */
-        if ( SEQ_EQ(seq, seq_end) )
+        if ( SEQ_EQ(trs.sos.seq, trs.sos.seq_end) )
             return STREAM_INSERT_OK;
     }
     else
     {
         /* seq is less than right->seq,  trunc length is reset to 0 at beginning of loop */
-        trunc_len = overlap;
+        trs.sos.trunc_len = trs.sos.overlap;
 
         /* insert this one, and see if we need to chunk it up
           Adjust slide so that is correct relative to orig seq */
-        slide = seq - tsd->get_seg_seq();
-        int rc = add_reassembly_segment(*tsd, len, slide, trunc_len, seq, left);
+        trs.sos.slide = trs.sos.seq - trs.sos.tsd->get_seg_seq();
+        int rc = add_reassembly_segment(trs, *trs.sos.tsd, trs.sos.len, trs.sos.slide,
+            trs.sos.trunc_len, trs.sos.seq, trs.sos.left);
         if ( rc != STREAM_INSERT_OK )
             return rc;
 
         // Set seq to end of right since overlap was greater than or equal to right->size and
         // inserted seq has been truncated to beginning of right and reset trunc length to 0
         // since we may fall out of loop if next right is NULL
-        seq = right->seq + right->payload_size;
-        left = right;
-        right = right->next;
-        trunc_len = 0;
+        trs.sos.seq = trs.sos.right->seq + trs.sos.right->payload_size;
+        trs.sos.left = trs.sos.right;
+        trs.sos.right = trs.sos.right->next;
+        trs.sos.trunc_len = 0;
     }
 
     return STREAM_INSERT_OK;
@@ -356,15 +423,16 @@ int SegmentOverlapEditor::full_right_overlap_truncate_new()
 // REASSEMBLY_POLICY_WINDOWS2K3:
 // REASSEMBLY_POLICY_BSD:
 // REASSEMBLY_POLICY_MACOS:
-int SegmentOverlapEditor::full_right_overlap_os1()
+int SegmentOverlapEditor::full_right_overlap_os1(TcpReassemblerState& trs)
 {
-    if ( SEQ_GEQ(seq_end, right->seq + right->payload_size)  && SEQ_LT(seq, right->seq) )
+    if ( SEQ_GEQ(trs.sos.seq_end, trs.sos.right->seq + trs.sos.right->payload_size) and
+        SEQ_LT(trs.sos.seq, trs.sos.right->seq) )
     {
-        drop_old_segment();
+        drop_old_segment(trs);
     }
     else
     {
-        int rc = full_right_overlap_truncate_new();
+        int rc = full_right_overlap_truncate_new(trs);
         if ( rc != STREAM_INSERT_OK )
             return rc;
     }
@@ -375,19 +443,21 @@ int SegmentOverlapEditor::full_right_overlap_os1()
 // REASSEMBLY_POLICY_LINUX:
 // REASSEMBLY_POLICY_HPUX10:
 // REASSEMBLY_POLICY_IRIX:
-int SegmentOverlapEditor::full_right_overlap_os2()
+int SegmentOverlapEditor::full_right_overlap_os2(TcpReassemblerState& trs)
 {
-    if ( SEQ_GEQ(seq_end, right->seq + right->payload_size) && SEQ_LT(seq, right->seq) )
+    if ( SEQ_GEQ(trs.sos.seq_end, trs.sos.right->seq + trs.sos.right->payload_size) and
+        SEQ_LT(trs.sos.seq, trs.sos.right->seq) )
     {
-        drop_old_segment();
+        drop_old_segment(trs);
     }
-    else if ( SEQ_GT(seq_end, right->seq + right->payload_size) && SEQ_EQ(seq, right->seq) )
+    else if ( SEQ_GT(trs.sos.seq_end, trs.sos.right->seq + trs.sos.right->payload_size) and
+        SEQ_EQ(trs.sos.seq, trs.sos.right->seq) )
     {
-        drop_old_segment();
+        drop_old_segment(trs);
     }
     else
     {
-        int rc = full_right_overlap_truncate_new();
+        int rc = full_right_overlap_truncate_new(trs);
         if ( rc != STREAM_INSERT_OK )
             return rc;
     }
@@ -397,25 +467,25 @@ int SegmentOverlapEditor::full_right_overlap_os2()
 
 // REASSEMBLY_POLICY_HPUX11:
 // REASSEMBLY_POLICY_SOLARIS:
-int SegmentOverlapEditor::full_right_overlap_os3()
+int SegmentOverlapEditor::full_right_overlap_os3(TcpReassemblerState& trs)
 {
     // If this packet is wholly overlapping and the same size as a previous one and we have not
     // received the one immediately preceding, we take the FIRST.
-    if ( SEQ_EQ(right->seq, seq) && ( right->payload_size == len )
-        && ( left && !SEQ_EQ(left->seq + left->payload_size, seq) ) )
+    if ( SEQ_EQ(trs.sos.right->seq, trs.sos.seq) && (trs.sos.right->payload_size == trs.sos.len)
+        && (trs.sos.left && !SEQ_EQ(trs.sos.left->seq + trs.sos.left->payload_size, trs.sos.seq)) )
     {
-        right_overlap_truncate_new();
-
-        rdata += right->payload_size;
-        rsize -= right->payload_size;
-        rseq += right->payload_size;
-        seq += right->payload_size;
-        left = right;
-        right = right->next;
+        right_overlap_truncate_new(trs);
+
+        trs.sos.rdata += trs.sos.right->payload_size;
+        trs.sos.rsize -= trs.sos.right->payload_size;
+        trs.sos.rseq += trs.sos.right->payload_size;
+        trs.sos.seq += trs.sos.right->payload_size;
+        trs.sos.left = trs.sos.right;
+        trs.sos.right = trs.sos.right->next;
     }
     else
     {
-        drop_old_segment();
+        drop_old_segment(trs);
     }
 
     return STREAM_INSERT_OK;
@@ -423,25 +493,25 @@ int SegmentOverlapEditor::full_right_overlap_os3()
 
 //  REASSEMBLY_POLICY_OLD_LINUX:
 //  REASSEMBLY_POLICY_LAST:
-int SegmentOverlapEditor::full_right_overlap_os4()
+int SegmentOverlapEditor::full_right_overlap_os4(TcpReassemblerState& trs)
 {
-    drop_old_segment();
+    drop_old_segment(trs);
     return STREAM_INSERT_OK;
 }
 
-int SegmentOverlapEditor::full_right_overlap_os5()
+int SegmentOverlapEditor::full_right_overlap_os5(TcpReassemblerState& trs)
 {
-    return full_right_overlap_truncate_new();
+    return full_right_overlap_truncate_new(trs);
 }
 
-void SegmentOverlapEditor::print()
+void SegmentOverlapEditor::print(TcpReassemblerState& trs)
 {
-    LogMessage("    seglist_base_seq:   %X\n", seglist_base_seq);
-    LogMessage("    seglist head:       %p\n", (void*)seglist.head);
-    LogMessage("    seglist tail:       %p\n", (void*)seglist.tail);
-    LogMessage("    seglist next:       %p\n", (void*)seglist.next);
-    LogMessage("    seg_count:          %d\n", seg_count);
-    LogMessage("    seg_bytes_total:    %d\n", seg_bytes_total);
-    LogMessage("    seg_bytes_logical:  %d\n", seg_bytes_logical);
+    LogMessage("    seglist_base_seq:   %X\n", trs.sos.seglist_base_seq);
+    LogMessage("    seglist head:       %p\n", (void*)trs.sos.seglist.head);
+    LogMessage("    seglist tail:       %p\n", (void*)trs.sos.seglist.tail);
+    LogMessage("    seglist next:       %p\n", (void*)trs.sos.seglist.next);
+    LogMessage("    seg_count:          %d\n", trs.sos.seg_count);
+    LogMessage("    seg_bytes_total:    %d\n", trs.sos.seg_bytes_total);
+    LogMessage("    seg_bytes_logical:  %d\n", trs.sos.seg_bytes_logical);
 }
 
index 71ab5fe95f66814f5668d98191708131c2afa7f4..22a8f59c14f25115581f47debae9bc413ea848a0 100644 (file)
 #include "stream/tcp/tcp_segment_node.h"
 
 class TcpSession;
+class TcpStreamTracker;
 
 #define STREAM_INSERT_OK  0  // FIXIT-L replace with bool
 
-class SegmentOverlapEditor
+struct SegmentOverlapState
 {
-protected:
+    TcpSession* session;
+    TcpSegmentDescriptor* tsd;
+    TcpSegmentNode* left;
+    TcpSegmentNode* right;
+    const uint8_t* rdata;
 
-    SegmentOverlapEditor()
-    {
-        tcp_ips_data = Normalize_GetMode(NORM_TCP_IPS);
-    }
+    TcpSegmentList seglist;
+    ReassemblyPolicy reassembly_policy;
 
-    virtual ~SegmentOverlapEditor() = default;
+    uint32_t seglist_base_seq;      /* seq of first queued segment */
+    uint32_t seg_count;             /* number of current queued segments */
+    uint32_t seg_bytes_total;       /* total bytes currently queued */
+    uint32_t seg_bytes_logical;     /* logical bytes queued (total - overlaps) */
+    uint32_t total_bytes_queued;    /* total bytes queued (life of session) */
+    uint32_t total_segs_queued;     /* number of segments queued (life) */
+    uint32_t overlap_count;         /* overlaps encountered */
+
+    uint32_t seq;
+    uint32_t seq_end;
+    uint32_t rseq;
+
+    int32_t overlap;
+    int32_t slide;
+    int32_t trunc_len;
+
+    uint16_t len;
+    uint16_t rsize;
+    int8_t tcp_ips_data;
+
+    bool keep_segment;
 
-    void init_soe(TcpSegmentDescriptor& tsd, TcpSegmentNode* left, TcpSegmentNode* right)
+    ~SegmentOverlapState()
     {
-        this->tsd = &tsd;
-        this->left = left;
-        this->right = right;
-        seq = tsd.get_seg_seq();
-        seq_end = tsd.get_end_seq();
-        len = tsd.get_seg_len();
-        overlap = 0;
-        slide = 0;
-        trunc_len = 0;
-        rdata = tsd.get_pkt()->data;
-        rsize = tsd.get_seg_len();
-        rseq = tsd.get_seg_seq();
-        keep_segment = true;
+        seglist.reset();
     }
 
-    int eval_left();
-    int eval_right();
-
-    virtual bool is_segment_retransmit(bool*);
-    virtual void drop_old_segment();
-
-    virtual int left_overlap_keep_first();
-    virtual int left_overlap_trim_first();
-    virtual int left_overlap_keep_last();
-    virtual void right_overlap_truncate_existing();
-    virtual void right_overlap_truncate_new();
-    virtual int full_right_overlap_truncate_new();
-    virtual int full_right_overlap_os1();
-    virtual int full_right_overlap_os2();
-    virtual int full_right_overlap_os3();
-    virtual int full_right_overlap_os4();
-    virtual int full_right_overlap_os5();
-
-    virtual int insert_left_overlap() = 0;
-    virtual void insert_right_overlap() = 0;
-    virtual int insert_full_overlap() = 0;
-    virtual int add_reassembly_segment(TcpSegmentDescriptor&, int16_t, uint32_t, uint32_t,
-        uint32_t, TcpSegmentNode*) = 0;
-    virtual int dup_reassembly_segment(TcpSegmentNode*, TcpSegmentNode**) = 0;
-    virtual int delete_reassembly_segment(TcpSegmentNode*) = 0;
-    virtual void print();
-
-    TcpSession* session = nullptr;
-    ReassemblyPolicy reassembly_policy = ReassemblyPolicy::OS_DEFAULT;
-    NormMode tcp_ips_data;
+    void init_sos(TcpSession*, ReassemblyPolicy);
+    void init_soe(TcpSegmentDescriptor& tsd, TcpSegmentNode* left, TcpSegmentNode* right);
+};
 
-    TcpSegmentList seglist;
-    uint32_t seglist_base_seq = 0;      /* seq of first queued segment */
-    uint32_t seg_count = 0;             /* number of current queued segments */
-    uint32_t seg_bytes_total = 0;       /* total bytes currently queued */
-    uint32_t seg_bytes_logical = 0;     /* logical bytes queued (total - overlaps) */
-    uint32_t total_bytes_queued = 0;    /* total bytes queued (life of session) */
-    uint32_t total_segs_queued = 0;     /* number of segments queued (life) */
-    uint32_t overlap_count = 0;         /* overlaps encountered */
-
-    TcpSegmentDescriptor* tsd = nullptr;
-    TcpSegmentNode* left = nullptr;
-    TcpSegmentNode* right = nullptr;
-    const uint8_t* rdata = nullptr;
-    uint32_t seq = 0;
-    uint32_t seq_end = 0;
-    uint16_t len = 0;
-    int32_t overlap = 0;
-    int32_t slide = 0;
-    int32_t trunc_len = 0;
-    uint16_t rsize = 0;
-    uint32_t rseq = 0;
-    bool keep_segment = true;
+struct TcpReassemblerState
+{
+    SegmentOverlapState sos;
+    TcpStreamTracker* tracker;
+    uint32_t flush_count;   // number of flushed queued segments
+    uint32_t xtradata_mask; // extra data available to log
+    bool server_side;
+    uint8_t ignore_dir;
+    uint8_t packet_dir;
+};
+
+class SegmentOverlapEditor
+{
+protected:
+    SegmentOverlapEditor() { }
+    virtual ~SegmentOverlapEditor() = default;
+
+    int eval_left(TcpReassemblerState&);
+    int eval_right(TcpReassemblerState&);
+
+    virtual bool is_segment_retransmit(TcpReassemblerState&, bool*);
+    virtual void drop_old_segment(TcpReassemblerState&);
+
+    virtual int left_overlap_keep_first(TcpReassemblerState&);
+    virtual int left_overlap_trim_first(TcpReassemblerState&);
+    virtual int left_overlap_keep_last(TcpReassemblerState&);
+    virtual void right_overlap_truncate_existing(TcpReassemblerState&);
+    virtual void right_overlap_truncate_new(TcpReassemblerState&);
+    virtual int full_right_overlap_truncate_new(TcpReassemblerState&);
+    virtual int full_right_overlap_os1(TcpReassemblerState&);
+    virtual int full_right_overlap_os2(TcpReassemblerState&);
+    virtual int full_right_overlap_os3(TcpReassemblerState&);
+    virtual int full_right_overlap_os4(TcpReassemblerState&);
+    virtual int full_right_overlap_os5(TcpReassemblerState&);
+
+    virtual int insert_left_overlap(TcpReassemblerState&) = 0;
+    virtual void insert_right_overlap(TcpReassemblerState&) = 0;
+    virtual int insert_full_overlap(TcpReassemblerState&) = 0;
+
+    virtual int add_reassembly_segment(
+        TcpReassemblerState&, TcpSegmentDescriptor&, int16_t, uint32_t,
+        uint32_t, uint32_t, TcpSegmentNode*) = 0;
+
+    virtual int dup_reassembly_segment(TcpReassemblerState&, TcpSegmentNode*, TcpSegmentNode**) = 0;
+    virtual int delete_reassembly_segment(TcpReassemblerState&, TcpSegmentNode*) = 0;
+    virtual void print(TcpReassemblerState&);
 };
 
 #endif
index 203d810f5be28738212ac8e54003433d4aacea08..15eaebef2b1b4a334f24f9af96f1153150450b1f 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "utils/stats.h"
 
-#include "tcp_reassembler.h"
+#include "tcp_reassemblers.h"
 
 #ifndef REG_TEST
 #define S5TraceTCP(pkt, flow, tsd, evt)
@@ -42,7 +42,8 @@ static const char* const flushxt[] = { "IGN", "FPR", "PRE", "PRO", "PAF" };
 
 static THREAD_LOCAL int s5_trace_enabled = -1;  // FIXIT-L should use module trace feature
 
-inline void TraceEvent(const snort::Packet* p, TcpSegmentDescriptor*, uint32_t txd, uint32_t rxd)
+inline void TraceEvent(
+    const snort::Packet* p, TcpSegmentDescriptor*, uint32_t txd, uint32_t rxd)
 {
     int i;
     char flags[7] = "UAPRSF";
@@ -78,7 +79,7 @@ inline void TraceSession(const snort::Flow* lws)
         lws->ssn_state.session_flags, lws->client_port, lws->server_port);
 }
 
-inline void TraceState(const TcpStreamTracker* a, const TcpStreamTracker* b, const char* s)
+inline void TraceState(TcpStreamTracker* a, TcpStreamTracker* b, const char* s)
 {
     uint32_t ua = a->get_snd_una() ? LCL(a, get_snd_una) : 0;
     uint32_t ns = a->get_snd_nxt() ? LCL(a, get_snd_nxt) : 0;
@@ -94,21 +95,22 @@ inline void TraceState(const TcpStreamTracker* a, const TcpStreamTracker* b, con
 
     fprintf(stdout, "         FP=%s:%-4u SC=%-4u FL=%-4u SL=%-5u BS=%-4u",
         flushxt[a->flush_policy + paf], fpt,
-        a->reassembler->get_seg_count(), a->reassembler->get_flush_count(),
-        a->reassembler->get_seg_bytes_logical(),
-        a->reassembler->get_seglist_base_seq() - b->get_iss());
+        a->reassembler.get_seg_count(), a->reassembler.get_flush_count(),
+        a->reassembler.get_seg_bytes_logical(),
+        a->reassembler.get_seglist_base_seq() - b->get_iss());
 
     if (s5_trace_enabled == 2)
-        a->reassembler->trace_segments();
+        a->reassembler.trace_segments();
 
     fprintf(stdout, "\n");
 }
 
-inline void TraceTCP(const snort::Packet* p, const snort::Flow* lws, TcpSegmentDescriptor* tsd, int event)
+inline void TraceTCP(
+    const snort::Packet* p, const snort::Flow* lws, TcpSegmentDescriptor* tsd, int event)
 {
-    const TcpSession* ssn = (TcpSession*)lws->session;
-    const TcpStreamTracker* srv = ssn ? ssn->server : nullptr;
-    const TcpStreamTracker* cli = ssn ? ssn->client : nullptr;
+    TcpSession* ssn = (TcpSession*)lws->session;
+    TcpStreamTracker* srv = ssn ? &ssn->server : nullptr;
+    TcpStreamTracker* cli = ssn ? &ssn->client : nullptr;
 
     const char* cdir = "?", * sdir = "?";
     uint32_t txd = 0, rxd = 0;
@@ -141,7 +143,8 @@ inline void TraceTCP(const snort::Packet* p, const snort::Flow* lws, TcpSegmentD
     }
 }
 
-inline void S5TraceTCP(const snort::Packet* p, const snort::Flow* lws, TcpSegmentDescriptor* tsd, int event)
+inline void S5TraceTCP(
+    const snort::Packet* p, const snort::Flow* lws, TcpSegmentDescriptor* tsd, int event)
 {
     if (!s5_trace_enabled)
         return;
@@ -162,7 +165,6 @@ inline void S5TraceTCP(const snort::Packet* p, const snort::Flow* lws, TcpSegmen
 
     TraceTCP(p, lws, tsd, event);
 }
-
 #endif  // REG_TEST
 
 #endif
index dcadac0c7a3ac38299b6dc9514e2b36933bf1655..4ec589ff24a079c76d9b1abcf29fe446712689f6 100644 (file)
@@ -85,8 +85,8 @@ struct TcpStats
     PegCount exceeded_max_segs;
     PegCount exceeded_max_bytes;
     PegCount internalEvents;
-    PegCount s5tcp1;
-    PegCount s5tcp2;
+    PegCount client_cleanups;
+    PegCount server_cleanups;
     PegCount mem_in_use;
     PegCount sessions_initializing;
     PegCount sessions_established;
index ee3a9f619c476deae8416372e24a39715cf48b01..40fb2d83ce88bf203aec8ccbaa0644706cbc34a2 100644 (file)
@@ -25,6 +25,9 @@
 
 #include "tcp_normalizer.h"
 
+#include "stream/libtcp/tcp_stream_session.h"
+#include "stream/libtcp/tcp_stream_tracker.h"
+
 #include "main/snort_debug.h"
 #include "packet_io/active.h"
 
@@ -45,20 +48,6 @@ static const PegInfo pegName[] =
     { CountType::END, nullptr, nullptr }
 };
 
-TcpNormalizer::TcpNormalizer(StreamPolicy os_policy, TcpSession* session,
-    TcpStreamTracker* tracker) :
-    os_policy(os_policy), session(session), tracker(tracker)
-{
-    tcp_ips_enabled = Normalize_IsEnabled(NORM_TCP_IPS);
-    trim_syn = Normalize_GetMode(NORM_TCP_TRIM_SYN);
-    trim_rst = Normalize_GetMode(NORM_TCP_TRIM_RST);
-    trim_win = Normalize_GetMode(NORM_TCP_TRIM_WIN);
-    trim_mss = Normalize_GetMode(NORM_TCP_TRIM_MSS);
-    strip_ecn = Normalize_GetMode(NORM_TCP_ECN_STR);
-    tcp_block = Normalize_GetMode(NORM_TCP_BLOCK);
-    opt_block = Normalize_GetMode(NORM_TCP_OPT);
-}
-
 const PegInfo* TcpNormalizer::get_normalization_pegs()
 {
     return pegName;
@@ -71,6 +60,7 @@ NormPegs TcpNormalizer::get_normalization_counts(unsigned& c)
 }
 
 void TcpNormalizer::trim_payload(
+    TcpNormalizerState&,
     TcpSegmentDescriptor& tsd, uint32_t max, NormMode mode, TcpPegCounts peg)
 {
     if (mode == NORM_MODE_ON)
@@ -85,6 +75,7 @@ void TcpNormalizer::trim_payload(
 }
 
 bool TcpNormalizer::strip_tcp_timestamp(
+    TcpNormalizerState&,
     TcpSegmentDescriptor& tsd, const tcp::TcpOption* opt, NormMode mode)
 {
     tcp_norm_stats[PC_TCP_TS_NOP][mode]++;
@@ -100,9 +91,10 @@ bool TcpNormalizer::strip_tcp_timestamp(
     return false;
 }
 
-bool TcpNormalizer::packet_dropper(TcpSegmentDescriptor& tsd, NormFlags f)
+bool TcpNormalizer::packet_dropper(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, NormFlags f)
 {
-    const NormMode mode = (f == NORM_TCP_BLOCK) ? tcp_block : opt_block;
+    const int8_t mode = (f == NORM_TCP_BLOCK) ? tns.tcp_block : tns.opt_block;
 
     tcp_norm_stats[PC_TCP_BLOCK][mode]++;
 
@@ -115,79 +107,87 @@ bool TcpNormalizer::packet_dropper(TcpSegmentDescriptor& tsd, NormFlags f)
     return false;
 }
 
-void TcpNormalizer::trim_syn_payload(TcpSegmentDescriptor& tsd, uint32_t max)
+void TcpNormalizer::trim_syn_payload(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
 {
     if (tsd.get_seg_len() > max)
-        trim_payload(tsd, max, trim_syn, PC_TCP_TRIM_SYN);
+        trim_payload(tns, tsd, max, (NormMode)tns.trim_syn, PC_TCP_TRIM_SYN);
 }
 
-void TcpNormalizer::trim_rst_payload(TcpSegmentDescriptor& tsd, uint32_t max)
+void TcpNormalizer::trim_rst_payload(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
 {
     if (tsd.get_seg_len() > max)
-        trim_payload(tsd, max, trim_rst, PC_TCP_TRIM_RST);
+        trim_payload(tns, tsd, max, (NormMode)tns.trim_rst, PC_TCP_TRIM_RST);
 }
 
-void TcpNormalizer::trim_win_payload(TcpSegmentDescriptor& tsd, uint32_t max)
+void TcpNormalizer::trim_win_payload(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
 {
     if (tsd.get_seg_len() > max)
-        trim_payload(tsd, max, trim_win, PC_TCP_TRIM_WIN);
+        trim_payload(tns, tsd, max, (NormMode)tns.trim_win, PC_TCP_TRIM_WIN);
 }
 
-void TcpNormalizer::trim_mss_payload(TcpSegmentDescriptor& tsd, uint32_t max)
+void TcpNormalizer::trim_mss_payload(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, uint32_t max)
 {
     if (tsd.get_seg_len() > max)
-        trim_payload(tsd, max, trim_mss, PC_TCP_TRIM_MSS);
+        trim_payload(tns, tsd, max, (NormMode)tns.trim_mss, PC_TCP_TRIM_MSS);
 }
 
-void TcpNormalizer::ecn_tracker(const tcp::TCPHdr* tcph, bool req3way)
+void TcpNormalizer::ecn_tracker(
+    TcpNormalizerState& tns, const tcp::TCPHdr* tcph, bool req3way)
 {
     if ( tcph->is_syn_ack() )
     {
-        if ( !req3way || session->ecn )
-            session->ecn = ((tcph->th_flags & (TH_ECE | TH_CWR)) == TH_ECE);
+        if ( !req3way || tns.session->ecn )
+            tns.session->ecn = ((tcph->th_flags & (TH_ECE | TH_CWR)) == TH_ECE);
     }
     else if ( tcph->is_syn() )
-        session->ecn = tcph->are_flags_set(TH_ECE | TH_CWR);
+        tns.session->ecn = tcph->are_flags_set(TH_ECE | TH_CWR);
 }
 
-void TcpNormalizer::ecn_stripper(Packet* p)
+void TcpNormalizer::ecn_stripper(
+    TcpNormalizerState& tns, Packet* p)
 {
-    if (!session->ecn && (p->ptrs.tcph->th_flags & (TH_ECE | TH_CWR)))
+    if (!tns.session->ecn && (p->ptrs.tcph->th_flags & (TH_ECE | TH_CWR)))
     {
-        if (strip_ecn == NORM_MODE_ON)
+        if (tns.strip_ecn == NORM_MODE_ON)
         {
             (const_cast<tcp::TCPHdr*>(p->ptrs.tcph))->th_flags &= ~(TH_ECE | TH_CWR);
             p->packet_flags |= PKT_MODIFIED;
         }
 
-        tcp_norm_stats[PC_TCP_ECN_SSN][strip_ecn]++;
+        tcp_norm_stats[PC_TCP_ECN_SSN][tns.strip_ecn]++;
     }
 }
 
 // don't use the window if we may have missed scaling
 // one way zero window is uninitialized
 // two way zero window is actually closed (regardless of scaling)
-uint32_t TcpNormalizer::get_stream_window(TcpSegmentDescriptor& tsd)
+uint32_t TcpNormalizer::get_stream_window(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
     int32_t window;
 
-    if ( tracker->get_snd_wnd() )
+    if ( tns.tracker->get_snd_wnd() )
     {
-        if ( !(session->flow->session_state & STREAM_STATE_MIDSTREAM ) )
-            return tracker->get_snd_wnd();
+        if ( !(tns.session->flow->session_state & STREAM_STATE_MIDSTREAM ) )
+            return tns.tracker->get_snd_wnd();
     }
-    else if ( session->flow->two_way_traffic() )
-        return tracker->get_snd_wnd();
+    else if ( tns.session->flow->two_way_traffic() )
+        return tns.tracker->get_snd_wnd();
 
     // ensure the data is in the window
-    window = tsd.get_end_seq() - tracker->r_win_base;
+    window = tsd.get_end_seq() - tns.tracker->r_win_base;
     if ( window < 0 )
         window = 0;
 
     return (uint32_t)window;
 }
 
-uint32_t TcpNormalizer::get_tcp_timestamp(TcpSegmentDescriptor& tsd, bool strip)
+uint32_t TcpNormalizer::get_tcp_timestamp(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd, bool strip)
 {
     DebugMessage(DEBUG_STREAM_STATE, "Getting timestamp...\n");
 
@@ -201,7 +201,7 @@ uint32_t TcpNormalizer::get_tcp_timestamp(TcpSegmentDescriptor& tsd, bool strip)
             bool stripped = false;
 
             if (strip)
-                stripped = strip_tcp_timestamp(tsd, &opt, opt_block);
+                stripped = strip_tcp_timestamp(tns, tsd, &opt, (NormMode)tns.opt_block);
 
             if (!stripped)
             {
@@ -218,15 +218,16 @@ uint32_t TcpNormalizer::get_tcp_timestamp(TcpSegmentDescriptor& tsd, bool strip)
     return TF_NONE;
 }
 
-bool TcpNormalizer::validate_rst_seq_geq(TcpSegmentDescriptor& tsd)
+bool TcpNormalizer::validate_rst_seq_geq(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
     DebugFormat(DEBUG_STREAM_STATE,
         "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
-        tsd.get_end_seq(), tracker->r_win_base, tsd.get_seg_seq(), tracker->r_nxt_ack +
-        get_stream_window(tsd));
+        tsd.get_end_seq(), tns.tracker->r_win_base, tsd.get_seg_seq(), tns.tracker->r_nxt_ack +
+        get_stream_window(tns, tsd));
 
     // FIXIT-H check for r_win_base == 0 is hack for uninitialized r_win_base, fix this
-    if ( ( tracker->r_nxt_ack == 0 ) || SEQ_GEQ(tsd.get_seg_seq(), tracker->r_nxt_ack) )
+    if ( ( tns.tracker->r_nxt_ack == 0 ) || SEQ_GEQ(tsd.get_seg_seq(), tns.tracker->r_nxt_ack) )
     {
         DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (>= next seq)!\n");
         return true;
@@ -236,21 +237,22 @@ bool TcpNormalizer::validate_rst_seq_geq(TcpSegmentDescriptor& tsd)
     return false;
 }
 
-bool TcpNormalizer::validate_rst_end_seq_geq(TcpSegmentDescriptor& tsd)
+bool TcpNormalizer::validate_rst_end_seq_geq(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
     DebugFormat(DEBUG_STREAM_STATE,
         "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
-        tsd.get_end_seq(), tracker->r_win_base, tsd.get_seg_seq(), tracker->r_nxt_ack +
-        get_stream_window(tsd));
+        tsd.get_end_seq(), tns.tracker->r_win_base, tsd.get_seg_seq(), tns.tracker->r_nxt_ack +
+        get_stream_window(tns, tsd));
 
     // FIXIT-H check for r_win_base == 0 is hack for uninitialized r_win_base, fix this
-    if ( tracker->r_win_base == 0 )
+    if ( tns.tracker->r_win_base == 0 )
         return true;
 
-    if ( SEQ_GEQ(tsd.get_end_seq(), tracker->r_win_base))
+    if ( SEQ_GEQ(tsd.get_end_seq(), tns.tracker->r_win_base))
     {
         // reset must be admitted when window closed
-        if (SEQ_LEQ(tsd.get_seg_seq(), tracker->r_win_base + get_stream_window(tsd)))
+        if (SEQ_LEQ(tsd.get_seg_seq(), tns.tracker->r_win_base + get_stream_window(tns, tsd)))
         {
             DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (within window)!\n");
             return true;
@@ -261,15 +263,16 @@ bool TcpNormalizer::validate_rst_end_seq_geq(TcpSegmentDescriptor& tsd)
     return false;
 }
 
-bool TcpNormalizer::validate_rst_seq_eq(TcpSegmentDescriptor& tsd)
+bool TcpNormalizer::validate_rst_seq_eq(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
     DebugFormat(DEBUG_STREAM_STATE,
         "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
-        tsd.get_end_seq(), tracker->r_win_base, tsd.get_seg_seq(), tracker->r_nxt_ack +
-        get_stream_window(tsd));
+        tsd.get_end_seq(), tns.tracker->r_win_base, tsd.get_seg_seq(),
+        tns.tracker->r_nxt_ack + get_stream_window(tns, tsd));
 
     // FIXIT-H check for r_nxt_ack == 0 is hack for uninitialized r_nxt_ack, fix this
-    if ( ( tracker->r_nxt_ack == 0 ) || SEQ_EQ(tsd.get_seg_seq(), tracker->r_nxt_ack) )
+    if ( ( tns.tracker->r_nxt_ack == 0 ) || SEQ_EQ(tsd.get_seg_seq(), tns.tracker->r_nxt_ack) )
     {
         DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (next seq)!\n");
         return true;
@@ -283,33 +286,35 @@ bool TcpNormalizer::validate_rst_seq_eq(TcpSegmentDescriptor& tsd)
 // for all states but syn-sent (handled above).  however, we
 // validate here based on how various implementations actually
 // handle a rst.
-bool TcpNormalizer::validate_rst(TcpSegmentDescriptor& tsd)
+bool TcpNormalizer::validate_rst(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return validate_rst_seq_eq(tsd);
+    return validate_rst_seq_eq(tns, tsd);
 }
 
-int TcpNormalizer::validate_paws_timestamp(TcpSegmentDescriptor& tsd)
+int TcpNormalizer::validate_paws_timestamp(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    if ( ( (int)( ( tsd.get_ts() - peer_tracker->get_ts_last() ) + paws_ts_fudge ) ) < 0 )
+    if ( ( (int)( ( tsd.get_ts() - tns.peer_tracker->get_ts_last() ) + tns.paws_ts_fudge ) ) < 0 )
     {
         DebugMessage(DEBUG_STREAM_STATE, "Packet outside PAWS window, dropping\n");
         /* bail, we've got a packet outside the PAWS window! */
         //inc_tcp_discards();
-        ( ( TcpSession* )tsd.get_flow()->session )->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
-        packet_dropper(tsd, NORM_TCP_OPT);
+        tns.session->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
+        packet_dropper(tns, tsd, NORM_TCP_OPT);
         return ACTION_BAD_PKT;
     }
-    else if ( ( peer_tracker->get_ts_last() != 0 )
-        && ( ( uint32_t )tsd.get_pkt()->pkth->ts.tv_sec > peer_tracker->get_ts_last_packet() +
+    else if ( ( tns.peer_tracker->get_ts_last() != 0 )
+        && ( ( uint32_t )tsd.get_pkt()->pkth->ts.tv_sec > tns.peer_tracker->get_ts_last_packet() +
         PAWS_24DAYS ) )
     {
         /* this packet is from way too far into the future */
         DebugFormat(DEBUG_STREAM_STATE,
             "packet PAWS timestamp way too far ahead of last packet %ld %u...\n",
-            tsd.get_pkt()->pkth->ts.tv_sec, peer_tracker->get_ts_last_packet() );
+            tsd.get_pkt()->pkth->ts.tv_sec, tns.peer_tracker->get_ts_last_packet() );
         //inc_tcp_discards();
-        ( ( TcpSession* )tsd.get_flow()->session )->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
-        packet_dropper(tsd, NORM_TCP_OPT);
+        tns.session->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
+        packet_dropper(tns, tsd, NORM_TCP_OPT);
         return ACTION_BAD_PKT;
     }
     else
@@ -319,20 +324,22 @@ int TcpNormalizer::validate_paws_timestamp(TcpSegmentDescriptor& tsd)
     }
 }
 
-bool TcpNormalizer::is_paws_ts_checked_required(TcpSegmentDescriptor&)
+bool TcpNormalizer::is_paws_ts_checked_required(
+    TcpNormalizerState&, TcpSegmentDescriptor&)
 {
     return true;
 }
 
-int TcpNormalizer::validate_paws(TcpSegmentDescriptor& tsd)
+int TcpNormalizer::validate_paws(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    tcp_ts_flags = get_tcp_timestamp(tsd, false);
-    if ( tcp_ts_flags )
+    tns.tcp_ts_flags = get_tcp_timestamp(tns, tsd, false);
+    if ( tns.tcp_ts_flags )
     {
-        bool check_ts = is_paws_ts_checked_required(tsd);
+        bool check_ts = is_paws_ts_checked_required(tns, tsd);
 
         if ( check_ts )
-            return validate_paws_timestamp(tsd);
+            return validate_paws_timestamp(tns, tsd);
         else
             return ACTION_NOTHING;
     }
@@ -343,38 +350,39 @@ int TcpNormalizer::validate_paws(TcpSegmentDescriptor& tsd)
         //   with the missing timestamp.  Log an alert, but continue to process the packet
         DebugMessage(DEBUG_STREAM_STATE,
             "packet no timestamp, had one earlier from this side...ok for now...\n");
-        ( ( TcpSession* )tsd.get_flow()->session )->tel.set_tcp_event(EVENT_NO_TIMESTAMP);
+        tns.session->tel.set_tcp_event(EVENT_NO_TIMESTAMP);
 
         /* Ignore the timestamp for this first packet, next one will checked. */
-        if ( session->config->policy == StreamPolicy::OS_SOLARIS )
-            tracker->clear_tf_flags(TF_TSTAMP);
+        if ( tns.session->config->policy == StreamPolicy::OS_SOLARIS )
+            tns.tracker->clear_tf_flags(TF_TSTAMP);
 
-        packet_dropper(tsd, NORM_TCP_OPT);
+        packet_dropper(tns, tsd, NORM_TCP_OPT);
         return ACTION_NOTHING;
     }
 }
 
-int TcpNormalizer::handle_paws_no_timestamps(TcpSegmentDescriptor& tsd)
+int TcpNormalizer::handle_paws_no_timestamps(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    tcp_ts_flags = get_tcp_timestamp(tsd, true);
-    if (tcp_ts_flags)
+    tns.tcp_ts_flags = get_tcp_timestamp(tns, tsd, true);
+    if (tns.tcp_ts_flags)
     {
-        if (!(peer_tracker->get_tf_flags() & TF_TSTAMP))
+        if (!(tns.peer_tracker->get_tf_flags() & TF_TSTAMP))
         {
             // SYN skipped, may have missed talker's timestamp , so set it now.
             if (tsd.get_ts() == 0)
-                peer_tracker->set_tf_flags(TF_TSTAMP | TF_TSTAMP_ZERO);
+                tns.peer_tracker->set_tf_flags(TF_TSTAMP | TF_TSTAMP_ZERO);
             else
-                peer_tracker->set_tf_flags(TF_TSTAMP);
+                tns.peer_tracker->set_tf_flags(TF_TSTAMP);
         }
 
         // Only valid to test this if listener is using timestamps. Otherwise, timestamp
         // in this packet is not used, regardless of its value.
-        if ( ( paws_drop_zero_ts && ( tsd.get_ts() == 0 ) ) && ( tracker->get_tf_flags() &
-            TF_TSTAMP ) )
+        if ( ( tns.paws_drop_zero_ts && ( tsd.get_ts() == 0 ) ) &&
+            ( tns.tracker->get_tf_flags() & TF_TSTAMP ) )
         {
             DebugMessage(DEBUG_STREAM_STATE, "Packet with 0 timestamp, dropping\n");
-            ( ( TcpSession* )tsd.get_flow()->session )->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
+            tns.session->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
             return ACTION_BAD_PKT;
         }
     }
@@ -382,7 +390,8 @@ int TcpNormalizer::handle_paws_no_timestamps(TcpSegmentDescriptor& tsd)
     return ACTION_NOTHING;
 }
 
-int TcpNormalizer::handle_paws(TcpSegmentDescriptor& tsd)
+int TcpNormalizer::handle_paws(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
     if ( tsd.get_tcph()->is_rst() )
         return ACTION_NOTHING;
@@ -396,26 +405,28 @@ int TcpNormalizer::handle_paws(TcpSegmentDescriptor& tsd)
     }
 #endif
 
-    if ((peer_tracker->get_tf_flags() & TF_TSTAMP) && (tracker->get_tf_flags() & TF_TSTAMP))
+    if ((tns.peer_tracker->get_tf_flags() & TF_TSTAMP) &&
+        (tns.tracker->get_tf_flags() & TF_TSTAMP))
     {
         DebugMessage(DEBUG_STREAM_STATE, "Checking timestamps for PAWS\n");
-        return validate_paws(tsd);
+        return validate_paws(tns, tsd);
     }
     else if (tsd.get_tcph()->is_syn_only())
     {
-        tcp_ts_flags = get_tcp_timestamp(tsd, false);
-        if (tcp_ts_flags)
-            peer_tracker->set_tf_flags(TF_TSTAMP);
+        tns.tcp_ts_flags = get_tcp_timestamp(tns, tsd, false);
+        if (tns.tcp_ts_flags)
+            tns.peer_tracker->set_tf_flags(TF_TSTAMP);
 
         return ACTION_NOTHING;
     }
     else
     {
-        return handle_paws_no_timestamps(tsd);
+        return handle_paws_no_timestamps(tns, tsd);
     }
 }
 
-uint16_t TcpNormalizer::set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize)
+uint16_t TcpNormalizer::set_urg_offset(
+    TcpNormalizerState&, const tcp::TCPHdr* tcph, uint16_t dsize)
 {
     uint16_t urg_offset = 0;
 
index 6a186b94382909aa270f9ddb83f76709e81ee44b..27ea3216331300a7048085c7df85c7ece8e38968 100644 (file)
 #ifndef TCP_NORMALIZER_H
 #define TCP_NORMALIZER_H
 
+#include "tcp_defs.h"
+
+#include "main/thread.h"
 #include "normalize/normalize.h"
 #include "protocols/tcp_options.h"
-#include "stream/tcp/tcp_session.h"
 
 enum TcpPegCounts
 {
@@ -41,127 +43,72 @@ enum TcpPegCounts
 
 extern THREAD_LOCAL PegCount tcp_norm_stats[PC_TCP_MAX][NORM_MODE_MAX];
 
+class TcpStreamSession;
+class TcpStreamTracker;
+class TcpSegmentDescriptor;
+
+struct TcpNormalizerState
+{
+    TcpStreamSession* session = nullptr;
+    TcpStreamTracker* tracker = nullptr;
+    TcpStreamTracker* peer_tracker = nullptr;
+
+    StreamPolicy os_policy = StreamPolicy::OS_INVALID;
+
+    int32_t paws_ts_fudge = 0;
+    int tcp_ts_flags = 0;
+
+    int8_t trim_syn = 0;
+    int8_t trim_rst = 0;
+    int8_t trim_win = 0;
+    int8_t trim_mss = 0;
+    int8_t strip_ecn = 0;
+    int8_t tcp_block = 0;
+    int8_t opt_block = 0;
+
+    bool tcp_ips_enabled = false;
+    bool paws_drop_zero_ts = false;
+};
+
 class TcpNormalizer
 {
 public:
-
-    virtual ~TcpNormalizer( ) = default;
-
-    virtual bool packet_dropper (TcpSegmentDescriptor&, NormFlags);
-    virtual void trim_syn_payload(TcpSegmentDescriptor&, uint32_t max = 0);
-    virtual void trim_rst_payload(TcpSegmentDescriptor&, uint32_t max = 0);
-    virtual void trim_win_payload(TcpSegmentDescriptor&, uint32_t max = 0);
-    virtual void trim_mss_payload(TcpSegmentDescriptor&, uint32_t max = 0);
-    virtual void ecn_tracker(const snort::tcp::TCPHdr*, bool req3way);
-    virtual void ecn_stripper(snort::Packet*);
-    virtual uint32_t get_stream_window(TcpSegmentDescriptor&);
-    virtual uint32_t get_tcp_timestamp(TcpSegmentDescriptor&, bool strip);
-    virtual int handle_paws(TcpSegmentDescriptor&);
-    virtual bool validate_rst(TcpSegmentDescriptor&);
-    virtual int handle_repeated_syn(TcpSegmentDescriptor&) = 0;
-    virtual uint16_t set_urg_offset(const snort::tcp::TCPHdr* tcph, uint16_t dsize);
+    using State = TcpNormalizerState;
+
+    virtual ~TcpNormalizer() = default;
+
+    virtual void init(State&) { }
+    virtual bool packet_dropper(State&, TcpSegmentDescriptor&, NormFlags);
+    virtual void trim_syn_payload(State&, TcpSegmentDescriptor&, uint32_t max = 0);
+    virtual void trim_rst_payload(State&, TcpSegmentDescriptor&, uint32_t max = 0);
+    virtual void trim_win_payload(State&, TcpSegmentDescriptor&, uint32_t max = 0);
+    virtual void trim_mss_payload(State&, TcpSegmentDescriptor&, uint32_t max = 0);
+    virtual void ecn_tracker(State&, const snort::tcp::TCPHdr*, bool req3way);
+    virtual void ecn_stripper(State&, snort::Packet*);
+    virtual uint32_t get_stream_window(State&, TcpSegmentDescriptor&);
+    virtual uint32_t get_tcp_timestamp(State&, TcpSegmentDescriptor&, bool strip);
+    virtual int handle_paws(State&, TcpSegmentDescriptor&);
+    virtual bool validate_rst(State&, TcpSegmentDescriptor&);
+    virtual int handle_repeated_syn(State&, TcpSegmentDescriptor&) = 0;
+    virtual uint16_t set_urg_offset(State&, const snort::tcp::TCPHdr* tcph, uint16_t dsize);
 
     static const PegInfo* get_normalization_pegs();
     static NormPegs get_normalization_counts(unsigned&);
 
-    void set_peer_tracker(TcpStreamTracker* peer_tracker)
-    {
-        this->peer_tracker = peer_tracker;
-    }
-
-    StreamPolicy get_os_policy() const
-    {
-        return os_policy;
-    }
-
-    bool is_paws_drop_zero_ts() const
-    {
-        return paws_drop_zero_ts;
-    }
-
-    int32_t get_paws_ts_fudge() const
-    {
-        return paws_ts_fudge;
-    }
-
-    NormMode get_opt_block() const
-    {
-        return opt_block;
-    }
-
-    NormMode get_strip_ecn() const
-    {
-        return strip_ecn;
-    }
-
-    NormMode get_tcp_block() const
-    {
-        return tcp_block;
-    }
-
-    NormMode get_trim_rst() const
-    {
-        return trim_rst;
-    }
-
-    NormMode get_trim_syn() const
-    {
-        return trim_syn;
-    }
-
-    NormMode get_trim_mss() const
-    {
-        return trim_mss;
-    }
-
-    NormMode get_trim_win() const
-    {
-        return trim_win;
-    }
-
-    bool is_tcp_ips_enabled() const
-    {
-        return tcp_ips_enabled;
-    }
-
-    bool handling_timestamps() const
-    {
-        return tcp_ts_flags != TF_NONE;
-    }
-
-    uint32_t get_timestamp_flags()
-    {
-        return tcp_ts_flags;
-    }
-
 protected:
-    TcpNormalizer(StreamPolicy, TcpSession*, TcpStreamTracker*);
-    virtual void trim_payload(TcpSegmentDescriptor&, uint32_t, NormMode, TcpPegCounts);
-    virtual bool strip_tcp_timestamp(TcpSegmentDescriptor&, const snort::tcp::TcpOption*, NormMode);
-    virtual bool validate_rst_seq_geq(TcpSegmentDescriptor&);
-    virtual bool validate_rst_end_seq_geq(TcpSegmentDescriptor&);
-    virtual bool validate_rst_seq_eq(TcpSegmentDescriptor&);
-
-    virtual int validate_paws_timestamp(TcpSegmentDescriptor&);
-    virtual bool is_paws_ts_checked_required(TcpSegmentDescriptor&);
-    virtual int validate_paws(TcpSegmentDescriptor&);
-    virtual int handle_paws_no_timestamps(TcpSegmentDescriptor&);
-
-    StreamPolicy os_policy;
-    TcpSession* session = nullptr;
-    TcpStreamTracker* tracker = nullptr;
-    TcpStreamTracker* peer_tracker = nullptr;
-    bool tcp_ips_enabled;
-    NormMode trim_syn;
-    NormMode trim_rst;
-    NormMode trim_win;
-    NormMode trim_mss;
-    NormMode strip_ecn;
-    NormMode tcp_block;
-    NormMode opt_block;
-    int32_t paws_ts_fudge = 0;
-    bool paws_drop_zero_ts = true;
-    int tcp_ts_flags = 0;
+    TcpNormalizer() = default;
+
+    virtual void trim_payload(State&, TcpSegmentDescriptor&, uint32_t, NormMode, TcpPegCounts);
+    virtual bool strip_tcp_timestamp(
+        State&, TcpSegmentDescriptor&, const snort::tcp::TcpOption*, NormMode);
+    virtual bool validate_rst_seq_geq(State&, TcpSegmentDescriptor&);
+    virtual bool validate_rst_end_seq_geq(State&, TcpSegmentDescriptor&);
+    virtual bool validate_rst_seq_eq(State&, TcpSegmentDescriptor&);
+
+    virtual int validate_paws_timestamp(State&, TcpSegmentDescriptor&);
+    virtual bool is_paws_ts_checked_required(State&, TcpSegmentDescriptor&);
+    virtual int validate_paws(State&, TcpSegmentDescriptor&);
+    virtual int handle_paws_no_timestamps(State&, TcpSegmentDescriptor&);
 };
 
 #endif
index 4b52552d47c4f3caaf03ceb9601e799bb7e70087..303c5203744ff59a22810d8aa3ddb1aed1440a22 100644 (file)
 #include "tcp_normalizers.h"
 
 #include "tcp_module.h"
+#include "stream/libtcp/tcp_segment_descriptor.h"
+#include "stream/libtcp/tcp_stream_session.h"
+#include "stream/libtcp/tcp_stream_tracker.h"
 
 using namespace snort;
 
 class TcpNormalizerFirst : public TcpNormalizer
 {
 public:
-    TcpNormalizerFirst(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_FIRST, session, tracker)
-    { }
+    TcpNormalizerFirst() = default;
 
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerLast : public TcpNormalizer
 {
 public:
-    TcpNormalizerLast(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_LAST, session, tracker)
-    { }
+    TcpNormalizerLast() = default;
 
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerLinux : public TcpNormalizer
 {
 public:
-    TcpNormalizerLinux(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_LINUX, session, tracker)
+    TcpNormalizerLinux() = default;
+
+    void init(TcpNormalizerState& tns) override
     {
         // Linux 2.6 accepts timestamp values that are off by one. so set fudge factor */
-        paws_ts_fudge = 1;
+        tns.paws_ts_fudge = 1;
     }
 
-    bool validate_rst(TcpSegmentDescriptor&) override;
-    bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
-    uint16_t set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize) override;
+    bool validate_rst(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    bool is_paws_ts_checked_required(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    uint16_t set_urg_offset(
+        TcpNormalizerState&, const tcp::TCPHdr* tcph, uint16_t dsize) override;
 };
 
 class TcpNormalizerOldLinux : public TcpNormalizer
 {
 public:
-    TcpNormalizerOldLinux(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_OLD_LINUX, session, tracker)
-    {
-        paws_drop_zero_ts = false;
-    }
+    TcpNormalizerOldLinux() = default;
 
-    bool validate_rst(TcpSegmentDescriptor&) override;
-    bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
-    uint16_t set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize) override;
+    void init(TcpNormalizerState& tns) override
+    { tns.paws_drop_zero_ts = false; }
+
+    bool validate_rst(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    bool is_paws_ts_checked_required(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    uint16_t set_urg_offset(
+        TcpNormalizerState&, const tcp::TCPHdr* tcph, uint16_t dsize) override;
 };
 
 class TcpNormalizerBSD : public TcpNormalizer
 {
 public:
-    TcpNormalizerBSD(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_BSD, session, tracker)
-    { }
+    TcpNormalizerBSD() = default;
 
-    bool validate_rst(TcpSegmentDescriptor&) override;
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    bool validate_rst(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerMacOS : public TcpNormalizer
 {
 public:
-    TcpNormalizerMacOS(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_MACOS, session, tracker)
-    { }
+    TcpNormalizerMacOS() = default;
 
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerSolaris : public TcpNormalizer
 {
 public:
-    TcpNormalizerSolaris(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_SOLARIS, session, tracker)
-    {
-        paws_drop_zero_ts = false;
-    }
+    TcpNormalizerSolaris() = default;
+
+    void init(TcpNormalizerState& tns) override
+    { tns.paws_drop_zero_ts = false; }
 
-    bool validate_rst(TcpSegmentDescriptor&) override;
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    bool validate_rst(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerIrix : public TcpNormalizer
 {
 public:
-    TcpNormalizerIrix(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_IRIX, session, tracker)
-    { }
+    TcpNormalizerIrix() = default;
 
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerHpux11 : public TcpNormalizer
 {
 public:
-    TcpNormalizerHpux11(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_HPUX11, session, tracker)
-    { }
+    TcpNormalizerHpux11() = default;
 
-    bool validate_rst(TcpSegmentDescriptor&) override;
-    bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    bool validate_rst(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    bool is_paws_ts_checked_required(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerHpux10 : public TcpNormalizer
 {
 public:
-    TcpNormalizerHpux10(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_HPUX10, session, tracker)
-    { }
+    TcpNormalizerHpux10() = default;
 
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerWindows : public TcpNormalizer
 {
 public:
-    TcpNormalizerWindows(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_WINDOWS, session, tracker)
-    {
-        paws_drop_zero_ts = false;
-    }
+    TcpNormalizerWindows() = default;
 
-    bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    void init(TcpNormalizerState& tns) override
+    { tns.paws_drop_zero_ts = false; }
+
+    bool is_paws_ts_checked_required(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerWindows2K3 : public TcpNormalizer
 {
 public:
-    TcpNormalizerWindows2K3(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_WINDOWS2K3, session, tracker)
-    {
-        paws_drop_zero_ts = false;
-    }
+    TcpNormalizerWindows2K3() = default;
+
+    void init(TcpNormalizerState& tns) override
+    { tns.paws_drop_zero_ts = false; }
 
-    bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    bool is_paws_ts_checked_required(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerVista : public TcpNormalizer
 {
 public:
-    TcpNormalizerVista(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_VISTA, session, tracker)
-    {
-        paws_drop_zero_ts = false;
-    }
+    TcpNormalizerVista() = default;
 
-    bool is_paws_ts_checked_required(TcpSegmentDescriptor&) override;
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    void init(TcpNormalizerState& tns) override
+    { tns.paws_drop_zero_ts = false; }
+
+    bool is_paws_ts_checked_required(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 class TcpNormalizerProxy : public TcpNormalizer
 {
 public:
-    TcpNormalizerProxy(TcpSession* session, TcpStreamTracker* tracker) :
-        TcpNormalizer(StreamPolicy::OS_PROXY, session, tracker)
-    { }
+    TcpNormalizerProxy() = default;
 
-    bool validate_rst(TcpSegmentDescriptor&) override;
-    int handle_paws(TcpSegmentDescriptor&) override;
-    int handle_repeated_syn(TcpSegmentDescriptor&) override;
+    bool validate_rst(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    int handle_paws(TcpNormalizerState&, TcpSegmentDescriptor&) override;
+    int handle_repeated_syn(TcpNormalizerState&, TcpSegmentDescriptor&) override;
 };
 
 
-static inline int handle_repeated_syn_mswin(TcpStreamTracker* talker, TcpStreamTracker* listener,
-    TcpSegmentDescriptor& tsd, TcpSession* session)
+static inline int handle_repeated_syn_mswin(
+    TcpStreamTracker* talker, TcpStreamTracker* listener,
+    TcpSegmentDescriptor& tsd, TcpStreamSession* session)
 {
     /* Windows has some strange behavior here.  If the sequence of the reset is the
      * next expected sequence, it Resets.  Otherwise it ignores the 2nd SYN.
@@ -221,8 +207,8 @@ static inline int handle_repeated_syn_mswin(TcpStreamTracker* talker, TcpStreamT
     }
 }
 
-static inline int handle_repeated_syn_bsd(TcpStreamTracker* talker, TcpSegmentDescriptor& tsd,
-    TcpSession* session)
+static inline int handle_repeated_syn_bsd(
+    TcpStreamTracker* talker, TcpSegmentDescriptor& tsd, TcpStreamSession* session)
 {
     /* If its not a retransmission of the actual SYN... RESET */
     if (!SEQ_EQ(tsd.get_seg_seq(), talker->get_iss()))
@@ -243,8 +229,8 @@ static inline int handle_repeated_syn_bsd(TcpStreamTracker* talker, TcpSegmentDe
 }
 
 // Linux, Win2k3 et al.  do not support timestamps if the 3whs used a 0 timestamp.
-static inline bool paws_3whs_zero_ts_not_supported(TcpStreamTracker* talker,
-    TcpStreamTracker* listener)
+static inline bool paws_3whs_zero_ts_not_supported(
+    TcpStreamTracker* talker, TcpStreamTracker* listener)
 {
     bool check_ts = true;
 
@@ -259,8 +245,8 @@ static inline bool paws_3whs_zero_ts_not_supported(TcpStreamTracker* talker,
 }
 
 // Older Linux ( <= 2.2 kernel ), Win32 (non 2K3) allow the 3whs to use a 0 timestamp.
-static inline bool paws_3whs_zero_ts_supported(TcpStreamTracker* talker,
-    TcpStreamTracker* listener, TcpSegmentDescriptor& tsd)
+static inline bool paws_3whs_zero_ts_supported(
+    TcpStreamTracker* talker, TcpStreamTracker* listener, TcpSegmentDescriptor& tsd)
 {
     bool check_ts = true;
 
@@ -296,67 +282,80 @@ static inline uint16_t set_urg_offset_linux(const tcp::TCPHdr* tcph, uint16_t ds
     return urg_offset;
 }
 
-int TcpNormalizerFirst::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerFirst::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_bsd(peer_tracker, tsd, session);
+    return handle_repeated_syn_bsd(tns.peer_tracker, tsd, tns.session);
 }
 
-int TcpNormalizerLast::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerLast::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_bsd(peer_tracker, tsd, session);
+    return handle_repeated_syn_bsd(tns.peer_tracker, tsd, tns.session);
 }
 
-bool TcpNormalizerLinux::validate_rst(TcpSegmentDescriptor& tsd)
+bool TcpNormalizerLinux::validate_rst(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return validate_rst_end_seq_geq(tsd);
+    return validate_rst_end_seq_geq(tns, tsd);
 }
 
-bool TcpNormalizerLinux::is_paws_ts_checked_required(TcpSegmentDescriptor&)
+bool TcpNormalizerLinux::is_paws_ts_checked_required(
+    TcpNormalizerState& tns, TcpSegmentDescriptor&)
 {
-    return paws_3whs_zero_ts_not_supported(peer_tracker, tracker);
+    return paws_3whs_zero_ts_not_supported(tns.peer_tracker, tns.tracker);
 }
 
-int TcpNormalizerLinux::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerLinux::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_bsd(peer_tracker, tsd, session);
+    return handle_repeated_syn_bsd(tns.peer_tracker, tsd, tns.session);
 }
 
-uint16_t TcpNormalizerLinux::set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize)
+uint16_t TcpNormalizerLinux::set_urg_offset(
+    TcpNormalizerState&, const tcp::TCPHdr* tcph, uint16_t dsize)
 {
     return set_urg_offset_linux(tcph, dsize);
 }
 
-bool TcpNormalizerOldLinux::validate_rst(TcpSegmentDescriptor& tsd)
+bool TcpNormalizerOldLinux::validate_rst(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return validate_rst_end_seq_geq(tsd);
+    return validate_rst_end_seq_geq(tns, tsd);
 }
 
-bool TcpNormalizerOldLinux::is_paws_ts_checked_required(TcpSegmentDescriptor& tsd)
+bool TcpNormalizerOldLinux::is_paws_ts_checked_required(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return paws_3whs_zero_ts_supported(peer_tracker, tracker, tsd);
+    return paws_3whs_zero_ts_supported(tns.peer_tracker, tns.tracker, tsd);
 }
 
-int TcpNormalizerOldLinux::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerOldLinux::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_bsd(peer_tracker, tsd, session);
+    return handle_repeated_syn_bsd(tns.peer_tracker, tsd, tns.session);
 }
 
-uint16_t TcpNormalizerOldLinux::set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize)
+uint16_t TcpNormalizerOldLinux::set_urg_offset(
+    TcpNormalizerState&, const tcp::TCPHdr* tcph, uint16_t dsize)
 {
     return set_urg_offset_linux(tcph, dsize);
 }
 
-bool TcpNormalizerBSD::validate_rst(TcpSegmentDescriptor& tsd)
+bool TcpNormalizerBSD::validate_rst(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return validate_rst_end_seq_geq(tsd);
+    return validate_rst_end_seq_geq(tns, tsd);
 }
 
-int TcpNormalizerBSD::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerBSD::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_bsd(peer_tracker, tsd, session);
+    return handle_repeated_syn_bsd(tns.peer_tracker, tsd, tns.session);
 }
 
-int TcpNormalizerMacOS::handle_repeated_syn(TcpSegmentDescriptor&)
+int TcpNormalizerMacOS::handle_repeated_syn(
+    TcpNormalizerState&, TcpSegmentDescriptor&)
 {
     /* MACOS ignores a 2nd SYN, regardless of the sequence number. */
     DebugMessage(DEBUG_STREAM_STATE,
@@ -365,173 +364,182 @@ int TcpNormalizerMacOS::handle_repeated_syn(TcpSegmentDescriptor&)
     return ACTION_NOTHING;
 }
 
-bool TcpNormalizerSolaris::validate_rst(TcpSegmentDescriptor& tsd)
+bool TcpNormalizerSolaris::validate_rst(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return validate_rst_end_seq_geq(tsd);
+    return validate_rst_end_seq_geq(tns, tsd);
 }
 
-int TcpNormalizerSolaris::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerSolaris::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_bsd(peer_tracker, tsd, session);
+    return handle_repeated_syn_bsd(tns.peer_tracker, tsd, tns.session);
 }
 
-int TcpNormalizerIrix::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerIrix::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_bsd(peer_tracker, tsd, session);
+    return handle_repeated_syn_bsd(tns.peer_tracker, tsd, tns.session);
 }
 
-bool TcpNormalizerHpux11::validate_rst(TcpSegmentDescriptor& tsd)
+bool TcpNormalizerHpux11::validate_rst(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return validate_rst_seq_geq(tsd);
+    return validate_rst_seq_geq(tns, tsd);
 }
 
-bool TcpNormalizerHpux11::is_paws_ts_checked_required(TcpSegmentDescriptor& tsd)
+bool TcpNormalizerHpux11::is_paws_ts_checked_required(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
     /* HPUX 11 ignores timestamps for out of order segments */
-    if ((tracker->get_tf_flags() & TF_MISSING_PKT) || !SEQ_EQ(tracker->r_nxt_ack,
+    if ((tns.tracker->get_tf_flags() & TF_MISSING_PKT) || !SEQ_EQ(tns.tracker->r_nxt_ack,
         tsd.get_seg_seq()))
         return false;
     else
         return true;
 }
 
-int TcpNormalizerHpux11::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerHpux11::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_bsd(peer_tracker, tsd, session);
+    return handle_repeated_syn_bsd(tns.peer_tracker, tsd, tns.session);
 }
 
-int TcpNormalizerHpux10::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerHpux10::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_bsd(peer_tracker, tsd, session);
+    return handle_repeated_syn_bsd(tns.peer_tracker, tsd, tns.session);
 }
 
-bool TcpNormalizerWindows::is_paws_ts_checked_required(TcpSegmentDescriptor& tsd)
+bool TcpNormalizerWindows::is_paws_ts_checked_required(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return paws_3whs_zero_ts_supported(peer_tracker, tracker, tsd);
+    return paws_3whs_zero_ts_supported(tns.peer_tracker, tns.tracker, tsd);
 }
 
-int TcpNormalizerWindows::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerWindows::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_mswin(peer_tracker, tracker, tsd, session);
+    return handle_repeated_syn_mswin(tns.peer_tracker, tns.tracker, tsd, tns.session);
 }
 
-int TcpNormalizerWindows2K3::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerWindows2K3::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_mswin(peer_tracker, tracker, tsd, session);
+    return handle_repeated_syn_mswin(tns.peer_tracker, tns.tracker, tsd, tns.session);
 }
 
-bool TcpNormalizerWindows2K3::is_paws_ts_checked_required(TcpSegmentDescriptor&)
+bool TcpNormalizerWindows2K3::is_paws_ts_checked_required(
+    TcpNormalizerState& tns, TcpSegmentDescriptor&)
 {
-    return paws_3whs_zero_ts_not_supported(peer_tracker, tracker);
+    return paws_3whs_zero_ts_not_supported(tns.peer_tracker, tns.tracker);
 }
 
-bool TcpNormalizerVista::is_paws_ts_checked_required(TcpSegmentDescriptor& tsd)
+bool TcpNormalizerVista::is_paws_ts_checked_required(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return paws_3whs_zero_ts_supported(peer_tracker, tracker, tsd);
+    return paws_3whs_zero_ts_supported(tns.peer_tracker, tns.tracker, tsd);
 }
 
-int TcpNormalizerVista::handle_repeated_syn(TcpSegmentDescriptor& tsd)
+int TcpNormalizerVista::handle_repeated_syn(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
-    return handle_repeated_syn_mswin(peer_tracker, tracker, tsd, session);
+    return handle_repeated_syn_mswin(tns.peer_tracker, tns.tracker, tsd, tns.session);
 }
 
-bool TcpNormalizerProxy::validate_rst(TcpSegmentDescriptor& tsd)
+bool TcpNormalizerProxy::validate_rst(
+    TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
 #ifndef DEBUG_MSGS
     UNUSED(tsd);
 #endif
 
     // FIXIT-L will session->flow ever be null? convert to assert if possible
-    if ( session->flow )
+    if ( tns.session->flow )
     {
         DebugFormat(DEBUG_STREAM_STATE,
             "Proxy Normalizer - Not Valid\n end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
-            tsd.get_end_seq(), tracker->r_win_base, tsd.get_seg_seq(), tracker->r_nxt_ack +
-            get_stream_window(tsd));
+            tsd.get_end_seq(), tns.tracker->r_win_base, tsd.get_seg_seq(), tns.tracker->r_nxt_ack +
+            get_stream_window(tns, tsd));
     }
 
     return false;
 }
 
-int TcpNormalizerProxy::handle_paws(TcpSegmentDescriptor&)
+int TcpNormalizerProxy::handle_paws(
+    TcpNormalizerState&, TcpSegmentDescriptor&)
 {
     return ACTION_NOTHING;
 }
 
-int TcpNormalizerProxy::handle_repeated_syn(TcpSegmentDescriptor&)
+int TcpNormalizerProxy::handle_repeated_syn(
+    TcpNormalizerState&, TcpSegmentDescriptor&)
 {
     return ACTION_NOTHING;
 }
 
-TcpNormalizer* TcpNormalizerFactory::create(TcpSession* session, StreamPolicy os_policy,
-    TcpStreamTracker* tracker, TcpStreamTracker* peer)
+void TcpNormalizerPolicy::init(StreamPolicy os, TcpStreamSession* ssn, TcpStreamTracker* trk, TcpStreamTracker* peer)
 {
-    TcpNormalizer* normalizer;
+    tns.os_policy = os;
+    tns.session = ssn;
+    tns.tracker = trk;
+    tns.peer_tracker = peer;
 
-    switch (os_policy)
-    {
-    case StreamPolicy::OS_FIRST:
-        normalizer = new TcpNormalizerFirst(session, tracker);
-        break;
-
-    case StreamPolicy::OS_LAST:
-        normalizer = new TcpNormalizerLast(session, tracker);
-        break;
-
-    case StreamPolicy::OS_LINUX:
-        normalizer = new TcpNormalizerLinux(session, tracker);
-        break;
-
-    case StreamPolicy::OS_OLD_LINUX:
-        normalizer = new TcpNormalizerOldLinux(session, tracker);
-        break;
-
-    case StreamPolicy::OS_BSD:
-        normalizer = new TcpNormalizerBSD(session, tracker);
-        break;
-
-    case StreamPolicy::OS_MACOS:
-        normalizer = new TcpNormalizerMacOS(session, tracker);
-        break;
-
-    case StreamPolicy::OS_SOLARIS:
-        normalizer = new TcpNormalizerSolaris(session, tracker);
-        break;
+    tns.paws_ts_fudge = 0;
+    tns.paws_drop_zero_ts = true;
+    tns.tcp_ts_flags = 0;
 
-    case StreamPolicy::OS_IRIX:
-        normalizer = new TcpNormalizerIrix(session, tracker);
-        break;
+    tns.tcp_ips_enabled = Normalize_IsEnabled(NORM_TCP_IPS);
+    tns.trim_syn = Normalize_GetMode(NORM_TCP_TRIM_SYN);
+    tns.trim_rst = Normalize_GetMode(NORM_TCP_TRIM_RST);
+    tns.trim_win = Normalize_GetMode(NORM_TCP_TRIM_WIN);
+    tns.trim_mss = Normalize_GetMode(NORM_TCP_TRIM_MSS);
+    tns.strip_ecn = Normalize_GetMode(NORM_TCP_ECN_STR);
+    tns.tcp_block = Normalize_GetMode(NORM_TCP_BLOCK);
+    tns.opt_block = Normalize_GetMode(NORM_TCP_OPT);
 
-    case StreamPolicy::OS_HPUX11:
-        normalizer = new TcpNormalizerHpux11(session, tracker);
-        break;
-
-    case StreamPolicy::OS_HPUX10:
-        normalizer = new TcpNormalizerHpux10(session, tracker);
-        break;
-
-    case StreamPolicy::OS_WINDOWS:
-        normalizer = new TcpNormalizerWindows(session, tracker);
-        break;
-
-    case StreamPolicy::OS_WINDOWS2K3:
-        normalizer = new TcpNormalizerWindows2K3(session, tracker);
-        break;
+    norm = TcpNormalizerFactory::create(os);
+    norm->init(tns);
+}
 
-    case StreamPolicy::OS_VISTA:
-        normalizer = new TcpNormalizerVista(session, tracker);
-        break;
+TcpNormalizer* TcpNormalizerFactory::create(StreamPolicy os_policy)
+{
+    static TcpNormalizerFirst first;
+    static TcpNormalizerLast last;
+    static TcpNormalizerLinux linux;
+    static TcpNormalizerOldLinux old_linux;
+    static TcpNormalizerBSD bsd;
+    static TcpNormalizerMacOS mac_os;
+    static TcpNormalizerSolaris solaris;
+    static TcpNormalizerIrix irix;
+    static TcpNormalizerHpux11 hpux11;
+    static TcpNormalizerHpux10 hpux10;
+    static TcpNormalizerWindows windows;
+    static TcpNormalizerWindows2K3 windows_2K3;
+    static TcpNormalizerVista vista;
+    static TcpNormalizerProxy proxy;
 
-    case StreamPolicy::OS_PROXY:
-        normalizer = new TcpNormalizerProxy(session, tracker);
-        break;
+    TcpNormalizer* normalizer;
 
-    default:
-        normalizer = new TcpNormalizerBSD(session, tracker);
-        break;
+    switch (os_policy)
+    {
+    case StreamPolicy::OS_FIRST: normalizer = &first; break;
+    case StreamPolicy::OS_LAST: normalizer = &last; break;
+    case StreamPolicy::OS_LINUX: normalizer = &linux; break;
+    case StreamPolicy::OS_OLD_LINUX: normalizer = &old_linux; break;
+    case StreamPolicy::OS_BSD: normalizer = &bsd; break;
+    case StreamPolicy::OS_MACOS: normalizer = &mac_os; break;
+    case StreamPolicy::OS_SOLARIS: normalizer = &solaris; break;
+    case StreamPolicy::OS_IRIX: normalizer = &irix; break;
+    case StreamPolicy::OS_HPUX11: normalizer = &hpux11; break;
+    case StreamPolicy::OS_HPUX10: normalizer = &hpux10; break;
+    case StreamPolicy::OS_WINDOWS: normalizer = &windows; break;
+    case StreamPolicy::OS_WINDOWS2K3: normalizer = &windows_2K3; break;
+    case StreamPolicy::OS_VISTA: normalizer = &vista; break;
+    case StreamPolicy::OS_PROXY: normalizer = &proxy; break;
+    default: normalizer = &bsd; break;
     }
 
-    normalizer->set_peer_tracker(peer);
     return normalizer;
 }
 
index 23c51849e52ef10080200a9efc17a9d568f090b4..025c478789df5921242381488f7db93b712de23b 100644 (file)
 
 #include "stream/tcp/tcp_normalizer.h"
 
+class TcpStreamSession;
+class TcpStreamSession;
+
 class TcpNormalizerFactory
 {
 public:
-    static TcpNormalizer* create(TcpSession*, StreamPolicy, TcpStreamTracker*, TcpStreamTracker*);
+    static TcpNormalizer* create(StreamPolicy);
+};
+
+class TcpNormalizerPolicy
+{
+public:
+    TcpNormalizerPolicy() = default;
+    ~TcpNormalizerPolicy() = default;
+
+    void init(StreamPolicy os, TcpStreamSession* ssn, TcpStreamTracker* trk, TcpStreamTracker* peer);
+    void reset()
+    { init(StreamPolicy::OS_INVALID, nullptr, nullptr, nullptr); }
+
+    bool packet_dropper(TcpSegmentDescriptor& tsd, NormFlags nflags)
+    { return norm->packet_dropper(tns, tsd, nflags); }
+
+    void trim_syn_payload(TcpSegmentDescriptor& tsd, uint32_t max = 0)
+    { norm->trim_syn_payload(tns, tsd, max); }
+
+    void trim_rst_payload(TcpSegmentDescriptor& tsd, uint32_t max = 0)
+    { norm->trim_rst_payload(tns, tsd, max); }
+
+    void trim_win_payload(TcpSegmentDescriptor& tsd, uint32_t max = 0)
+    { norm->trim_win_payload(tns, tsd, max); }
+
+    void trim_mss_payload(TcpSegmentDescriptor& tsd, uint32_t max = 0)
+    { norm->trim_mss_payload(tns, tsd, max); }
+
+    void ecn_tracker(const snort::tcp::TCPHdr* tcph, bool req3way)
+    { norm->ecn_tracker(tns, tcph, req3way); }
+
+    void ecn_stripper(snort::Packet* p)
+    { norm->ecn_stripper(tns, p); }
+
+    uint32_t get_stream_window(TcpSegmentDescriptor& tsd)
+    { return norm->get_stream_window(tns, tsd); }
+
+    uint32_t get_tcp_timestamp(TcpSegmentDescriptor& tsd, bool strip)
+    { return norm->get_tcp_timestamp(tns, tsd, strip); }
+
+    int handle_paws(TcpSegmentDescriptor& tsd)
+    { return norm->handle_paws(tns, tsd); }
+
+    bool validate_rst(TcpSegmentDescriptor& tsd)
+    { return norm->validate_rst(tns, tsd); }
+
+    int handle_repeated_syn(TcpSegmentDescriptor& tsd)
+    { return norm->handle_repeated_syn(tns, tsd); }
+
+    uint16_t set_urg_offset(const snort::tcp::TCPHdr* tcph, uint16_t dsize)
+    { return norm->set_urg_offset(tns, tcph, dsize); }
+
+    StreamPolicy get_os_policy() const
+    { return tns.os_policy; }
+
+    bool is_paws_drop_zero_ts() const
+    { return tns.paws_drop_zero_ts; }
+
+    int32_t get_paws_ts_fudge() const
+    { return tns.paws_ts_fudge; }
+
+    int8_t get_opt_block() const
+    { return tns.opt_block; }
+
+    int8_t get_strip_ecn() const
+    { return tns.strip_ecn; }
+
+    int8_t get_tcp_block() const
+    { return tns.tcp_block; }
+
+    int8_t get_trim_rst() const
+    { return tns.trim_rst; }
+
+    int8_t get_trim_syn() const
+    { return tns.trim_syn; }
+
+    int8_t get_trim_mss() const
+    { return tns.trim_mss; }
+
+    int8_t get_trim_win() const
+    { return tns.trim_win; }
+
+    bool is_tcp_ips_enabled() const
+    { return tns.tcp_ips_enabled; }
+
+    bool handling_timestamps() const
+    { return tns.tcp_ts_flags != TF_NONE; }
+
+    uint32_t get_timestamp_flags()
+    { return tns.tcp_ts_flags; }
+
+private:
+    TcpNormalizer* norm = nullptr;
+    TcpNormalizerState tns;
 };
 
 #endif
index e0458194261a5599e970fb3d69a77cb68bb784c5..fb819fd1f0cbf340e17c6be0080bab6de0590e0e 100644 (file)
 #include "log/log.h"
 #include "main/snort.h"
 #include "profiler/profiler.h"
-#include "detection/detection_engine.h"
 #include "protocols/packet_manager.h"
 #include "time/packet_time.h"
 
 #include "tcp_module.h"
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
+#include "tcp_session.h"
 
 using namespace snort;
 
-ReassemblyPolicy stream_reassembly_policy_map[] =
-{
-    ReassemblyPolicy::OS_INVALID,
-    ReassemblyPolicy::OS_FIRST,
-    ReassemblyPolicy::OS_LAST,
-    ReassemblyPolicy::OS_LINUX,
-    ReassemblyPolicy::OS_OLD_LINUX,
-    ReassemblyPolicy::OS_BSD,
-    ReassemblyPolicy::OS_MACOS,
-    ReassemblyPolicy::OS_SOLARIS,
-    ReassemblyPolicy::OS_IRIX,
-    ReassemblyPolicy::OS_HPUX11,
-    ReassemblyPolicy::OS_HPUX10,
-    ReassemblyPolicy::OS_WINDOWS,
-    ReassemblyPolicy::OS_WINDOWS2K3,
-    ReassemblyPolicy::OS_VISTA,
-    ReassemblyPolicy::OS_PROXY,
-    ReassemblyPolicy::OS_DEFAULT
-};
-
-void TcpReassembler::set_tcp_reassembly_policy(StreamPolicy os_policy)
-{
-    reassembly_policy = stream_reassembly_policy_map[ static_cast<int>( os_policy ) ];
-}
-
-void TcpReassembler::trace_segments()
+void TcpReassembler::trace_segments(TcpReassemblerState& trs)
 {
-    TcpSegmentNode* tsn = seglist.head;
-    uint32_t sx = tracker->r_win_base;
+    TcpSegmentNode* tsn = trs.sos.seglist.head;
+    uint32_t sx = trs.tracker->r_win_base;
     unsigned segs = 0, bytes = 0;
 
     while ( tsn )
@@ -84,28 +59,28 @@ void TcpReassembler::trace_segments()
         sx = tsn->seq + tsn->payload_size;
         tsn = tsn->next;
     }
-    assert(seg_count == segs);
-    assert(seg_bytes_logical == bytes);
+    assert(trs.sos.seg_count == segs);
+    assert(trs.sos.seg_bytes_logical == bytes);
 }
 
-bool TcpReassembler::is_segment_pending_flush()
+bool TcpReassembler::is_segment_pending_flush(TcpReassemblerState& trs)
 {
-    return ( get_pending_segment_count(1) > 0 );
+    return ( get_pending_segment_count(trs, 1) > 0 );
 }
 
-uint32_t TcpReassembler::get_pending_segment_count(unsigned max)
+uint32_t TcpReassembler::get_pending_segment_count(TcpReassemblerState& trs, unsigned max)
 {
-    uint32_t n = seg_count - flush_count;
+    uint32_t n = trs.sos.seg_count - trs.flush_count;
     TcpSegmentNode* tsn;
 
     if ( !n || max == 1 )
         return n;
 
     n = 0;
-    tsn = seglist.head;
+    tsn = trs.sos.seglist.head;
     while ( tsn )
     {
-        if ( !tsn->buffered && SEQ_LT(tsn->seq, tracker->r_win_base) )
+        if ( !tsn->buffered && SEQ_LT(tsn->seq, trs.tracker->r_win_base) )
             n++;
 
         if ( max && n == max )
@@ -117,20 +92,21 @@ uint32_t TcpReassembler::get_pending_segment_count(unsigned max)
     return n;
 }
 
-bool TcpReassembler::flush_data_ready()
+bool TcpReassembler::flush_data_ready(TcpReassemblerState& trs)
 {
     // needed by stream_reassemble:action disable; can fire on rebuilt
     // packets, yanking the splitter out from under us :(
-    if (!tracker->flush_policy or !tracker->splitter)
+    if (!trs.tracker->flush_policy or !trs.tracker->splitter)
         return false;
 
-    if (tracker->flush_policy == STREAM_FLPOLICY_ON_DATA || tracker->splitter->is_paf())
-        return ( is_segment_pending_flush( ) );
+    if ( (trs.tracker->flush_policy == STREAM_FLPOLICY_ON_DATA) or
+        trs.tracker->splitter->is_paf() )
+        return ( is_segment_pending_flush(trs) );
 
-    return ( get_pending_segment_count(2) > 1 );  // FIXIT-L return false?
+    return ( get_pending_segment_count(trs, 2) > 1 );  // FIXIT-L return false?
 }
 
-int TcpReassembler::delete_reassembly_segment(TcpSegmentNode* tsn)
+int TcpReassembler::delete_reassembly_segment(TcpReassemblerState& trs, TcpSegmentNode* tsn)
 {
     int ret;
     assert(tsn);
@@ -141,36 +117,37 @@ int TcpReassembler::delete_reassembly_segment(TcpSegmentNode* tsn)
     if (tsn->prev)
         tsn->prev->next = tsn->next;
     else
-        seglist.head = tsn->next;
+        trs.sos.seglist.head = tsn->next;
 
     if (tsn->next)
         tsn->next->prev = tsn->prev;
     else
-        seglist.tail = tsn->prev;
+        trs.sos.seglist.tail = tsn->prev;
 
-    seg_bytes_logical -= tsn->payload_size;
-    seg_bytes_total -= tsn->orig_dsize;
+    trs.sos.seg_bytes_logical -= tsn->payload_size;
+    trs.sos.seg_bytes_total -= tsn->orig_dsize;
 
     ret = tsn->orig_dsize;
 
     if (tsn->buffered)
     {
         tcpStats.segs_used++;
-        flush_count--;
+        trs.flush_count--;
     }
 
-    if (seglist.next == tsn)
-        seglist.next = nullptr;
+    if (trs.sos.seglist.next == tsn)
+        trs.sos.seglist.next = nullptr;
 
     tsn->term( );
-    seg_count--;
+    trs.sos.seg_count--;
 
     return ret;
 }
 
-int TcpReassembler::trim_delete_reassembly_segment(TcpSegmentNode* tsn, uint32_t flush_seq)
+int TcpReassembler::trim_delete_reassembly_segment(
+    TcpReassemblerState& trs, TcpSegmentNode* tsn, uint32_t flush_seq)
 {
-    if ( paf_active(&tracker->paf_state) && ( ( tsn->seq + tsn->payload_size ) > flush_seq ) )
+    if ( paf_active(&trs.tracker->paf_state) && ( ( tsn->seq + tsn->payload_size ) > flush_seq ) )
     {
         uint32_t delta = flush_seq - tsn->seq;
 
@@ -181,27 +158,29 @@ int TcpReassembler::trim_delete_reassembly_segment(TcpSegmentNode* tsn, uint32_t
 
             tsn->seq = flush_seq;
             tsn->payload_size -= (uint16_t)delta;
-            seg_bytes_logical -= delta;
+            trs.sos.seg_bytes_logical -= delta;
             return 0;
         }
     }
 
-    return delete_reassembly_segment(tsn);
+    return delete_reassembly_segment(trs, tsn);
 }
 
-void TcpReassembler::queue_reassembly_segment(TcpSegmentNode* prev, TcpSegmentNode* tsn)
+void TcpReassembler::queue_reassembly_segment(
+    TcpReassemblerState& trs, TcpSegmentNode* prev, TcpSegmentNode* tsn)
 {
-    seglist.insert(prev, tsn);
-    seg_count++;
-    seg_bytes_total += tsn->orig_dsize;
-    total_segs_queued++;
+    trs.sos.seglist.insert(prev, tsn);
+    trs.sos.seg_count++;
+    trs.sos.seg_bytes_total += tsn->orig_dsize;
+    trs.sos.total_segs_queued++;
     tcpStats.segs_queued++;
 }
 
-bool TcpReassembler::is_segment_fasttrack(TcpSegmentNode* tail, TcpSegmentDescriptor& tsd)
+bool TcpReassembler::is_segment_fasttrack(
+    TcpReassemblerState&, TcpSegmentNode* tail, TcpSegmentDescriptor& tsd)
 {
-    DebugFormat(DEBUG_STREAM_STATE,  "Checking seq for fast track: %X > %X\n", tsd.get_seg_seq(),
-        tail->seq + tail->payload_size);
+    DebugFormat(DEBUG_STREAM_STATE,  "Checking seq for fast track: %X > %X\n",
+        tsd.get_seg_seq(), tail->seq + tail->payload_size);
 
     if ( SEQ_EQ(tsd.get_seg_seq(), tail->seq + tail->payload_size) )
         return true;
@@ -209,9 +188,9 @@ bool TcpReassembler::is_segment_fasttrack(TcpSegmentNode* tail, TcpSegmentDescri
     return false;
 }
 
-int TcpReassembler::add_reassembly_segment(TcpSegmentDescriptor& tsd, int16_t len, uint32_t slide,
-    uint32_t trunc_len,
-    uint32_t seq, TcpSegmentNode* left)
+int TcpReassembler::add_reassembly_segment(
+    TcpReassemblerState& trs, TcpSegmentDescriptor& tsd, int16_t len, uint32_t slide,
+    uint32_t trunc_len, uint32_t seq, TcpSegmentNode* left)
 {
     TcpSegmentNode* tsn = nullptr;
     int32_t newSize = len - slide - trunc_len;
@@ -226,7 +205,7 @@ int TcpReassembler::add_reassembly_segment(TcpSegmentDescriptor& tsd, int16_t le
             "(len: %hd slide: %u trunc: %u)\n", len, slide, trunc_len);
 
         inc_tcp_discards();
-        tracker->normalizer->trim_win_payload(tsd);
+        trs.tracker->normalizer.trim_win_payload(tsd);
 
         return STREAM_INSERT_OK;
     }
@@ -241,23 +220,27 @@ int TcpReassembler::add_reassembly_segment(TcpSegmentDescriptor& tsd, int16_t le
     // FIXIT-M the urgent ptr handling is broken... urg_offset is set here but currently
     // not actually referenced anywhere else.  In 2.9.7 the FlushStream function did reference
     // this field but that code has been lost... urg ptr handling needs to be reviewed and fixed
-    tsn->urg_offset = tracker->normalizer->set_urg_offset(tsd.get_tcph(), tsd.get_seg_len() );
-    queue_reassembly_segment(left, tsn);
-    seg_bytes_logical += tsn->payload_size;
-    total_bytes_queued += tsn->payload_size;
+    tsn->urg_offset = trs.tracker->normalizer.set_urg_offset(tsd.get_tcph(), tsd.get_seg_len() );
+
+    queue_reassembly_segment(trs, left, tsn);
+
+    trs.sos.seg_bytes_logical += tsn->payload_size;
+    trs.sos.total_bytes_queued += tsn->payload_size;
     tsd.get_pkt()->packet_flags |= PKT_STREAM_INSERT;
 
     DebugFormat(DEBUG_STREAM_STATE,
         "added %hu bytes on segment list @ seq: 0x%X, total %u, %u segments queued\n",
-        tsn->payload_size, tsn->seq, seg_bytes_logical, get_pending_segment_count(0));
+        tsn->payload_size, tsn->seq, trs.sos.seg_bytes_logical,
+        get_pending_segment_count(trs, 0));
 
 #ifdef SEG_TEST
-    CheckSegments(tracker);
+    CheckSegments(trs.tracker);
 #endif
     return STREAM_INSERT_OK;
 }
 
-int TcpReassembler::dup_reassembly_segment(TcpSegmentNode* left, TcpSegmentNode** retSeg)
+int TcpReassembler::dup_reassembly_segment(
+    TcpReassemblerState& trs, TcpSegmentNode* left, TcpSegmentNode** retSeg)
 {
     TcpSegmentNode* tsn = TcpSegmentNode::init(*left);
     tcpStats.segs_split++;
@@ -266,32 +249,33 @@ int TcpReassembler::dup_reassembly_segment(TcpSegmentNode* left, TcpSegmentNode*
     tsn->payload_size = left->payload_size;
     tsn->seq = left->seq;
 
-    queue_reassembly_segment(left, tsn);
+    queue_reassembly_segment(trs, left, tsn);
 
     DebugFormat(DEBUG_STREAM_STATE,
         "added %hu bytes on segment list @ seq: 0x%X, total %u, %u segments queued\n",
-        tsn->payload_size, tsn->seq, seg_bytes_logical, get_pending_segment_count(0));
+        tsn->payload_size, tsn->seq, trs.sos.seg_bytes_logical,
+        get_pending_segment_count(trs, 0));
 
     *retSeg = tsn;
     return STREAM_INSERT_OK;
 }
 
-int TcpReassembler::purge_alerts(Flow* flow)
+int TcpReassembler::purge_alerts(TcpReassemblerState& trs, Flow* flow)
 {
-    for (int i = 0; i < tracker->alert_count; i++)
+    for (int i = 0; i < trs.tracker->alert_count; i++)
     {
-        StreamAlertInfo* ai = tracker->alerts + i;
-        Stream::log_extra_data(flow, xtradata_mask, ai->event_id, ai->event_second);
+        StreamAlertInfo* ai = trs.tracker->alerts + i;
+        Stream::log_extra_data(flow, trs.xtradata_mask, ai->event_id, ai->event_second);
     }
-    tracker->alert_count = 0;
+    trs.tracker->alert_count = 0;
 
     return 0;
 }
 
-int TcpReassembler::purge_to_seq(uint32_t flush_seq)
+int TcpReassembler::purge_to_seq(TcpReassemblerState& trs, uint32_t flush_seq)
 {
-    assert(seglist.head != nullptr);
-    TcpSegmentNode* tsn = seglist.head;
+    assert(trs.sos.seglist.head != nullptr);
+    TcpSegmentNode* tsn = trs.sos.seglist.head;
     TcpSegmentNode* dump_me = nullptr;
     int purged_bytes = 0;
     uint32_t last_ts = 0;
@@ -310,26 +294,26 @@ int TcpReassembler::purge_to_seq(uint32_t flush_seq)
             if (dump_me->ts > last_ts)
                 last_ts = dump_me->ts;
 
-            purged_bytes += trim_delete_reassembly_segment(dump_me, flush_seq);
+            purged_bytes += trim_delete_reassembly_segment(trs, dump_me, flush_seq);
         }
         else
             break;
     }
 
-    if ( SEQ_LT(seglist_base_seq, flush_seq) )
+    if ( SEQ_LT(trs.sos.seglist_base_seq, flush_seq) )
     {
         // FIXIT-M these lines are out of code coverage. Is this even possible?
         DebugFormat(DEBUG_STREAM_STATE, "setting seglist_base_seq to 0x%X\n", flush_seq);
-        seglist_base_seq = flush_seq;
+        trs.sos.seglist_base_seq = flush_seq;
     }
 
-    if ( SEQ_LT(tracker->r_nxt_ack, flush_seq) )
-        tracker->r_nxt_ack = flush_seq;
+    if ( SEQ_LT(trs.tracker->r_nxt_ack, flush_seq) )
+        trs.tracker->r_nxt_ack = flush_seq;
 
-    purge_alerts(session->flow);
+    purge_alerts(trs, trs.sos.session->flow);
 
-    if ( seglist.head == nullptr )
-        seglist.tail = nullptr;
+    if ( trs.sos.seglist.head == nullptr )
+        trs.sos.seglist.tail = nullptr;
 
     /* Update the "last" time stamp seen from the other side
      * to be the most recent timestamp (largest) that was removed
@@ -349,17 +333,17 @@ int TcpReassembler::purge_to_seq(uint32_t flush_seq)
     if ( !last_ts )
         return purged_bytes;
 
-    if ( !server_side )
+    if ( !trs.server_side )
     {
-        int32_t delta = last_ts - session->server->get_ts_last();
+        int32_t delta = last_ts - trs.sos.session->server.get_ts_last();
         if ( delta > 0 )
-            session->server->set_ts_last(last_ts);
+            trs.sos.session->server.set_ts_last(last_ts);
     }
     else
     {
-        int32_t delta = last_ts - session->client->get_ts_last();
+        int32_t delta = last_ts - trs.sos.session->client.get_ts_last();
         if ( delta > 0 )
-            session->client->set_ts_last(last_ts);
+            trs.sos.session->client.set_ts_last(last_ts);
     }
 
     return purged_bytes;
@@ -371,44 +355,45 @@ int TcpReassembler::purge_to_seq(uint32_t flush_seq)
 // part of a segment
 // * FIXIT-L need flag to mark any reassembled packets that have a gap
 //   (if we reassemble such)
-int TcpReassembler::purge_flushed_ackd()
+int TcpReassembler::purge_flushed_ackd(TcpReassemblerState& trs)
 {
-    TcpSegmentNode* tsn = seglist.head;
+    TcpSegmentNode* tsn = trs.sos.seglist.head;
     uint32_t seq;
 
-    if (!seglist.head)
+    if (!trs.sos.seglist.head)
         return 0;
 
-    seq = seglist.head->seq;
+    seq = trs.sos.seglist.head->seq;
 
     while ( tsn && tsn->buffered )
     {
         uint32_t end = tsn->seq + tsn->payload_size;
 
-        if ( SEQ_GT(end, tracker->r_win_base) )
+        if ( SEQ_GT(end, trs.tracker->r_win_base) )
         {
-            seq = tracker->r_win_base;
+            seq = trs.tracker->r_win_base;
             break;
         }
         seq = end;
         tsn = tsn->next;
     }
-    if ( seq != seglist.head->seq )
-        return purge_to_seq(seq);
+    if ( seq != trs.sos.seglist.head->seq )
+        return purge_to_seq(trs, seq);
 
     return 0;
 }
 
-void TcpReassembler::show_rebuilt_packet(Packet* pkt)
+void TcpReassembler::show_rebuilt_packet(TcpReassemblerState& trs, Packet* pkt)
 {
-    if ( session->config->flags & STREAM_CONFIG_SHOW_PACKETS )
+    if ( trs.sos.session->config->flags & STREAM_CONFIG_SHOW_PACKETS )
     {
         LogFlow(pkt);
         LogNetData(pkt->data, pkt->dsize, pkt);
     }
 }
 
-uint32_t TcpReassembler::get_flush_data_len(TcpSegmentNode* tsn, uint32_t to_seq, unsigned max)
+uint32_t TcpReassembler::get_flush_data_len(
+    TcpReassemblerState& trs, TcpSegmentNode* tsn, uint32_t to_seq, unsigned max)
 {
     unsigned int flushSize = tsn->payload_size;
 
@@ -416,29 +401,31 @@ uint32_t TcpReassembler::get_flush_data_len(TcpSegmentNode* tsn, uint32_t to_seq
         flushSize = max;
 
     // copy only to flush point
-    if ( paf_active(&tracker->paf_state) && SEQ_GT(tsn->seq + flushSize, to_seq) )
+    if ( paf_active(&trs.tracker->paf_state) && SEQ_GT(tsn->seq + flushSize, to_seq) )
         flushSize = to_seq - tsn->seq;
 
     return flushSize;
 }
 
-// flush the client seglist up to the most recently acked segment
-int TcpReassembler::flush_data_segments(Packet* p, uint32_t total, Packet* pdu)
+// flush the client trs.sos.seglist up to the most recently acked segment
+int TcpReassembler::flush_data_segments(
+    TcpReassemblerState& trs, Packet* p, uint32_t total, Packet* pdu)
 {
     uint32_t bytes_flushed = 0;
     uint32_t segs = 0;
     uint32_t flags = PKT_PDU_HEAD;
-    DEBUG_WRAP(uint32_t bytes_queued = seg_bytes_logical; );
+    DEBUG_WRAP(uint32_t bytes_queued = trs.sos.seg_bytes_logical; );
 
-    assert(seglist.next);
+    assert(trs.sos.seglist.next);
     Profile profile(s5TcpBuildPacketPerfStats);
 
-    uint32_t to_seq = seglist.next->seq + total;
+    uint32_t to_seq = trs.sos.seglist.next->seq + total;
 
-    while ( SEQ_LT(seglist.next->seq, to_seq) )
+    while ( SEQ_LT(trs.sos.seglist.next->seq, to_seq) )
     {
-        TcpSegmentNode* tsn = seglist.next, * sr = nullptr;
-        unsigned bytes_to_copy = get_flush_data_len(tsn, to_seq, tracker->splitter->max(p->flow));
+        TcpSegmentNode* tsn = trs.sos.seglist.next, * sr = nullptr;
+        unsigned bytes_to_copy = get_flush_data_len(
+            trs, tsn, to_seq, trs.tracker->splitter->max(p->flow));
         unsigned bytes_copied = 0;
         assert(bytes_to_copy);
 
@@ -447,12 +434,12 @@ int TcpReassembler::flush_data_segments(Packet* p, uint32_t total, Packet* pdu)
         if ( !tsn->next or (bytes_to_copy < tsn->payload_size) or
             SEQ_EQ(tsn->seq +  bytes_to_copy, to_seq) or
             (bytes_flushed + tsn->payload_size + tsn->next->payload_size >
-                tracker->splitter->get_max_pdu()) )
+                trs.tracker->splitter->get_max_pdu()) )
         {
             flags |= PKT_PDU_TAIL;
         }
-        const StreamBuffer sb = tracker->splitter->reassemble(
-            session->flow, total, bytes_flushed, tsn->payload(),
+        const StreamBuffer sb = trs.tracker->splitter->reassemble(
+            trs.sos.session->flow, total, bytes_flushed, tsn->payload(),
             bytes_to_copy, flags, bytes_copied);
 
         flags = 0;
@@ -469,7 +456,7 @@ int TcpReassembler::flush_data_segments(Packet* p, uint32_t total, Packet* pdu)
         bytes_flushed += bytes_to_copy;
 
         if ( bytes_to_copy < tsn->payload_size
-            && dup_reassembly_segment(tsn, &sr) == STREAM_INSERT_OK )
+            && dup_reassembly_segment(trs, tsn, &sr) == STREAM_INSERT_OK )
         {
             tsn->payload_size = bytes_to_copy;
             sr->seq += bytes_to_copy;
@@ -477,10 +464,10 @@ int TcpReassembler::flush_data_segments(Packet* p, uint32_t total, Packet* pdu)
             sr->offset += bytes_to_copy;
         }
         tsn->buffered = true;
-        flush_count++;
+        trs.flush_count++;
         segs++;
 
-        seglist.next = tsn->next;
+        trs.sos.seglist.next = tsn->next;
 
         if ( SEQ_EQ(tsn->seq + bytes_to_copy, to_seq) )
             break;
@@ -493,16 +480,19 @@ int TcpReassembler::flush_data_segments(Packet* p, uint32_t total, Packet* pdu)
             || (!tsn->next && (tsn->seq + tsn->payload_size < to_seq))))
         {
             // FIXIT-L this is suboptimal - better to exclude fin from to_seq
-            if ( !tracker->is_fin_seq_set() or SEQ_LEQ(to_seq, tracker->get_fin_final_seq()) )
-                tracker->set_tf_flags(TF_MISSING_PKT);
-
+            if ( !trs.tracker->is_fin_seq_set() or
+                SEQ_LEQ(to_seq, trs.tracker->get_fin_final_seq()) )
+            {
+                trs.tracker->set_tf_flags(TF_MISSING_PKT);
+            }
             break;
         }
 
-        if ( sb.data || !seglist.next )
+        if ( sb.data || !trs.sos.seglist.next )
             break;
 
-        if ( bytes_flushed + seglist.next->payload_size > tracker->splitter->get_max_pdu() )
+        if ( bytes_flushed + trs.sos.seglist.next->payload_size >
+            trs.tracker->splitter->get_max_pdu() )
             break;
     }
 
@@ -515,7 +505,8 @@ int TcpReassembler::flush_data_segments(Packet* p, uint32_t total, Packet* pdu)
 }
 
 // FIXIT-L consolidate encode format, update, and this into new function?
-void TcpReassembler::prep_pdu(Flow* flow, Packet* p, uint32_t pkt_flags, Packet* pdu)
+void TcpReassembler::prep_pdu(
+    TcpReassemblerState&, Flow* flow, Packet* p, uint32_t pkt_flags, Packet* pdu)
 {
     pdu->ptrs.set_pkt_type(PktType::PDU);
     pdu->proto_bits |= PROTO_BIT__TCP;
@@ -565,27 +556,29 @@ void TcpReassembler::prep_pdu(Flow* flow, Packet* p, uint32_t pkt_flags, Packet*
     }
 }
 
-Packet* TcpReassembler::initialize_pdu(Packet* p, uint32_t pkt_flags, struct timeval tv)
+Packet* TcpReassembler::initialize_pdu(
+    TcpReassemblerState& trs, Packet* p, uint32_t pkt_flags, struct timeval tv)
 {
-    DetectionEngine::onload(session->flow);
+    DetectionEngine::onload(trs.sos.session->flow);
     Packet* pdu = DetectionEngine::set_next_packet();
 
     EncodeFlags enc_flags = 0;
     DAQ_PktHdr_t pkth;
-    session->GetPacketHeaderFoo(&pkth, pkt_flags);
+    trs.sos.session->GetPacketHeaderFoo(&pkth, pkt_flags);
     PacketManager::format_tcp(enc_flags, p, pdu, PSEUDO_PKT_TCP, &pkth, pkth.opaque);
-    prep_pdu(session->flow, p, pkt_flags, pdu);
+    prep_pdu(trs, trs.sos.session->flow, p, pkt_flags, pdu);
     (const_cast<DAQ_PktHdr_t*>(pdu->pkth))->ts = tv;
     pdu->dsize = 0;
     pdu->data = nullptr;
     return pdu;
 }
 
-int TcpReassembler::_flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
+int TcpReassembler::_flush_to_seq(
+    TcpReassemblerState& trs, uint32_t bytes, Packet* p, uint32_t pkt_flags)
 {
     Profile profile(s5TcpFlushPerfStats);
 
-    DetectionEngine::onload(session->flow);
+    DetectionEngine::onload(trs.sos.session->flow);
     Packet* pdu = DetectionEngine::set_next_packet();
 
     if ( !p )
@@ -599,12 +592,12 @@ int TcpReassembler::_flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
     DebugFormat(DEBUG_STREAM_STATE, "Attempting to flush %u bytes\n", bytes);
 
     uint32_t bytes_processed = 0;
-    uint32_t stop_seq = seglist.next->seq + bytes;
+    uint32_t stop_seq = trs.sos.seglist.next->seq + bytes;
 
-    while ( seglist.next and SEQ_LT(seglist.next->seq, stop_seq) )
+    while ( trs.sos.seglist.next and SEQ_LT(trs.sos.seglist.next->seq, stop_seq) )
     {
-        seglist_base_seq = seglist.next->seq;
-        uint32_t footprint = stop_seq - seglist_base_seq;
+        trs.sos.seglist_base_seq = trs.sos.seglist.next->seq;
+        uint32_t footprint = stop_seq - trs.sos.seglist_base_seq;
 
         if ( footprint == 0 )
             return bytes_processed;
@@ -613,16 +606,17 @@ int TcpReassembler::_flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
             /* this is as much as we can pack into a stream buffer */
             footprint = pdu->max_dsize;
 
-        if ( tracker->splitter->is_paf() and ( tracker->get_tf_flags() & TF_MISSING_PREV_PKT ) )
-            fallback();
+        if ( trs.tracker->splitter->is_paf() and
+            ( trs.tracker->get_tf_flags() & TF_MISSING_PREV_PKT ) )
+            fallback(trs);
 
-        Packet* pdu = initialize_pdu(p, pkt_flags, seglist.next->tv);
-        int32_t flushed_bytes = flush_data_segments(p, footprint, pdu);
+        Packet* pdu = initialize_pdu(trs, p, pkt_flags, trs.sos.seglist.next->tv);
+        int32_t flushed_bytes = flush_data_segments(trs, p, footprint, pdu);
         if ( flushed_bytes == 0 )
             break; /* No more data... bail */
 
         bytes_processed += flushed_bytes;
-        seglist_base_seq += flushed_bytes;
+        trs.sos.seglist_base_seq += flushed_bytes;
 
         if ( pdu->dsize )
         {
@@ -632,7 +626,7 @@ int TcpReassembler::_flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
                 pdu->packet_flags |= ( PKT_REBUILT_STREAM | PKT_STREAM_EST );
 
             pdu->set_snort_protocol_id(p->get_snort_protocol_id());
-            show_rebuilt_packet(pdu);
+            show_rebuilt_packet(trs, pdu);
             tcpStats.rebuilt_packets++;
             tcpStats.rebuilt_bytes += flushed_bytes;
 
@@ -644,24 +638,25 @@ int TcpReassembler::_flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
             tcpStats.rebuilt_buffers++; // FIXIT-L this is not accurate
         }
 
-        DebugFormat(DEBUG_STREAM_STATE, "setting seglist_base_seq to 0x%X\n", seglist_base_seq);
+        DebugFormat(DEBUG_STREAM_STATE, "setting trs.sos.seglist_base_seq to 0x%X\n",
+            trs.sos.seglist_base_seq);
 
-        // FIXIT-L must check because above may clear session
-        if ( tracker->splitter )
-            tracker->splitter->update();
+        // FIXIT-L must check because above may clear trs.sos.session
+        if ( trs.tracker->splitter )
+            trs.tracker->splitter->update();
 
         // FIXIT-L abort should be by PAF callback only since recovery may be possible
-        if ( tracker->get_tf_flags() & TF_MISSING_PKT )
+        if ( trs.tracker->get_tf_flags() & TF_MISSING_PKT )
         {
-            tracker->set_tf_flags(TF_MISSING_PREV_PKT | TF_PKT_MISSED);
-            tracker->clear_tf_flags(TF_MISSING_PKT);
+            trs.tracker->set_tf_flags(TF_MISSING_PREV_PKT | TF_PKT_MISSED);
+            trs.tracker->clear_tf_flags(TF_MISSING_PKT);
             tcpStats.gaps++;
         }
         else
-            tracker->clear_tf_flags(TF_MISSING_PREV_PKT);
+            trs.tracker->clear_tf_flags(TF_MISSING_PREV_PKT);
 
         // check here instead of in while to allow single segment flushes
-        if ( !flush_data_ready() )
+        if ( !flush_data_ready(trs) )
             break;
     }
 
@@ -669,89 +664,92 @@ int TcpReassembler::_flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
 }
 
 // flush a seglist up to the given point, generate a pseudopacket, and fire it thru the system.
-int TcpReassembler::flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
+int TcpReassembler::flush_to_seq(
+    TcpReassemblerState& trs, uint32_t bytes, Packet* p, uint32_t pkt_flags)
 {
-    if ( !bytes || !seglist.next )
+    if ( !bytes || !trs.sos.seglist.next )
     {
-        DebugFormat(DEBUG_STREAM_STATE, "bailing: no bytes: %u or empty seglist: %p\n",
-            bytes, (void*)seglist.next);
+        DebugFormat(DEBUG_STREAM_STATE, "bailing: no bytes: %u or empty trs.sos.seglist: %p\n",
+            bytes, (void*)trs.sos.seglist.next);
         return 0;
     }
 
-    if ( !flush_data_ready() and !(tracker->get_tf_flags() & TF_FORCE_FLUSH) and
-        !tracker->splitter->is_paf() )
+    if ( !flush_data_ready(trs) and !(trs.tracker->get_tf_flags() & TF_FORCE_FLUSH) and
+        !trs.tracker->splitter->is_paf() )
     {
-        DebugMessage(DEBUG_STREAM_STATE, "only 1 packet in seglist no need to flush\n");
+        DebugMessage(DEBUG_STREAM_STATE, "only 1 packet in trs.sos.seglist no need to flush\n");
         return 0;
     }
 
-    tracker->clear_tf_flags(TF_MISSING_PKT | TF_MISSING_PREV_PKT);
+    trs.tracker->clear_tf_flags(TF_MISSING_PKT | TF_MISSING_PREV_PKT);
 
     /* This will set this flag on the first reassembly
      * if reassembly for this direction was set midstream */
-    if ( SEQ_LT(seglist_base_seq, seglist.next->seq) )
+    if ( SEQ_LT(trs.sos.seglist_base_seq, trs.sos.seglist.next->seq) )
     {
-        uint32_t missed = seglist.next->seq - seglist_base_seq;
+        uint32_t missed = trs.sos.seglist.next->seq - trs.sos.seglist_base_seq;
 
         if ( missed <= bytes )
             bytes -= missed;
 
-        tracker->set_tf_flags(TF_MISSING_PREV_PKT | TF_PKT_MISSED);
+        trs.tracker->set_tf_flags(TF_MISSING_PREV_PKT | TF_PKT_MISSED);
 
         tcpStats.gaps++;
-        seglist_base_seq = seglist.next->seq;
+        trs.sos.seglist_base_seq = trs.sos.seglist.next->seq;
 
         if ( !bytes )
             return 0;
     }
 
-    return _flush_to_seq(bytes, p, pkt_flags);
+    return _flush_to_seq(trs, bytes, p, pkt_flags);
 }
 
 // flush a seglist up to the given point, generate a pseudopacket, and fire it thru the system.
-int TcpReassembler::do_zero_byte_flush(Packet* p, uint32_t pkt_flags)
+int TcpReassembler::do_zero_byte_flush(TcpReassemblerState& trs, Packet* p, uint32_t pkt_flags)
 {
     unsigned bytes_copied = 0;
 
-    const StreamBuffer sb = tracker->splitter->reassemble(session->flow, 0, 0, nullptr, 0,
-        (PKT_PDU_HEAD | PKT_PDU_TAIL), bytes_copied);
+    const StreamBuffer sb = trs.tracker->splitter->reassemble(
+        trs.sos.session->flow, 0, 0, nullptr, 0, (PKT_PDU_HEAD | PKT_PDU_TAIL), bytes_copied);
 
      if ( sb.data )
      {
-        Packet* pdu = initialize_pdu(p, pkt_flags, p->pkth->ts);
+        Packet* pdu = initialize_pdu(trs, p, pkt_flags, p->pkth->ts);
         /* setup the pseudopacket payload */
         pdu->data = sb.data;
         pdu->dsize = sb.length;
-        pdu->packet_flags |= ( PKT_REBUILT_STREAM | PKT_STREAM_EST | PKT_PDU_HEAD | PKT_PDU_TAIL );
+        pdu->packet_flags |= (PKT_REBUILT_STREAM | PKT_STREAM_EST | PKT_PDU_HEAD | PKT_PDU_TAIL);
         pdu->set_snort_protocol_id(p->get_snort_protocol_id());
-        flush_count++;
+        trs.flush_count++;
 
-        show_rebuilt_packet(pdu);
+        show_rebuilt_packet(trs, pdu);
         ProfileExclude profile_exclude(s5TcpFlushPerfStats);
         Snort::inspect(pdu);
-        if ( tracker->splitter )
-            tracker->splitter->update();
+
+        if ( trs.tracker->splitter )
+            trs.tracker->splitter->update();
      }
 
      return bytes_copied;
 }
 
-// get the footprint for the current seglist, the difference
+// get the footprint for the current trs.sos.seglist, the difference
 // between our base sequence and the last ack'd sequence we received
 
-uint32_t TcpReassembler::get_q_footprint()
+uint32_t TcpReassembler::get_q_footprint(TcpReassemblerState& trs)
 {
     int32_t footprint = 0, sequenced = 0;
 
-    if ( !tracker )
+    if ( !trs.tracker )
         return 0;
 
-    seglist.next = seglist.head;
-    footprint = tracker->r_win_base - seglist_base_seq;
-    if( footprint )
+    trs.sos.seglist.next = trs.sos.seglist.head;
+    footprint = trs.tracker->r_win_base - trs.sos.seglist_base_seq;
+
+    if ( footprint )
     {
-        sequenced = get_q_sequenced();
-        iftracker->fin_seq_status == TcpStreamTracker::FIN_WITH_SEQ_ACKED )
+        sequenced = get_q_sequenced(trs);
+        if ( trs.tracker->fin_seq_status == TcpStreamTracker::FIN_WITH_SEQ_ACKED )
             --footprint;
     }
 
@@ -759,15 +757,16 @@ uint32_t TcpReassembler::get_q_footprint()
 }
 
 // FIXIT-P get_q_sequenced() performance could possibly be
-// boosted by tracking sequenced bytes as seglist is updated
+// boosted by tracking sequenced bytes as trs.sos.seglist is updated
 // to avoid the while loop, etc. below.
 
-uint32_t TcpReassembler::get_q_sequenced()
+uint32_t TcpReassembler::get_q_sequenced(TcpReassemblerState& trs)
 {
-    TcpSegmentNode* tsn = tracker ? seglist.head : nullptr;
+    TcpSegmentNode* tsn = trs.tracker ? trs.sos.seglist.head : nullptr;
     TcpSegmentNode* base = nullptr;
 
-    if ( !tsn || ( session->flow->two_way_traffic() && SEQ_LT(tracker->r_win_base, tsn->seq) ) )
+    if ( !tsn || ( trs.sos.session->flow->two_way_traffic() &&
+        SEQ_LT(trs.tracker->r_win_base, tsn->seq) ) )
         return 0;
 
     while ( tsn->next && ( tsn->next->seq == tsn->seq + tsn->payload_size ) )
@@ -781,10 +780,11 @@ uint32_t TcpReassembler::get_q_sequenced()
         base = tsn;
 
     int32_t len = 0;
+
     if ( base )
     {
-        seglist.next = base;
-        seglist_base_seq = base->seq;
+        trs.sos.seglist.next = base;
+        trs.sos.seglist_base_seq = base->seq;
         len = tsn->seq + tsn->payload_size - base->seq;
     }
 
@@ -794,35 +794,43 @@ uint32_t TcpReassembler::get_q_sequenced()
 // FIXIT-L flush_stream() calls should be replaced with calls to
 // CheckFlushPolicyOn*() with the exception that for the *OnAck() case,
 // any available ackd data must be flushed in both directions.
-int TcpReassembler::flush_stream(Packet* p, uint32_t dir, bool final_flush)
+int TcpReassembler::flush_stream(
+    TcpReassemblerState& trs, Packet* p, uint32_t dir, bool final_flush)
 {
     // this is not always redundant; stream_reassemble rule option causes trouble
-    if ( !tracker->flush_policy or !tracker->splitter )
+    if ( !trs.tracker->flush_policy or !trs.tracker->splitter )
         return 0;
 
     uint32_t bytes;
 
-    if ( tracker->normalizer->is_tcp_ips_enabled() )
-        bytes = get_q_sequenced( );
+    if ( trs.tracker->normalizer.is_tcp_ips_enabled() )
+        bytes = get_q_sequenced(trs);
     else
-        bytes = get_q_footprint( );
+        bytes = get_q_footprint(trs);
 
     if ( bytes )
-        return flush_to_seq(bytes, p, dir);
-    else if( final_flush )
-        return do_zero_byte_flush(p, dir);
+        return flush_to_seq(trs, bytes, p, dir);
+
+    if ( final_flush )
+        return do_zero_byte_flush(trs, p, dir);
 
     return 0;
 }
 
-void TcpReassembler::final_flush(Packet* p, uint32_t dir)
+void TcpReassembler::final_flush(TcpReassemblerState& trs, Packet* p, uint32_t dir)
 {
-    tracker->set_tf_flags(TF_FORCE_FLUSH);
+    trs.tracker->set_tf_flags(TF_FORCE_FLUSH);
 
-    if ( flush_stream(p, dir, true) )
-        purge_flushed_ackd( );
+    if ( flush_stream(trs, p, dir, true) )
+    {
+        if ( trs.server_side )
+            tcpStats.server_cleanups++;
+        else
+            tcpStats.client_cleanups++;
 
-    tracker->clear_tf_flags(TF_FORCE_FLUSH);
+        purge_flushed_ackd(trs);
+    }
+    trs.tracker->clear_tf_flags(TF_FORCE_FLUSH);
 }
 
 static Packet* set_packet(Flow* flow, uint32_t flags, bool c2s)
@@ -854,30 +862,26 @@ static Packet* set_packet(Flow* flow, uint32_t flags, bool c2s)
     return p;
 }
 
-void TcpReassembler::flush_queued_segments(Flow* flow, bool clear, Packet* p)
+void TcpReassembler::flush_queued_segments(
+    TcpReassemblerState& trs, Flow* flow, bool clear, Packet* p)
 {
     if ( !p )
     {
         // this packet is required if we call finish and/or final_flush
-        p = set_packet(flow, packet_dir, server_side);
-
-        if ( server_side )
-            tcpStats.s5tcp2++;
-        else
-            tcpStats.s5tcp1++;
+        p = set_packet(flow, trs.packet_dir, trs.server_side);
     }
 
-    bool pending = clear and paf_initialized(&tracker->paf_state)
-        and (!tracker->splitter or tracker->splitter->finish(flow) );
+    bool pending = clear and paf_initialized(&trs.tracker->paf_state)
+        and (!trs.tracker->splitter or trs.tracker->splitter->finish(flow) );
 
-    if ( pending and !(flow->ssn_state.ignore_direction & ignore_dir) )
+    if ( pending and !(flow->ssn_state.ignore_direction & trs.ignore_dir) )
     {
-        final_flush(p, packet_dir);
+        final_flush(trs, p, trs.packet_dir);
     }
 }
 
 // this is for post-ack flushing
-uint32_t TcpReassembler::get_reverse_packet_dir(const Packet* p)
+uint32_t TcpReassembler::get_reverse_packet_dir(TcpReassemblerState&, const Packet* p)
 {
     /* Remember, one side's packets are stored in the
      * other side's queue.  So when talker ACKs data,
@@ -890,17 +894,19 @@ uint32_t TcpReassembler::get_reverse_packet_dir(const Packet* p)
      */
     if ( p->is_from_server() )
         return PKT_FROM_CLIENT;
-    else if ( p->is_from_client() )
+
+    if ( p->is_from_client() )
         return PKT_FROM_SERVER;
 
     return 0;
 }
 
-uint32_t TcpReassembler::get_forward_packet_dir(const Packet* p)
+uint32_t TcpReassembler::get_forward_packet_dir(TcpReassemblerState&, const Packet* p)
 {
     if ( p->is_from_server() )
         return PKT_FROM_SERVER;
-    else if ( p->is_from_client() )
+
+    if ( p->is_from_client() )
         return PKT_FROM_CLIENT;
 
     return 0;
@@ -909,16 +915,16 @@ uint32_t TcpReassembler::get_forward_packet_dir(const Packet* p)
 // see flush_pdu_ackd() for details
 // the key difference is that we operate on forward moving data
 // because we don't wait until it is acknowledged
-int32_t TcpReassembler::flush_pdu_ips(uint32_t* flags)
+int32_t TcpReassembler::flush_pdu_ips(TcpReassemblerState& trs, uint32_t* flags)
 {
     Profile profile(s5TcpPAFPerfStats);
-    DetectionEngine::onload(session->flow);
+    DetectionEngine::onload(trs.sos.session->flow);
 
     uint32_t total = 0, avail;
     TcpSegmentNode* tsn;
 
-    avail = get_q_sequenced( );
-    tsn = seglist.next;
+    avail = get_q_sequenced(trs);
+    tsn = trs.sos.seglist.next;
 
     // * must stop if gap (checked in paf_check)
     while ( tsn && *flags && ( total < avail ) )
@@ -926,25 +932,26 @@ int32_t TcpReassembler::flush_pdu_ips(uint32_t* flags)
         int32_t flush_pt;
         uint32_t size = tsn->payload_size;
         uint32_t end = tsn->seq + tsn->payload_size;
-        uint32_t pos = paf_position(&tracker->paf_state);
+        uint32_t pos = paf_position(&trs.tracker->paf_state);
 
         total += size;
 
-        if ( paf_initialized(&tracker->paf_state) && SEQ_LEQ(end, pos) )
+        if ( paf_initialized(&trs.tracker->paf_state) && SEQ_LEQ(end, pos) )
         {
             tsn = tsn->next;
             continue;
         }
 
-        flush_pt = paf_check(tracker->splitter, &tracker->paf_state, session->flow,
+        flush_pt = paf_check(
+            trs.tracker->splitter, &trs.tracker->paf_state, trs.sos.session->flow,
             tsn->payload(), size, total, tsn->seq, flags);
 
         if (flush_pt >= 0)
         {
             // see flush_pdu_ackd()
-            if ( !tracker->splitter->is_paf() && avail > (unsigned)flush_pt )
+            if ( !trs.tracker->splitter->is_paf() && avail > (unsigned)flush_pt )
             {
-                paf_jump(&tracker->paf_state, avail - (unsigned)flush_pt);
+                paf_jump(&trs.tracker->paf_state, avail - (unsigned)flush_pt);
                 return avail;
             }
             return flush_pt;
@@ -955,20 +962,21 @@ int32_t TcpReassembler::flush_pdu_ips(uint32_t* flags)
     return -1;
 }
 
-void TcpReassembler::fallback()
+void TcpReassembler::fallback(TcpReassemblerState& trs)
 {
-    bool c2s = tracker->splitter->to_server();
+    bool c2s = trs.tracker->splitter->to_server();
 
-    delete tracker->splitter;
-    tracker->splitter = new AtomSplitter(c2s, session->config->paf_max);
-    tracker->paf_state.paf = StreamSplitter::SEARCH;
+    delete trs.tracker->splitter;
+    trs.tracker->splitter = new AtomSplitter(c2s, trs.sos.session->config->paf_max);
+    trs.tracker->paf_state.paf = StreamSplitter::SEARCH;
 
-    session->flow->set_session_flags( c2s ? SSNFLAG_ABORT_CLIENT : SSNFLAG_ABORT_SERVER );
+    trs.sos.session->flow->set_session_flags(
+        c2s ? SSNFLAG_ABORT_CLIENT : SSNFLAG_ABORT_SERVER );
 }
 
-// iterate over seglist and scan all new acked bytes
+// iterate over trs.sos.seglist and scan all new acked bytes
 // - new means not yet scanned
-// - must use seglist data (not packet) since this packet may plug a
+// - must use trs.sos.seglist data (not packet) since this packet may plug a
 //   hole and enable paf scanning of following segments
 // - if we reach a flush point
 //   - return bytes to flush if data available (must be acked)
@@ -981,36 +989,38 @@ void TcpReassembler::fallback()
 // - if we partially scan a segment we must save state so we
 //   know where we left off and can resume scanning the remainder
 
-int32_t TcpReassembler::flush_pdu_ackd(uint32_t* flags)
+int32_t TcpReassembler::flush_pdu_ackd(TcpReassemblerState& trs, uint32_t* flags)
 {
     Profile profile(s5TcpPAFPerfStats);
-    DetectionEngine::onload(session->flow);
+    DetectionEngine::onload(trs.sos.session->flow);
 
     uint32_t total = 0;
-    TcpSegmentNode* tsn = SEQ_LT(seglist_base_seq, tracker->r_win_base) ? seglist.head : nullptr;
+    TcpSegmentNode* tsn =
+        SEQ_LT(trs.sos.seglist_base_seq, trs.tracker->r_win_base) ? trs.sos.seglist.head : nullptr;
 
     // must stop if not acked
     // must use adjusted size of tsn if not fully acked
     // must stop if gap (checked in paf_check)
-    while (tsn && *flags && SEQ_LT(tsn->seq, tracker->r_win_base))
+    while (tsn && *flags && SEQ_LT(tsn->seq, trs.tracker->r_win_base))
     {
         int32_t flush_pt;
         uint32_t size = tsn->payload_size;
         uint32_t end = tsn->seq + tsn->payload_size;
-        uint32_t pos = paf_position(&tracker->paf_state);
+        uint32_t pos = paf_position(&trs.tracker->paf_state);
 
-        if ( paf_initialized(&tracker->paf_state) && SEQ_LEQ(end, pos) )
+        if ( paf_initialized(&trs.tracker->paf_state) && SEQ_LEQ(end, pos) )
         {
             total += size;
             tsn = tsn->next;
             continue;
         }
-        if ( SEQ_GT(end, tracker->r_win_base))
-            size = tracker->r_win_base - tsn->seq;
+        if ( SEQ_GT(end, trs.tracker->r_win_base))
+            size = trs.tracker->r_win_base - tsn->seq;
 
         total += size;
 
-        flush_pt = paf_check(tracker->splitter, &tracker->paf_state, session->flow,
+        flush_pt = paf_check(
+            trs.tracker->splitter, &trs.tracker->paf_state, trs.sos.session->flow,
             tsn->payload(), size, total, tsn->seq, flags);
 
         if ( flush_pt >= 0 )
@@ -1020,13 +1030,14 @@ int32_t TcpReassembler::flush_pdu_ackd(uint32_t* flags)
             // instead of creating more, but smaller, packets
             // FIXIT-L just flush to end of segment to avoid splitting
             // instead of all avail?
-            if ( !tracker->splitter->is_paf() )
+            if ( !trs.tracker->splitter->is_paf() )
             {
                 // get_q_footprint() w/o side effects
-                int32_t avail = tracker->r_win_base - seglist_base_seq;
+                int32_t avail = trs.tracker->r_win_base - trs.sos.seglist_base_seq;
+
                 if ( avail > flush_pt )
                 {
-                    paf_jump(&tracker->paf_state, avail - flush_pt);
+                    paf_jump(&trs.tracker->paf_state, avail - flush_pt);
                     return avail;
                 }
             }
@@ -1038,15 +1049,15 @@ int32_t TcpReassembler::flush_pdu_ackd(uint32_t* flags)
     return -1;
 }
 
-int TcpReassembler::flush_on_data_policy(Packet* p)
+int TcpReassembler::flush_on_data_policy(TcpReassemblerState& trs, Packet* p)
 {
     uint32_t flushed = 0;
 
     DebugMessage(DEBUG_STREAM_STATE, "In CheckFlushPolicyOnData\n");
     DebugFormat(DEBUG_STREAM_STATE, "Listener flush policy: %s\n",
-        flush_policy_names[ tracker->flush_policy ]);
+        flush_policy_names[ trs.tracker->flush_policy ]);
 
-    switch ( tracker->flush_policy )
+    switch ( trs.tracker->flush_policy )
     {
     case STREAM_FLPOLICY_IGNORE:
         DebugMessage(DEBUG_STREAM_STATE, "STREAM_FLPOLICY_IGNORE\n");
@@ -1057,25 +1068,25 @@ int TcpReassembler::flush_on_data_policy(Packet* p)
 
     case STREAM_FLPOLICY_ON_DATA:
     {
-        uint32_t flags = get_forward_packet_dir(p);
-        int32_t flush_amt = flush_pdu_ips(&flags);
+        uint32_t flags = get_forward_packet_dir(trs, p);
+        int32_t flush_amt = flush_pdu_ips(trs, &flags);
         uint32_t this_flush;
 
         while ( flush_amt >= 0 )
         {
             if ( !flush_amt )
-                flush_amt = seglist.next->seq - seglist_base_seq;
+                flush_amt = trs.sos.seglist.next->seq - trs.sos.seglist_base_seq;
 #if 0
 // FIXIT-P can't do this with new HI - copy is inevitable
             // if this payload is exactly one pdu, don't
             // actually flush, just use the raw packet
-            if ( listener->seglist.next &&
-                ( tsd.seq == listener->seglist.next->seq ) &&
-                ( flush_amt == listener->seglist.next->payload_size ) &&
+            if ( listener->trs.sos.seglist.next &&
+                ( tsd.seq == listener->trs.sos.seglist.next->seq ) &&
+                ( flush_amt == listener->trs.sos.seglist.next->payload_size ) &&
                 ( flush_amt == p->dsize ) )
             {
                 this_flush = flush_amt;
-                listener->seglist.next->buffered = true;
+                listener->trs.sos.seglist.next->buffered = true;
                 listener->flush_count++;
                 p->packet_flags |= PKT_PDU_FULL;
                 ShowRebuiltPacket(p);
@@ -1083,7 +1094,7 @@ int TcpReassembler::flush_on_data_policy(Packet* p)
             else
 #endif
             {
-                this_flush = flush_to_seq(flush_amt, p, flags);
+                this_flush = flush_to_seq(trs, flush_amt, p, flags);
             }
             // if we didn't flush as expected, bail
             // (we can flush less than max dsize)
@@ -1091,14 +1102,14 @@ int TcpReassembler::flush_on_data_policy(Packet* p)
                 break;
 
             flushed += this_flush;
-            flags = get_forward_packet_dir(p);
-            flush_amt = flush_pdu_ips(&flags);
+            flags = get_forward_packet_dir(trs, p);
+            flush_amt = flush_pdu_ips(trs, &flags);
         }
 
-        if ( !flags && tracker->splitter->is_paf() )
+        if ( !flags && trs.tracker->splitter->is_paf() )
         {
-            fallback( );
-            return flush_on_data_policy(p);
+            fallback(trs);
+            return flush_on_data_policy(trs, p);
         }
     }
     break;
@@ -1106,15 +1117,15 @@ int TcpReassembler::flush_on_data_policy(Packet* p)
     return flushed;
 }
 
-int TcpReassembler::flush_on_ack_policy(Packet* p)
+int TcpReassembler::flush_on_ack_policy(TcpReassemblerState& trs, Packet* p)
 {
     uint32_t flushed = 0;
 
     DebugMessage(DEBUG_STREAM_STATE, "In CheckFlushPolicyOnAck\n");
     DebugFormat(DEBUG_STREAM_STATE, "Talker flush policy: %s\n",
-        flush_policy_names[ tracker->flush_policy ]);
+        flush_policy_names[ trs.tracker->flush_policy ]);
 
-    switch (tracker->flush_policy)
+    switch (trs.tracker->flush_policy)
     {
     case STREAM_FLPOLICY_IGNORE:
         DebugMessage(DEBUG_STREAM_STATE, "STREAM_FLPOLICY_IGNORE\n");
@@ -1122,61 +1133,62 @@ int TcpReassembler::flush_on_ack_policy(Packet* p)
 
     case STREAM_FLPOLICY_ON_ACK:
     {
-        uint32_t flags = get_reverse_packet_dir(p);
-        int32_t flush_amt = flush_pdu_ackd(&flags);
+        uint32_t flags = get_reverse_packet_dir(trs, p);
+        int32_t flush_amt = flush_pdu_ackd(trs, &flags);
 
         while (flush_amt >= 0)
         {
             if (!flush_amt)
-                flush_amt = seglist.next->seq - seglist_base_seq;
+                flush_amt = trs.sos.seglist.next->seq - trs.sos.seglist_base_seq;
 
-            seglist.next = seglist.head;
-            seglist_base_seq = seglist.head->seq;
+            trs.sos.seglist.next = trs.sos.seglist.head;
+            trs.sos.seglist_base_seq = trs.sos.seglist.head->seq;
 
             // for consistency with other cases, should return total
             // but that breaks flushing pipelined pdus
-            flushed = flush_to_seq(flush_amt, p, flags);
+            flushed = flush_to_seq(trs, flush_amt, p, flags);
 
             // ideally we would purge just once after this loop
             // but that throws off base
-            if ( flushed and seglist.head )
-                purge_to_seq(seglist.head->seq + flushed);
+            if ( flushed and trs.sos.seglist.head )
+                purge_to_seq(trs, trs.sos.seglist.head->seq + flushed);
 
             // if we didn't flush as expected, bail
             // (we can flush less than max dsize)
             if (!flushed)
                 break;
 
-            flags = get_reverse_packet_dir(p);
-            flush_amt = flush_pdu_ackd(&flags);
+            flags = get_reverse_packet_dir(trs, p);
+            flush_amt = flush_pdu_ackd(trs, &flags);
         }
 
-        if (!flags && tracker->splitter->is_paf())
+        if (!flags && trs.tracker->splitter->is_paf())
         {
-            fallback( );
-            return flush_on_ack_policy(p);
+            fallback(trs);
+            return flush_on_ack_policy(trs, p);
         }
     }
     break;
 
     case STREAM_FLPOLICY_ON_DATA:
-        purge_flushed_ackd( );
+        purge_flushed_ackd(trs);
         break;
     }
 
     return flushed;
 }
 
-void TcpReassembler::purge_segment_list()
+void TcpReassembler::purge_segment_list(TcpReassemblerState& trs)
 {
-    seglist.clear( );
-    seg_count = 0;
-    flush_count = 0;
-    seg_bytes_total = 0;
-    seg_bytes_logical = 0;
+    trs.sos.seglist.reset();
+    trs.sos.seg_count = 0;
+    trs.sos.seg_bytes_total = 0;
+    trs.sos.seg_bytes_logical = 0;
+    trs.flush_count = 0;
 }
 
-void TcpReassembler::insert_segment_in_empty_seglist(TcpSegmentDescriptor& tsd)
+void TcpReassembler::insert_segment_in_empty_seglist(
+    TcpReassemblerState& trs, TcpSegmentDescriptor& tsd)
 {
     const tcp::TCPHdr* tcph = tsd.get_tcph();
 
@@ -1186,10 +1198,11 @@ void TcpReassembler::insert_segment_in_empty_seglist(TcpSegmentDescriptor& tsd)
     if ( tcph->is_syn() )
         seq++;
 
-    if ( SEQ_GT(tracker->r_win_base, seq) )
+    if ( SEQ_GT(trs.tracker->r_win_base, seq) )
     {
         DebugMessage(DEBUG_STREAM_STATE, "segment overlaps ack'd data...\n");
-        overlap = tracker->r_win_base - tsd.get_seg_seq();
+        overlap = trs.tracker->r_win_base - tsd.get_seg_seq();
+
         if ( overlap >= tsd.get_seg_len() )
         {
             DebugMessage(DEBUG_STREAM_STATE, "full overlap on ack'd data, dropping segment\n");
@@ -1197,59 +1210,66 @@ void TcpReassembler::insert_segment_in_empty_seglist(TcpSegmentDescriptor& tsd)
         }
     }
 
-    // BLOCK add new block to seglist containing data
-    add_reassembly_segment(tsd, tsd.get_seg_len(), overlap, 0, tsd.get_seg_seq() + overlap, nullptr);
+    // BLOCK add new block to trs.sos.seglist containing data
+    add_reassembly_segment(
+        trs, tsd, tsd.get_seg_len(), overlap, 0, tsd.get_seg_seq() + overlap, nullptr);
 
     DebugFormat(DEBUG_STREAM_STATE,
-        "Attached new queue to seglist, %u bytes queued, base_seq 0x%X\n",
-        tsd.get_seg_len() - overlap, seglist_base_seq);
+        "Attached new queue to trs.sos.seglist, %u bytes queued, base_seq 0x%X\n",
+        tsd.get_seg_len() - overlap, trs.sos.seglist_base_seq);
 }
 
-void TcpReassembler::init_overlap_editor(TcpSegmentDescriptor& tsd)
+void TcpReassembler::init_overlap_editor(
+    TcpReassemblerState& trs, TcpSegmentDescriptor& tsd)
 {
     TcpSegmentNode* left = nullptr;
     TcpSegmentNode* right = nullptr;
     TcpSegmentNode* tsn = nullptr;
+
     int32_t dist_head;
     int32_t dist_tail;
+
     DEBUG_WRAP(
         TcpSegmentNode *lastptr = nullptr;
-        uint32_t base_seq = seglist_base_seq;
+        uint32_t base_seq = trs.sos.seglist_base_seq;
         int last = 0;
-        );
+    );
 
-    if ( seglist.head && seglist.tail )
+    if ( trs.sos.seglist.head && trs.sos.seglist.tail )
     {
-        if ( SEQ_GT(tsd.get_seg_seq(), seglist.head->seq) )
-            dist_head = tsd.get_seg_seq() - seglist.head->seq;
+        if ( SEQ_GT(tsd.get_seg_seq(), trs.sos.seglist.head->seq) )
+            dist_head = tsd.get_seg_seq() - trs.sos.seglist.head->seq;
         else
-            dist_head = seglist.head->seq - tsd.get_seg_seq();
+            dist_head = trs.sos.seglist.head->seq - tsd.get_seg_seq();
 
-        if ( SEQ_GT(tsd.get_seg_seq(), seglist.tail->seq) )
-            dist_tail = tsd.get_seg_seq() - seglist.tail->seq;
+        if ( SEQ_GT(tsd.get_seg_seq(), trs.sos.seglist.tail->seq) )
+            dist_tail = tsd.get_seg_seq() - trs.sos.seglist.tail->seq;
         else
-            dist_tail = seglist.tail->seq - tsd.get_seg_seq();
+            dist_tail = trs.sos.seglist.tail->seq - tsd.get_seg_seq();
     }
     else
         dist_head = dist_tail = 0;
 
     if ( SEQ_LEQ(dist_head, dist_tail) )
     {
-        for ( tsn = seglist.head; tsn; tsn = tsn->next )
+        for ( tsn = trs.sos.seglist.head; tsn; tsn = tsn->next )
         {
             DEBUG_WRAP(
                 DebugFormat(DEBUG_STREAM_STATE, "tsn: %p  seq: 0x%X  size: %hu delta: %u\n",
-                (void*) tsn, tsn->seq, tsn->payload_size, ( tsn->seq - base_seq ) - last);
+                    (void*) tsn, tsn->seq, tsn->payload_size, ( tsn->seq - base_seq ) - last);
+
                 last = tsn->seq - base_seq;
                 lastptr = tsn;
 
                 DebugFormat(DEBUG_STREAM_STATE, "   lastptr: %p tsn->next: %p tsn->prev: %p\n",
-                (void*) lastptr, (void*) tsn->next, (void*) tsn->prev);
-                );
+                    (void*) lastptr, (void*) tsn->next, (void*) tsn->prev);
+            );
 
             right = tsn;
+
             if ( SEQ_GEQ(right->seq, tsd.get_seg_seq() ) )
                 break;
+
             left = right;
         }
 
@@ -1258,21 +1278,24 @@ void TcpReassembler::init_overlap_editor(TcpSegmentDescriptor& tsd)
     }
     else
     {
-        for ( tsn = seglist.tail; tsn; tsn = tsn->prev )
+        for ( tsn = trs.sos.seglist.tail; tsn; tsn = tsn->prev )
         {
             DEBUG_WRAP(
                 DebugFormat(DEBUG_STREAM_STATE, "tsn: %p  seq: 0x%X  size: %hu delta: %u\n",
-                (void*) tsn, tsn->seq, tsn->payload_size, ( tsn->seq - base_seq ) - last);
+                    (void*) tsn, tsn->seq, tsn->payload_size, ( tsn->seq - base_seq ) - last);
+
                 last = tsn->seq - base_seq;
                 lastptr = tsn;
 
                 DebugFormat(DEBUG_STREAM_STATE, "   lastptr: %p tsn->next: %p tsn->prev: %p\n",
-                (void*) lastptr, (void*) tsn->next, (void*) tsn->prev);
-                );
+                    (void*) lastptr, (void*) tsn->next, (void*) tsn->prev);
+            );
 
             left = tsn;
+
             if ( SEQ_LT(left->seq, tsd.get_seg_seq() ) )
                 break;
+
             right = left;
         }
 
@@ -1282,53 +1305,60 @@ void TcpReassembler::init_overlap_editor(TcpSegmentDescriptor& tsd)
 
     DebugMessage(DEBUG_STREAM_STATE, "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n");
     DebugMessage(DEBUG_STREAM_STATE, "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n");
+
     DebugFormat(DEBUG_STREAM_STATE, "left: %p:0x%X  right: %p:0x%X\n",
         (void*) left, left ? left->seq : 0, (void*) right, right ? right->seq : 0);
 
-    init_soe(tsd, left, right);
+    trs.sos.init_soe(tsd, left, right);
 }
 
-int TcpReassembler::insert_segment_in_seglist(TcpSegmentDescriptor& tsd)
+int TcpReassembler::insert_segment_in_seglist(
+    TcpReassemblerState& trs, TcpSegmentDescriptor& tsd)
 {
     int rc = STREAM_INSERT_OK;
 
     DebugFormat(DEBUG_STREAM_STATE,
         "Queuing %u bytes on stream!\nbase_seq: %X seq: %X  seq_end: %X\n",
-        tsd.get_end_seq() - tsd.get_seg_seq(), seglist_base_seq, tsd.get_seg_seq(),
+        tsd.get_end_seq() - tsd.get_seg_seq(), trs.sos.seglist_base_seq, tsd.get_seg_seq(),
         tsd.get_end_seq());
 
-    DebugFormat(DEBUG_STREAM_STATE, "%u segments on seglist\n", get_pending_segment_count(0));
+    DebugFormat(DEBUG_STREAM_STATE, "%u segments on trs.sos.seglist\n",
+        get_pending_segment_count(trs, 0));
+
     DebugMessage(DEBUG_STREAM_STATE, "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n");
     DebugMessage(DEBUG_STREAM_STATE, "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n");
 
     // NORM fast tracks are in sequence - no norms
-    if ( seglist.tail && is_segment_fasttrack(seglist.tail, tsd) )
+    if ( trs.sos.seglist.tail && is_segment_fasttrack(trs, trs.sos.seglist.tail, tsd) )
     {
         /* segment fit cleanly at the end of the segment list */
-        TcpSegmentNode* left = seglist.tail;
+        TcpSegmentNode* left = trs.sos.seglist.tail;
 
         DebugFormat(DEBUG_STREAM_STATE, "Fast tracking segment! (tail_seq %X size %d)\n",
-            seglist.tail->seq, seglist.tail->payload_size);
+            trs.sos.seglist.tail->seq, trs.sos.seglist.tail->payload_size);
 
         // BLOCK add to existing block and/or allocate new block
-        rc = add_reassembly_segment(tsd, tsd.get_seg_len(), 0, 0, tsd.get_seg_seq(), left);
+        rc = add_reassembly_segment(trs, tsd, tsd.get_seg_len(), 0, 0, tsd.get_seg_seq(), left);
         return rc;
     }
 
-    init_overlap_editor(tsd);
-    rc = eval_left();
+    init_overlap_editor(trs, tsd);
+    rc = eval_left(trs);
+
     if ( rc != STREAM_INSERT_OK )
         return rc;
 
-    rc = eval_right( );
+    rc = eval_right(trs);
+
     if ( rc != STREAM_INSERT_OK )
         return rc;
 
-    if ( keep_segment )
+    if ( trs.sos.keep_segment )
     {
         /* Adjust slide so that is correct relative to orig seq */
-        slide = seq - tsd.get_seg_seq();
-        rc = add_reassembly_segment(tsd, len, slide, trunc_len, seq, left);
+        trs.sos.slide = trs.sos.seq - tsd.get_seg_seq();
+        rc = add_reassembly_segment(
+            trs, tsd, trs.sos.len, trs.sos.slide, trs.sos.trunc_len, trs.sos.seq, trs.sos.left);
     }
     else
     {
@@ -1339,39 +1369,40 @@ int TcpReassembler::insert_segment_in_seglist(TcpSegmentDescriptor& tsd)
     return rc;
 }
 
-int TcpReassembler::queue_packet_for_reassembly(TcpSegmentDescriptor& tsd)
+int TcpReassembler::queue_packet_for_reassembly(
+    TcpReassemblerState& trs, TcpSegmentDescriptor& tsd)
 {
     Profile profile(s5TcpInsertPerfStats);
 
     int rc = STREAM_INSERT_OK;
 
-    if ( seg_count == 0 )
+    if ( trs.sos.seg_count == 0 )
     {
-        insert_segment_in_empty_seglist(tsd);
+        insert_segment_in_empty_seglist(trs, tsd);
         return STREAM_INSERT_OK;
     }
 
-    if ( SEQ_GT(tracker->r_win_base, tsd.get_seg_seq() ) )
+    if ( SEQ_GT(trs.tracker->r_win_base, tsd.get_seg_seq() ) )
     {
-        int32_t offset = tracker->r_win_base - tsd.get_seg_seq();
+        int32_t offset = trs.tracker->r_win_base - tsd.get_seg_seq();
 
         if ( offset < tsd.get_seg_len() )
         {
             tsd.slide_segment_in_rcv_window(offset);
-            rc = insert_segment_in_seglist(tsd);
+            rc = insert_segment_in_seglist(trs, tsd);
             tsd.slide_segment_in_rcv_window(-offset);
         }
     }
     else
-        rc = insert_segment_in_seglist(tsd);
+        rc = insert_segment_in_seglist(trs, tsd);
 
     return rc;
 }
 
 #ifdef SEG_TEST
-static void CheckSegments(const TcpStreamTracker* a)
+static void CheckSegments(const TcpStreamtrs.tracker* a)
 {
-    TcpSegmentNode* tsn = a->seglist.head;
+    TcpSegmentNode* tsn = a->trs.sos.seglist.head;
     uint32_t sx = tsn ? tsn->seq : 0;
 
     while ( tsn )
@@ -1385,6 +1416,5 @@ static void CheckSegments(const TcpStreamTracker* a)
         tsn = tsn->next;
     }
 }
-
 #endif
 
index 28661bee761539d76a7272ccb69f2b32647dc17f..8a9ffcf54014a638d812fe66504eb27db5e27c26 100644 (file)
@@ -31,137 +31,65 @@ class TcpStreamTracker;
 class TcpReassembler : public SegmentOverlapEditor
 {
 public:
-
-    virtual int queue_packet_for_reassembly(TcpSegmentDescriptor&);
-    virtual void purge_segment_list();
-    virtual int flush_stream(snort::Packet* p, uint32_t dir, bool final_flush = false);
-    virtual int purge_flushed_ackd();
-    virtual void flush_queued_segments(snort::Flow* flow, bool clear, snort::Packet* p = nullptr);
-    virtual bool is_segment_pending_flush();
-    virtual int flush_on_data_policy(snort::Packet*);
-    virtual int flush_on_ack_policy(snort::Packet*);
-    void set_seglist_base_seq(uint32_t seglist_base_seq)
-    {
-        this->seglist_base_seq = seglist_base_seq;
-        DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", seglist_base_seq);
-    }
-
-    uint32_t get_seglist_base_seq() const
-    {
-        return seglist_base_seq;
-    }
-
-    void set_xtradata_mask(uint32_t xtradata_mask)
-    {
-        this->xtradata_mask = xtradata_mask;
-    }
-
-    uint32_t get_xtradata_mask() const
-    {
-        return xtradata_mask;
-    }
-
-    uint32_t get_seg_count() const
-    {
-        return seg_count;
-    }
-
-    uint32_t get_seg_bytes_total() const
-    {
-        return seg_bytes_total;
-    }
-
-    uint32_t get_overlap_count() const
-    {
-        return overlap_count;
-    }
-
-    void set_overlap_count(uint32_t overlap_count)
-    {
-        this->overlap_count = overlap_count;
-    }
-
-    uint32_t get_flush_count() const
-    {
-        return flush_count;
-    }
-
-    uint32_t get_seg_bytes_logical() const
-    {
-        return seg_bytes_logical;
-    }
-
-    ReassemblyPolicy get_reassembly_policy() const
-    {
-        return reassembly_policy;
-    }
-
-    void trace_segments();
+    virtual int queue_packet_for_reassembly(TcpReassemblerState&, TcpSegmentDescriptor&);
+    virtual void purge_segment_list(TcpReassemblerState&);
+    virtual int purge_flushed_ackd(TcpReassemblerState&);
+    virtual int flush_stream(
+        TcpReassemblerState&, snort::Packet* p, uint32_t dir, bool final_flush = false);
+    virtual void flush_queued_segments(
+        TcpReassemblerState&, snort::Flow* flow, bool clear, snort::Packet* p = nullptr);
+    virtual bool is_segment_pending_flush(TcpReassemblerState&);
+    virtual int flush_on_data_policy(TcpReassemblerState&, snort::Packet*);
+    virtual int flush_on_ack_policy(TcpReassemblerState&, snort::Packet*);
+    virtual void trace_segments(TcpReassemblerState&);
 
 protected:
-    TcpReassembler(TcpSession* session, TcpStreamTracker* tracker,
-            StreamPolicy os_policy, bool server) : server_side(server), tracker(tracker)
-    {
-        this->session = session;
-        set_tcp_reassembly_policy(os_policy);
-
-        if ( server_side )
-        {
-            ignore_dir = SSN_DIR_FROM_CLIENT;
-            packet_dir = PKT_FROM_CLIENT;
-        }
-        else
-        {
-            ignore_dir = SSN_DIR_FROM_SERVER;
-            packet_dir = PKT_FROM_SERVER;
-        }
-
-        seglist.head = nullptr;
-        seglist.tail = nullptr;
-        seglist.next = nullptr;
-    }
-
-    int add_reassembly_segment(TcpSegmentDescriptor&, int16_t len, uint32_t slide, uint32_t trunc,
-        uint32_t seq, TcpSegmentNode* left) override;
-    int dup_reassembly_segment(TcpSegmentNode* left, TcpSegmentNode** retSeg) override;
-    int delete_reassembly_segment(TcpSegmentNode*) override;
-
-    virtual void insert_segment_in_empty_seglist(TcpSegmentDescriptor&);
-    virtual int insert_segment_in_seglist(TcpSegmentDescriptor&);
-
-    void set_tcp_reassembly_policy(StreamPolicy os_policy);
-    virtual uint32_t get_pending_segment_count(unsigned max);
-
-    bool flush_data_ready();
-    int trim_delete_reassembly_segment(TcpSegmentNode*, uint32_t flush_seq);
-    void queue_reassembly_segment(TcpSegmentNode* prev, TcpSegmentNode*);
-    void init_overlap_editor(TcpSegmentDescriptor&);
-    bool is_segment_fasttrack(TcpSegmentNode* tail, TcpSegmentDescriptor&);
-    int purge_alerts(snort::Flow*);
-    void show_rebuilt_packet(snort::Packet*);
-    uint32_t get_flush_data_len(TcpSegmentNode*, uint32_t to_seq, unsigned max);
-    int flush_data_segments(snort::Packet*, uint32_t total, snort::Packet* pdu);
-    void prep_pdu(snort::Flow*, snort::Packet*, uint32_t pkt_flags, snort::Packet* pdu);
-    snort::Packet* initialize_pdu(snort::Packet* p, uint32_t pkt_flags, struct timeval tv);
-    int _flush_to_seq(uint32_t bytes, snort::Packet*, uint32_t pkt_flags);
-    int flush_to_seq(uint32_t bytes, snort::Packet*, uint32_t pkt_flags);
-    int do_zero_byte_flush(snort::Packet* p, uint32_t pkt_flags);
-    uint32_t get_q_footprint();
-    uint32_t get_q_sequenced();
-    void final_flush(snort::Packet*, uint32_t dir);
-    uint32_t get_reverse_packet_dir(const snort::Packet*);
-    uint32_t get_forward_packet_dir(const snort::Packet*);
-    int32_t flush_pdu_ips(uint32_t*);
-    void fallback();
-    int32_t flush_pdu_ackd(uint32_t* flags);
-    int purge_to_seq(uint32_t flush_seq);
-
-    bool server_side;
-    TcpStreamTracker* tracker;
-    uint8_t ignore_dir;
-    uint8_t packet_dir;
-    uint32_t flush_count = 0; /* number of flushed queued segments */
-    uint32_t xtradata_mask = 0; /* extra data available to log */
+    TcpReassembler() = default;
+
+    int add_reassembly_segment(
+        TcpReassemblerState&, TcpSegmentDescriptor&, int16_t len, uint32_t slide,
+        uint32_t trunc, uint32_t seq, TcpSegmentNode* left) override;
+
+    int dup_reassembly_segment(
+        TcpReassemblerState&, TcpSegmentNode* left, TcpSegmentNode** retSeg) override;
+
+    int delete_reassembly_segment(TcpReassemblerState&, TcpSegmentNode*) override;
+
+    virtual void insert_segment_in_empty_seglist(TcpReassemblerState&, TcpSegmentDescriptor&);
+    virtual int insert_segment_in_seglist(TcpReassemblerState&, TcpSegmentDescriptor&);
+
+    virtual uint32_t get_pending_segment_count(TcpReassemblerState&, unsigned max);
+
+    bool flush_data_ready(TcpReassemblerState&);
+    int trim_delete_reassembly_segment(TcpReassemblerState&, TcpSegmentNode*, uint32_t flush_seq);
+    void queue_reassembly_segment(TcpReassemblerState&, TcpSegmentNode* prev, TcpSegmentNode*);
+    void init_overlap_editor(TcpReassemblerState&, TcpSegmentDescriptor&);
+    bool is_segment_fasttrack(TcpReassemblerState&, TcpSegmentNode* tail, TcpSegmentDescriptor&);
+    int purge_alerts(TcpReassemblerState&, snort::Flow*);
+    void show_rebuilt_packet(TcpReassemblerState&, snort::Packet*);
+
+    uint32_t get_flush_data_len(
+        TcpReassemblerState&, TcpSegmentNode*, uint32_t to_seq, unsigned max);
+    int flush_data_segments(
+        TcpReassemblerState&, snort::Packet*, uint32_t total, snort::Packet* pdu);
+    void prep_pdu(
+        TcpReassemblerState&, snort::Flow*, snort::Packet*, uint32_t pkt_flags,
+        snort::Packet* pdu);
+    snort::Packet* initialize_pdu(
+        TcpReassemblerState&, snort::Packet* p, uint32_t pkt_flags, struct timeval tv);
+
+    int _flush_to_seq(TcpReassemblerState&, uint32_t bytes, snort::Packet*, uint32_t pkt_flags);
+    int flush_to_seq(TcpReassemblerState&, uint32_t bytes, snort::Packet*, uint32_t pkt_flags);
+    int do_zero_byte_flush(TcpReassemblerState&, snort::Packet* p, uint32_t pkt_flags);
+    uint32_t get_q_footprint(TcpReassemblerState&);
+    uint32_t get_q_sequenced(TcpReassemblerState&);
+    void final_flush(TcpReassemblerState&, snort::Packet*, uint32_t dir);
+    uint32_t get_reverse_packet_dir(TcpReassemblerState&, const snort::Packet*);
+    uint32_t get_forward_packet_dir(TcpReassemblerState&, const snort::Packet*);
+    int32_t flush_pdu_ips(TcpReassemblerState&, uint32_t*);
+    void fallback(TcpReassemblerState&);
+    int32_t flush_pdu_ackd(TcpReassemblerState&, uint32_t* flags);
+    int purge_to_seq(TcpReassemblerState&, uint32_t flush_seq);
 };
 
 #endif
index e54761e8437bbd17098bdb7b9119f4ad2a5f15ce..91b6b3ba9490eb3424b19f2e97654664e605d19e 100644 (file)
 #endif
 
 #include "tcp_reassemblers.h"
+#include "stream/libtcp/tcp_stream_tracker.h"
 
 class TcpReassemblerFirst : public TcpReassembler
 {
 public:
-    TcpReassemblerFirst(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_FIRST, server)
-    { }
+    TcpReassemblerFirst() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_new( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_new(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os5( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os5(trs); }
 };
 
 class TcpReassemblerLast : public TcpReassembler
 {
 public:
-    TcpReassemblerLast(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_LAST, server)
-    { }
+    TcpReassemblerLast() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_last( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_last(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_existing( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_existing(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os4( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os4(trs); }
 };
 
 class TcpReassemblerLinux : public TcpReassembler
 {
 public:
-    TcpReassemblerLinux(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_LINUX, server)
-    { }
+    TcpReassemblerLinux() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_existing( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_existing(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os2( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os2(trs); }
 };
 
 class TcpReassemblerOldLinux : public TcpReassembler
 {
 public:
-    TcpReassemblerOldLinux(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_OLD_LINUX, server)
-    { }
+    TcpReassemblerOldLinux() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_existing( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_existing(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os4( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os4(trs); }
 };
 
 class TcpReassemblerBSD : public TcpReassembler
 {
 public:
-    TcpReassemblerBSD(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_BSD, server)
-    { }
+    TcpReassemblerBSD() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_existing( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_existing(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os1( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os1(trs); }
 };
 
 class TcpReassemblerMacOS : public TcpReassembler
 {
 public:
-    TcpReassemblerMacOS(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_MACOS, server)
-    { }
+    TcpReassemblerMacOS() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_existing( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_existing(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os1( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os1(trs); }
 };
 
 class TcpReassemblerSolaris : public TcpReassembler
 {
 public:
-    TcpReassemblerSolaris(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_SOLARIS, server)
-    { }
+    TcpReassemblerSolaris() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_trim_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_trim_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_new( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_new(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os3( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os3(trs); }
 };
 
 class TcpReassemblerIrix : public TcpReassembler
 {
 public:
-    TcpReassemblerIrix(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_IRIX, server)
-    { }
+    TcpReassemblerIrix() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs);  }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_existing( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_existing(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os2( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os2(trs); }
 };
 
 class TcpReassemblerHpux11 : public TcpReassembler
 {
 public:
-    TcpReassemblerHpux11(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_HPUX11, server)
-    { }
+    TcpReassemblerHpux11() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_trim_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_trim_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_new( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_new(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os3( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os3(trs); }
 };
 
 class TcpReassemblerHpux10 : public TcpReassembler
 {
 public:
-    TcpReassemblerHpux10(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_HPUX10, server)
-    { }
+    TcpReassemblerHpux10() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_existing( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_existing(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os2( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os2(trs); }
 };
 
 class TcpReassemblerWindows : public TcpReassembler
 {
 public:
-    TcpReassemblerWindows(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_WINDOWS, server)
-    { }
+    TcpReassemblerWindows() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_existing( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_existing(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os1( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os1(trs); }
 };
 
 class TcpReassemblerWindows2K3 : public TcpReassembler
 {
 public:
-    TcpReassemblerWindows2K3(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_WINDOWS2K3, server)
-    { }
+    TcpReassemblerWindows2K3() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_existing( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_existing(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os1( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os1(trs); }
 };
 
 class TcpReassemblerVista : public TcpReassembler
 {
 public:
-    TcpReassemblerVista(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassembler(session, tracker, StreamPolicy::OS_VISTA, server)
-    { }
+    TcpReassemblerVista() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_new( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_new(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os5 ( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os5 (trs); }
 };
 
 class TcpReassemblerProxy : public TcpReassemblerFirst
 {
 public:
-    TcpReassemblerProxy(TcpSession* session, TcpStreamTracker* tracker, bool server) :
-        TcpReassemblerFirst(session, tracker, server)
-    {
-        tcp_ips_data = NORM_MODE_TEST;
-    }
+    TcpReassemblerProxy() = default;
 
 private:
-    int insert_left_overlap() override
-    {
-        return left_overlap_keep_first( );
-    }
+    int insert_left_overlap(TcpReassemblerState& trs) override
+    { return left_overlap_keep_first(trs); }
 
-    void insert_right_overlap() override
-    {
-        right_overlap_truncate_new( );
-    }
+    void insert_right_overlap(TcpReassemblerState& trs) override
+    { right_overlap_truncate_new(trs); }
 
-    int insert_full_overlap() override
-    {
-        return full_right_overlap_os5( );
-    }
+    int insert_full_overlap(TcpReassemblerState& trs) override
+    { return full_right_overlap_os5(trs); }
 };
 
-TcpReassembler* TcpReassemblerFactory::create(TcpSession* session, TcpStreamTracker* tracker,
-    StreamPolicy os_policy, bool server)
+static ReassemblyPolicy stream_reassembly_policy_map[] =
 {
-    NormMode tcp_ips_data = Normalize_GetMode(NORM_TCP_IPS);
+    ReassemblyPolicy::OS_INVALID,
+    ReassemblyPolicy::OS_FIRST,
+    ReassemblyPolicy::OS_LAST,
+    ReassemblyPolicy::OS_LINUX,
+    ReassemblyPolicy::OS_OLD_LINUX,
+    ReassemblyPolicy::OS_BSD,
+    ReassemblyPolicy::OS_MACOS,
+    ReassemblyPolicy::OS_SOLARIS,
+    ReassemblyPolicy::OS_IRIX,
+    ReassemblyPolicy::OS_HPUX11,
+    ReassemblyPolicy::OS_HPUX10,
+    ReassemblyPolicy::OS_WINDOWS,
+    ReassemblyPolicy::OS_WINDOWS2K3,
+    ReassemblyPolicy::OS_VISTA,
+    ReassemblyPolicy::OS_PROXY,
+    ReassemblyPolicy::OS_DEFAULT
+};
 
-    if (tcp_ips_data == NORM_MODE_ON)
-        return new TcpReassemblerFirst(session, tracker, server);
+void TcpReassemblerPolicy::init(TcpSession* ssn, TcpStreamTracker* trk, StreamPolicy pol, bool server)
+{
+    trs.sos.init_sos(ssn, stream_reassembly_policy_map[ static_cast<int>(pol) ]);
+    trs.server_side = server;
+    trs.tracker = trk;
+
+    if ( trs.server_side )
+    {
+        trs.ignore_dir = SSN_DIR_FROM_CLIENT;
+        trs.packet_dir = PKT_FROM_CLIENT;
+    }
     else
     {
-        switch (os_policy)
-        {
-        case StreamPolicy::OS_FIRST:
-            return new TcpReassemblerFirst(session, tracker, server);
-
-        case StreamPolicy::OS_LAST:
-            return new TcpReassemblerLast(session, tracker, server);
-
-        case StreamPolicy::OS_LINUX:
-            return new TcpReassemblerLinux(session, tracker, server);
-
-        case StreamPolicy::OS_OLD_LINUX:
-            return new TcpReassemblerOldLinux(session, tracker, server);
-
-        case StreamPolicy::OS_BSD:
-            return new TcpReassemblerBSD(session, tracker, server);
-
-        case StreamPolicy::OS_MACOS:
-            return new TcpReassemblerMacOS(session, tracker, server);
-
-        case StreamPolicy::OS_SOLARIS:
-            return new TcpReassemblerSolaris(session, tracker, server);
-
-        case StreamPolicy::OS_IRIX:
-            return new TcpReassemblerIrix(session, tracker, server);
-
-        case StreamPolicy::OS_HPUX11:
-            return new TcpReassemblerHpux11(session, tracker, server);
-
-        case StreamPolicy::OS_HPUX10:
-            return new TcpReassemblerHpux10(session, tracker, server);
+        trs.ignore_dir = SSN_DIR_FROM_SERVER;
+        trs.packet_dir = PKT_FROM_SERVER;
+    }
 
-        case StreamPolicy::OS_WINDOWS:
-            return new TcpReassemblerWindows(session, tracker, server);
+    trs.flush_count = 0;
+    trs.xtradata_mask = 0;
 
-        case StreamPolicy::OS_WINDOWS2K3:
-            return new TcpReassemblerWindows2K3(session, tracker, server);
+    reassembler = TcpReassemblerFactory::create(pol);
+}
 
-        case StreamPolicy::OS_VISTA:
-            return new TcpReassemblerVista(session, tracker, server);
+void TcpReassemblerPolicy::reset()
+{
+    init(nullptr, nullptr, StreamPolicy::OS_INVALID, false);
+}
 
-        case StreamPolicy::OS_PROXY:
-            return new TcpReassemblerProxy(session, tracker, server);
+TcpReassembler* TcpReassemblerFactory::create(StreamPolicy os_policy)
+{
+    static TcpReassemblerFirst first;
+    static TcpReassemblerLast last;
+    static TcpReassemblerLinux linux;
+    static TcpReassemblerOldLinux old_linux;
+    static TcpReassemblerBSD bsd;
+    static TcpReassemblerMacOS mac_os;
+    static TcpReassemblerSolaris solaris;
+    static TcpReassemblerIrix irix;
+    static TcpReassemblerHpux11 hpux11;
+    static TcpReassemblerHpux10 hpux10;
+    static TcpReassemblerWindows windows;
+    static TcpReassemblerWindows2K3 windows_2K3;
+    static TcpReassemblerVista vista;
+    static TcpReassemblerProxy proxy;
 
-        default:
-            return new TcpReassemblerBSD(session, tracker, server);
-        }
-    }
+    NormMode tcp_ips_data = Normalize_GetMode(NORM_TCP_IPS);
+    StreamPolicy actual = (tcp_ips_data == NORM_MODE_ON) ? StreamPolicy::OS_FIRST : os_policy;
+    TcpReassembler* reassembler;
+
+    switch (actual)
+    {
+    case StreamPolicy::OS_FIRST: reassembler = &first; break;
+    case StreamPolicy::OS_LAST: reassembler = &last; break;
+    case StreamPolicy::OS_LINUX: reassembler = &linux; break;
+    case StreamPolicy::OS_OLD_LINUX: reassembler = &old_linux; break;
+    case StreamPolicy::OS_BSD: reassembler = &bsd; break;
+    case StreamPolicy::OS_MACOS: reassembler = &mac_os; break;
+    case StreamPolicy::OS_SOLARIS: reassembler = &solaris; break;
+    case StreamPolicy::OS_IRIX: reassembler = &irix; break;
+    case StreamPolicy::OS_HPUX11: reassembler = &hpux11; break;
+    case StreamPolicy::OS_HPUX10: reassembler = &hpux10; break;
+    case StreamPolicy::OS_WINDOWS: reassembler = &windows; break;
+    case StreamPolicy::OS_WINDOWS2K3: reassembler = &windows_2K3; break;
+    case StreamPolicy::OS_VISTA: reassembler = &vista; break;
+    case StreamPolicy::OS_PROXY: reassembler = &proxy; break;
+    default: reassembler = &bsd; break;
+    }
+
+    return reassembler;
 }
 
index e9b1674ac48a7899156e64e424fa1c71b687b021..affa5ba981f6e0348b04ce152661f4a5b24158c3 100644 (file)
 #ifndef TCP_REASSEMBLERS_H
 #define TCP_REASSEMBLERS_H
 
-#include "stream/tcp/tcp_reassembler.h"
+#include "tcp_reassembler.h"
 
 class TcpReassemblerFactory
 {
 public:
-    static TcpReassembler* create(TcpSession* session, TcpStreamTracker* tracker,
-        StreamPolicy os_policy, bool server);
+    static TcpReassembler* create(StreamPolicy);
 };
 
+class TcpReassemblerPolicy
+
+{
+public:
+    TcpReassemblerPolicy() = default;
+    ~TcpReassemblerPolicy() = default;
+
+    void init(TcpSession* ssn, TcpStreamTracker* trk, StreamPolicy pol, bool server);
+    void reset();
+
+    int queue_packet_for_reassembly(TcpSegmentDescriptor& tsd)
+    { return reassembler->queue_packet_for_reassembly(trs, tsd); }
+
+    void purge_segment_list()
+    { reassembler->purge_segment_list(trs); }
+
+    int purge_flushed_ackd()
+    { return reassembler->purge_flushed_ackd(trs); }
+
+    int flush_stream(snort::Packet* p, uint32_t dir, bool final_flush = false)
+    { return reassembler->flush_stream(trs, p, dir, final_flush); }
+
+    void flush_queued_segments(snort::Flow* flow, bool clear, snort::Packet* p = nullptr)
+    { reassembler->flush_queued_segments(trs, flow, clear, p); }
+
+    bool is_segment_pending_flush()
+    { return reassembler->is_segment_pending_flush(trs); }
+
+    int flush_on_data_policy(snort::Packet* p)
+    { return reassembler->flush_on_data_policy(trs, p); }
+
+    int flush_on_ack_policy(snort::Packet* p)
+    { return reassembler->flush_on_ack_policy(trs, p); }
+
+    void trace_segments()
+    { reassembler->trace_segments(trs); }
+
+    void set_seglist_base_seq(uint32_t seglist_base_seq)
+    { trs.sos.seglist_base_seq = seglist_base_seq; }
+
+    uint32_t get_seglist_base_seq() const
+    { return trs.sos.seglist_base_seq; }
+
+    void set_xtradata_mask(uint32_t xtradata_mask)
+    { trs.xtradata_mask = xtradata_mask; }
+
+    uint32_t get_xtradata_mask() const
+    { return trs.xtradata_mask; }
+
+    uint32_t get_seg_count() const
+    { return trs.sos.seg_count; }
+
+    uint32_t get_seg_bytes_total() const
+    { return trs.sos.seg_bytes_total; }
+
+    uint32_t get_overlap_count() const
+    { return trs.sos.overlap_count; }
+
+    void set_overlap_count(uint32_t overlap_count)
+    { trs.sos.overlap_count = overlap_count;  }
+
+    uint32_t get_flush_count() const
+    { return trs.flush_count; }
+
+    uint32_t get_seg_bytes_logical() const
+    { return trs.sos.seg_bytes_logical; }
+
+    ReassemblyPolicy get_reassembly_policy() const
+    { return trs.sos.reassembly_policy; }
+
+    void set_norm_mode_test()
+    { trs.sos.tcp_ips_data = NORM_MODE_TEST; }
+
+private:
+    TcpReassembler* reassembler = nullptr;
+    TcpReassemblerState trs;
+};
 #endif
 
index d8649f69076678af3dfcddea7b4978a121c98db6..47b19bb0a446f214d94d73a3e1f27e313883e843 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "utils/util.h"
 
+#include "segment_overlap_editor.h"
 #include "tcp_module.h"
 
 // FIXIT-P this is going to set each member 2X; once here and once in init
@@ -46,9 +47,9 @@ TcpSegmentNode* TcpSegmentNode::init(TcpSegmentDescriptor& tsd)
     return init(tsd.get_pkt()->pkth->ts, tsd.get_pkt()->data, tsd.get_seg_len() );
 }
 
-TcpSegmentNode* TcpSegmentNode::init(TcpSegmentNode& tsn)
+TcpSegmentNode* TcpSegmentNode::init(TcpSegmentNode& tns)
 {
-    return init(tsn.tv, tsn.payload(), tsn.payload_size);
+    return init(tns.tv, tns.payload(), tns.payload_size);
 }
 
 TcpSegmentNode* TcpSegmentNode::init(const struct timeval& tv, const uint8_t* data, unsigned dsize)
index 1575817519ecc953dd4c989449c34ceb95e18a6f..8092ab87d7385e3577cad2556ca301a92c5e7611 100644 (file)
@@ -16,7 +16,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
 
-// tcp_segment.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_segment_node.h author davis mcpherson <davmcphe@@cisco.com>
 // Created on: Sep 21, 2015
 
 #ifndef TCP_SEGMENT_H
@@ -26,6 +26,8 @@
 #include "stream/libtcp/tcp_segment_descriptor.h"
 #include "stream/tcp/tcp_defs.h"
 
+class TcpSegmentDescriptor;
+
 //-----------------------------------------------------------------
 // we make a lot of TcpSegments so it is organized by member
 // size/alignment requirements to minimize unused space
@@ -37,7 +39,7 @@ struct TcpSegmentNode
     TcpSegmentNode();
 
     static TcpSegmentNode* init(TcpSegmentDescriptor& tsd);
-    static TcpSegmentNode* init(TcpSegmentNode& tsn);
+    static TcpSegmentNode* init(TcpSegmentNode& tns);
     static TcpSegmentNode* init(const struct timeval&, const uint8_t*, unsigned);
 
     void term();
@@ -66,32 +68,10 @@ struct TcpSegmentNode
 class TcpSegmentList
 {
 public:
-    TcpSegmentList() :
-        head(nullptr), tail(nullptr), next(nullptr), count(0)
-    {
-    }
-
-    ~TcpSegmentList()
-    {
-        clear( );
-    }
-
-    TcpSegmentNode* head;
-    TcpSegmentNode* tail;
-
-    // FIXIT-P seglist_base_seq is the sequence number to flush from
-    // and is valid even when seglist is empty.  next points to
-    // the segment to flush from and is set per packet.  should keep
-    // up to date.
-    TcpSegmentNode* next;
-
-    uint32_t count;
-
-    uint32_t clear()
+    uint32_t reset()
     {
         int i = 0;
 
-        DebugMessage(DEBUG_STREAM_STATE, "Clearing segment list.\n");
         while ( head )
         {
             i++;
@@ -102,7 +82,6 @@ public:
 
         head = tail = next = nullptr;
         count = 0;
-        DebugFormat(DEBUG_STREAM_STATE, "Dropped %d segments\n", i);
         return i;
     }
 
@@ -113,6 +92,7 @@ public:
             ss->next = prev->next;
             ss->prev = prev;
             prev->next = ss;
+
             if ( ss->next )
                 ss->next->prev = ss;
             else
@@ -121,6 +101,7 @@ public:
         else
         {
             ss->next = head;
+
             if ( ss->next )
                 ss->next->prev = ss;
             else
@@ -145,6 +126,16 @@ public:
 
         count--;
     }
+
+    TcpSegmentNode* head = nullptr;
+    TcpSegmentNode* tail = nullptr;
+
+    // FIXIT-P seglist_base_seq is the sequence number to flush from
+    // and is valid even when seglist is empty.  next points to
+    // the segment to flush from and is set per packet.  should keep
+    // up to date.
+    TcpSegmentNode* next = nullptr;
+    uint32_t count = 0;
 };
 
 #endif
index b849e85f1cfc1c6c0f06567ffebd93167c9d1606..5b589888105d39c764eb9b570f23f634e569052f 100644 (file)
@@ -69,21 +69,20 @@ static THREAD_LOCAL const char* t_name = nullptr;
 static THREAD_LOCAL const char* l_name = nullptr;
 #endif
 
-TcpSession::TcpSession(Flow* flow) : TcpStreamSession(flow)
+TcpSession::TcpSession(Flow* flow)
+    : TcpStreamSession(flow)
 {
     tsm = TcpStreamStateMachine::get_instance();
-    client = new TcpTracker(true, this);
-    server = new TcpTracker(false, this);
     splitter_init = false;
+
+    client.session = this;
+    server.session = this;
 }
 
 TcpSession::~TcpSession()
 {
     if (tcp_init)
         clear_session(true, false, false);
-
-    delete client;
-    delete server;
 }
 
 bool TcpSession::setup(Packet* p)
@@ -91,9 +90,6 @@ bool TcpSession::setup(Packet* p)
     TcpStreamSession::setup(p);
     splitter_init = false;
 
-    client->init_toolbox();
-    server->init_toolbox();
-
     SESSION_STATS_ADD(tcpStats);
     return true;
 }
@@ -111,21 +107,21 @@ void TcpSession::restart(Packet* p)
 
     if (p->is_from_server())
     {
-        talker = server;
-        listener = client;
+        talker = &server;
+        listener = &client;
     }
     else
     {
-        talker = client;
-        listener = server;
+        talker = &client;
+        listener = &server;
     }
 
     // FIXIT-H on data / on ack must be based on flush policy
     if (p->dsize > 0)
-        listener->reassembler->flush_on_data_policy(p);
+        listener->reassembler.flush_on_data_policy(p);
 
     if (p->ptrs.tcph->is_ack())
-        talker->reassembler->flush_on_ack_policy(p);
+        talker->reassembler.flush_on_ack_policy(p);
 }
 
 //-------------------------------------------------------------------------
@@ -146,18 +142,15 @@ void TcpSession::clear_session(bool free_flow_data, bool flush_segments, bool re
     assert(!p or p->flow == flow);
     DetectionEngine::onload(flow);
 
-    if ( client->reassembler )
-    {
-        if ( flush_segments )
-            client->reassembler->flush_queued_segments(flow, true, p);
-        client->reassembler->purge_segment_list();
-    }
-
-    if ( server->reassembler )
+    if ( tcp_init )
     {
         if ( flush_segments )
-            server->reassembler->flush_queued_segments(flow, true, p);
-        server->reassembler->purge_segment_list();
+        {
+            client.reassembler.flush_queued_segments(flow, true, p);
+            server.reassembler.flush_queued_segments(flow, true, p);
+        }
+        client.reassembler.purge_segment_list();
+        server.reassembler.purge_segment_list();
     }
 
     if ( tcp_init )
@@ -172,15 +165,15 @@ void TcpSession::clear_session(bool free_flow_data, bool flush_segments, bool re
     if ( restart )
     {
         flow->restart(free_flow_data);
-        paf_reset(&client->paf_state);
-        paf_reset(&server->paf_state);
+        paf_reset(&client.paf_state);
+        paf_reset(&server.paf_state);
 
     }
     else
     {
         flow->clear(free_flow_data);
-        paf_clear(&client->paf_state);
-        paf_clear(&server->paf_state);
+        paf_clear(&client.paf_state);
+        paf_clear(&server.paf_state);
     }
 
     set_splitter(true, nullptr);
@@ -307,7 +300,7 @@ bool TcpSession::flow_exceeds_config_thresholds(TcpSegmentDescriptor& tsd)
     }
 
     if ( config->max_queued_bytes
-        && ( listener->reassembler->get_seg_bytes_total() > config->max_queued_bytes ) )
+        && ( listener->reassembler.get_seg_bytes_total() > config->max_queued_bytes ) )
     {
         tcpStats.exceeded_max_bytes++;
         // FIXIT-H add one alert per flow per above
@@ -315,7 +308,7 @@ bool TcpSession::flow_exceeds_config_thresholds(TcpSegmentDescriptor& tsd)
     }
 
     if ( config->max_queued_segs
-        && ( listener->reassembler->get_seg_count() + 1 > config->max_queued_segs ) )
+        && ( listener->reassembler.get_seg_count() + 1 > config->max_queued_segs ) )
     {
         tcpStats.exceeded_max_segs++;
         // FIXIT-H add one alert per flow per above
@@ -339,14 +332,14 @@ void TcpSession::process_tcp_stream(TcpSegmentDescriptor& tsd)
         return;
 
     DebugMessage(DEBUG_STREAM_STATE, "queuing segment\n");
-    listener->reassembler->queue_packet_for_reassembly(tsd);
+    listener->reassembler.queue_packet_for_reassembly(tsd);
 
     // Alert if overlap limit exceeded
     if ( ( config->overlap_limit )
-        && ( listener->reassembler->get_overlap_count() > config->overlap_limit ) )
+        && ( listener->reassembler.get_overlap_count() > config->overlap_limit ) )
     {
         tel.set_tcp_event(EVENT_EXCESSIVE_OVERLAP);
-        listener->reassembler->set_overlap_count(0);
+        listener->reassembler.set_overlap_count(0);
     }
 }
 
@@ -371,26 +364,25 @@ int TcpSession::process_tcp_data(TcpSegmentDescriptor& tsd)
 
     if ( tcph->is_syn() )
     {
-        if (listener->normalizer->get_os_policy() == StreamPolicy::OS_MACOS)
+        if (listener->normalizer.get_os_policy() == StreamPolicy::OS_MACOS)
             seq++;
 
         else
         {
             DebugMessage(DEBUG_STREAM_STATE, "Bailing, data on SYN, not MAC Policy!\n");
-            listener->normalizer->trim_syn_payload(tsd);
+            listener->normalizer.trim_syn_payload(tsd);
             return STREAM_UNALIGNED;
-        }
-    }
+        }   }
 
     /* we're aligned, so that's nice anyway */
     if (seq == listener->r_nxt_ack)
     {
         /* check if we're in the window */
         if (config->policy != StreamPolicy::OS_PROXY
-            and listener->normalizer->get_stream_window(tsd) == 0)
+            and listener->normalizer.get_stream_window(tsd) == 0)
         {
             DebugMessage(DEBUG_STREAM_STATE, "Bailing, we're out of the window!\n");
-            listener->normalizer->trim_win_payload(tsd);
+            listener->normalizer.trim_win_payload(tsd);
             return STREAM_UNALIGNED;
         }
 
@@ -422,10 +414,10 @@ int TcpSession::process_tcp_data(TcpSegmentDescriptor& tsd)
 
         /* check if we're in the window */
         if (config->policy != StreamPolicy::OS_PROXY
-            and listener->normalizer->get_stream_window(tsd) == 0)
+            and listener->normalizer.get_stream_window(tsd) == 0)
         {
             DebugMessage(DEBUG_STREAM_STATE, "Bailing, we're out of the window!\n");
-            listener->normalizer->trim_win_payload(tsd);
+            listener->normalizer.trim_win_payload(tsd);
             return STREAM_UNALIGNED;
         }
 
@@ -458,20 +450,15 @@ void TcpSession::set_os_policy()
 {
     StreamPolicy client_os_policy = flow->ssn_policy ?
         static_cast<StreamPolicy>( flow->ssn_policy ) : config->policy;
+
     StreamPolicy server_os_policy = flow->ssn_policy ?
         static_cast<StreamPolicy>( flow->ssn_policy ) : config->policy;
 
-    if ( client->normalizer == nullptr )
-        client->normalizer = TcpNormalizerFactory::create(this, client_os_policy, client, server);
-
-    if ( server->normalizer == nullptr )
-        server->normalizer = TcpNormalizerFactory::create(this, server_os_policy, server, client);
+    client.normalizer.init(client_os_policy, this, &client, &server);
+    server.normalizer.init(server_os_policy, this, &server, &client);
 
-    if ( client->reassembler == nullptr )
-        client->reassembler = TcpReassemblerFactory::create(this, client, client_os_policy, false);
-
-    if ( server->reassembler == nullptr )
-        server->reassembler = TcpReassemblerFactory::create(this, server, server_os_policy, true);
+    client.reassembler.init(this, &client, client_os_policy, false);
+    server.reassembler.init(this, &server, server_os_policy, true);
 }
 
 // FIXIT-H this is no longer called (but should be)
@@ -480,7 +467,7 @@ void TcpSession::swap_trackers()
     uint32_t session_flags = flow->get_session_flags( );
     if ( ( session_flags & SSNFLAG_CLIENT_SWAP ) && !( session_flags & SSNFLAG_CLIENT_SWAPPED ) )
     {
-        TcpStreamTracker* trk = client;
+        TcpStreamTracker& trk = client;
         client = server;
         server = trk;
 
@@ -513,24 +500,24 @@ void TcpSession::swap_trackers()
 
 void TcpSession::NewTcpSessionOnSyn(TcpSegmentDescriptor& tsd)
 {
-    server->init_on_syn_recv(tsd);
-    client->init_on_syn_sent(tsd);
+    server.init_on_syn_recv(tsd);
+    client.init_on_syn_sent(tsd);
     init_new_tcp_session(tsd);
     tcpStats.sessions_on_syn++;
 }
 
 void TcpSession::NewTcpSessionOnSynAck(TcpSegmentDescriptor& tsd)
 {
-    server->init_on_synack_sent(tsd);
-    client->init_on_synack_recv(tsd);
+    server.init_on_synack_sent(tsd);
+    client.init_on_synack_recv(tsd);
     init_new_tcp_session(tsd);
     tcpStats.sessions_on_syn_ack++;
 }
 
 void TcpSession::update_timestamp_tracking(TcpSegmentDescriptor& tsd)
 {
-    talker->set_tf_flags(listener->normalizer->get_timestamp_flags());
-    if (listener->normalizer->handling_timestamps()
+    talker->set_tf_flags(listener->normalizer.get_timestamp_flags());
+    if (listener->normalizer.handling_timestamps()
         && SEQ_EQ(listener->r_nxt_ack, tsd.get_seg_seq()))
     {
         talker->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
@@ -561,8 +548,8 @@ bool TcpSession::handle_syn_on_reset_session(TcpSegmentDescriptor& tsd)
             // one function can ever perform a normalization.
 
             /* Got SYN/RST.  We're done. */
-            listener->normalizer->trim_syn_payload(tsd);
-            listener->normalizer->trim_rst_payload(tsd);
+            listener->normalizer.trim_syn_payload(tsd);
+            listener->normalizer.trim_rst_payload(tsd);
             pkt_action_mask |= ACTION_RST;
             return false;
         }
@@ -573,9 +560,9 @@ bool TcpSession::handle_syn_on_reset_session(TcpSegmentDescriptor& tsd)
             flow->set_ttl(tsd.get_pkt(), true);
             NewTcpSessionOnSyn(tsd);
             tcpStats.resyns++;
-            listener = server;
-            talker = client;
-            listener->normalizer->ecn_tracker( tcph, config->require_3whs() );
+            listener = &server;
+            talker = &client;
+            listener->normalizer.ecn_tracker(tcph, config->require_3whs());
             flow->update_session_flags(SSNFLAG_SEEN_CLIENT);
         }
         else if (tcph->is_syn_ack())
@@ -589,9 +576,9 @@ bool TcpSession::handle_syn_on_reset_session(TcpSegmentDescriptor& tsd)
                 tcpStats.resyns++;
             }
 
-            listener = client;
-            talker = server;
-            listener->normalizer->ecn_tracker( tcph, config->require_3whs() );
+            listener = &client;
+            talker = &server;
+            listener->normalizer.ecn_tracker(tcph, config->require_3whs());
             flow->update_session_flags(SSNFLAG_SEEN_SERVER);
         }
     }
@@ -625,13 +612,13 @@ void TcpSession::update_ignored_session(TcpSegmentDescriptor& tsd)
 void TcpSession::handle_data_on_syn(TcpSegmentDescriptor& tsd)
 {
     /* MacOS accepts data on SYN, so don't alert if policy is MACOS */
-    if (talker->normalizer->get_os_policy() == StreamPolicy::OS_MACOS)
+    if (talker->normalizer.get_os_policy() == StreamPolicy::OS_MACOS)
     {
         handle_data_segment(tsd);
     }
     else
     {
-        listener->normalizer->trim_syn_payload(tsd);
+        listener->normalizer.trim_syn_payload(tsd);
         DebugMessage(DEBUG_STREAM_STATE, "Got data on SYN packet, not processing it\n");
         tel.set_tcp_event(EVENT_DATA_ON_SYN);
         pkt_action_mask |= ACTION_BAD_PKT;
@@ -660,7 +647,7 @@ void TcpSession::update_paws_timestamps(TcpSegmentDescriptor& tsd)
     DebugFormat(DEBUG_STREAM_STATE, "PAWS update tsd.seq %u > listener->r_win_base %u\n",
         tsd.get_seg_seq(), listener->r_win_base);
 
-    if ( listener->normalizer->handling_timestamps()
+    if ( listener->normalizer.handling_timestamps()
         && SEQ_EQ(listener->r_win_base, tsd.get_seg_seq() ) )
     {
         if ( ( (int32_t)(tsd.get_ts() - talker->get_ts_last() ) >= 0 )
@@ -730,7 +717,7 @@ bool TcpSession::check_for_window_slam(TcpSegmentDescriptor& tsd)
         /* got a window too large, alert! */
         tel.set_tcp_event(EVENT_WINDOW_TOO_LARGE);
         inc_tcp_discards();
-        listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+        listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
         pkt_action_mask |= ACTION_BAD_PKT;
         return true;
     }
@@ -745,7 +732,7 @@ bool TcpSession::check_for_window_slam(TcpSegmentDescriptor& tsd)
         tel.set_tcp_event(EVENT_WINDOW_SLAM);
         inc_tcp_discards();
 
-        if (listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
+        if (listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK))
         {
             pkt_action_mask |= ACTION_BAD_PKT;
             return true;
@@ -757,7 +744,7 @@ bool TcpSession::check_for_window_slam(TcpSegmentDescriptor& tsd)
 
 void TcpSession::mark_packet_for_drop(TcpSegmentDescriptor& tsd)
 {
-    listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+    listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
     set_pkt_action_flag(ACTION_BAD_PKT);
 }
 
@@ -774,9 +761,9 @@ void TcpSession::handle_data_segment(TcpSegmentDescriptor& tsd)
     {
         uint8_t tcp_options_len = tsd.get_tcph()->options_len();
         if (tsd.is_packet_from_server())
-            server->set_tcp_options_len(tcp_options_len);
+            server.set_tcp_options_len(tcp_options_len);
         else
-            client->set_tcp_options_len(tcp_options_len);
+            client.set_tcp_options_len(tcp_options_len);
 
         // FIXIT-M move this to normalizer base class, handle OS_PROXY in derived class
         if (config->policy != StreamPolicy::OS_PROXY)
@@ -794,13 +781,13 @@ void TcpSession::handle_data_segment(TcpSegmentDescriptor& tsd)
                 TcpStreamTracker* st = listener;
 
                 // trim to fit in window and mss as needed
-                st->normalizer->trim_win_payload(tsd, (st->r_win_base + st->get_snd_wnd() -
-                        st->r_nxt_ack));
+                st->normalizer.trim_win_payload(
+                    tsd, (st->r_win_base + st->get_snd_wnd() - st->r_nxt_ack));
 
                 if (st->get_mss())
-                    st->normalizer->trim_mss_payload(tsd, st->get_mss());
+                    st->normalizer.trim_mss_payload(tsd, st->get_mss());
 
-                st->normalizer->ecn_stripper(tsd.get_pkt());
+                st->normalizer.ecn_stripper(tsd.get_pkt());
             }
         }
 
@@ -816,11 +803,11 @@ void TcpSession::handle_data_segment(TcpSegmentDescriptor& tsd)
         else
         {
             tel.set_tcp_event(EVENT_DATA_WITHOUT_FLAGS);
-            listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+            listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
         }
     }
 
-    listener->reassembler->flush_on_data_policy(tsd.get_pkt());
+    listener->reassembler.flush_on_data_policy(tsd.get_pkt());
 }
 
 TcpStreamTracker::TcpState TcpSession::get_talker_state()
@@ -838,14 +825,14 @@ void TcpSession::check_for_repeated_syn(TcpSegmentDescriptor& tsd)
     uint32_t action = ACTION_NOTHING;
 
     if ( !SEQ_EQ(tsd.get_seg_seq(), talker->get_iss()) and
-        listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK) )
+        listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK) )
     {
         action = ACTION_BAD_PKT;
     }
     else if ( talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED and
         talker->get_tcp_state() < TcpStreamTracker::TCP_CLOSED )
     {
-        action = listener->normalizer->handle_repeated_syn(tsd);
+        action = listener->normalizer.handle_repeated_syn(tsd);
     }
     if (action != ACTION_NOTHING)
     {
@@ -860,7 +847,7 @@ void TcpSession::flush_server(Packet* p)
     if ( !tcp_init )
         return;
 
-    server->set_tf_flags(TF_FORCE_FLUSH);
+    server.set_tf_flags(TF_FORCE_FLUSH);
 
     // If rebuilt packet, don't flush now because we'll overwrite the packet being processed.
     if ( p->packet_flags & PKT_REBUILT_STREAM )
@@ -870,10 +857,10 @@ void TcpSession::flush_server(Packet* p)
     }
 
     // Need to convert the addresses to network order
-    if ( server->reassembler->flush_stream(p, PKT_FROM_SERVER) )
-        server->reassembler->purge_flushed_ackd( );
+    if ( server.reassembler.flush_stream(p, PKT_FROM_SERVER) )
+        server.reassembler.purge_flushed_ackd();
 
-    server->clear_tf_flags(TF_FORCE_FLUSH);
+    server.clear_tf_flags(TF_FORCE_FLUSH);
 }
 
 void TcpSession::flush_client(Packet* p)
@@ -881,7 +868,7 @@ void TcpSession::flush_client(Packet* p)
     if ( !tcp_init )
         return;
 
-    client->set_tf_flags(TF_FORCE_FLUSH);
+    client.set_tf_flags(TF_FORCE_FLUSH);
 
     // If rebuilt packet, don't flush now because we'll overwrite the packet being processed.
     if ( p->packet_flags & PKT_REBUILT_STREAM )
@@ -890,25 +877,25 @@ void TcpSession::flush_client(Packet* p)
         return;
     }
 
-    if ( client->reassembler->flush_stream(p, PKT_FROM_CLIENT) )
-        client->reassembler->purge_flushed_ackd( );
+    if ( client.reassembler.flush_stream(p, PKT_FROM_CLIENT) )
+        client.reassembler.purge_flushed_ackd();
 
-    client->clear_tf_flags(TF_FORCE_FLUSH);
+    client.clear_tf_flags(TF_FORCE_FLUSH);
 }
 
 void TcpSession::flush_tracker(
-    TcpStreamTracker* tracker, Packet* p, uint32_t dir, bool final_flush)
+    TcpStreamTracker& tracker, Packet* p, uint32_t dir, bool final_flush)
 {
-    if ( final_flush && ( !tracker->splitter || !tracker->splitter->finish(flow) ) )
+    if ( final_flush && ( !tracker.splitter || !tracker.splitter->finish(flow) ) )
          return;
 
      DebugFormat(DEBUG_STREAM_STATE, "Flushing tracker on packet from %s\n",
              (dir == PKT_FROM_CLIENT) ? "client" : "server");
-     tracker->set_tf_flags(TF_FORCE_FLUSH);
-     if ( tracker->reassembler->flush_stream(p, dir) )
-         tracker->reassembler->purge_flushed_ackd( );
+     tracker.set_tf_flags(TF_FORCE_FLUSH);
+     if ( tracker.reassembler.flush_stream(p, dir) )
+         tracker.reassembler.purge_flushed_ackd();
 
-     tracker->clear_tf_flags(TF_FORCE_FLUSH);
+     tracker.clear_tf_flags(TF_FORCE_FLUSH);
 }
 
 void TcpSession::flush_listener(Packet* p, bool final_flush)
@@ -931,14 +918,8 @@ void TcpSession::flush_talker(Packet* p, bool final_flush)
 
 void TcpSession::set_extra_data(Packet* p, uint32_t xid)
 {
-    TcpStreamTracker* st;
-
-    if (p->ptrs.ip_api.get_src()->equals(flow->client_ip))
-        st = server;
-    else
-        st = client;
-
-    st->reassembler->set_xtradata_mask(st->reassembler->get_xtradata_mask() | BIT(xid) );
+    TcpStreamTracker& st = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ? server : client;
+    st.reassembler.set_xtradata_mask(st.reassembler.get_xtradata_mask() | BIT(xid));
 }
 
 static inline void set_window_scale(TcpStreamTracker& talker, TcpStreamTracker& listener,
@@ -996,8 +977,8 @@ bool TcpSession::is_flow_handling_packets(Packet* p)
     // harmonize this with that and the checks above
     if ( Stream::expected_flow(flow, p) )
     {
-        server->flush_policy = STREAM_FLPOLICY_IGNORE;
-        client->flush_policy = STREAM_FLPOLICY_IGNORE;
+        server.flush_policy = STREAM_FLPOLICY_IGNORE;
+        client.flush_policy = STREAM_FLPOLICY_IGNORE;
         flow_ready = false;
     }
 
@@ -1035,11 +1016,11 @@ bool TcpSession::do_packet_analysis_pre_checks(Packet* p, TcpSegmentDescriptor&
 
     if ( !splitter_init and tsd.get_seg_len() > 0 )
     {
-        client->set_splitter(tsd.get_flow());
-        server->set_splitter(tsd.get_flow());
+        client.set_splitter(tsd.get_flow());
+        server.set_splitter(tsd.get_flow());
 
-        client->init_flush_policy();
-        server->init_flush_policy();
+        client.init_flush_policy();
+        server.init_flush_policy();
 
         splitter_init = true;
     }
@@ -1072,7 +1053,7 @@ bool TcpSession::do_packet_analysis_pre_checks(Packet* p, TcpSegmentDescriptor&
 
 bool TcpSession::validate_packet_established_session(TcpSegmentDescriptor& tsd)
 {
-    pkt_action_mask |= listener->normalizer->handle_paws(tsd);
+    pkt_action_mask |= listener->normalizer.handle_paws(tsd);
 
     if ( pkt_action_mask & ACTION_BAD_PKT )
         return false;
@@ -1153,14 +1134,14 @@ int TcpSession::process(Packet* p)
 
 void TcpSession::flush()
 {
-    if ( ( server->reassembler->is_segment_pending_flush() ) ||
-        (client->reassembler->is_segment_pending_flush() ) )
+    if ( ( server.reassembler.is_segment_pending_flush() ) ||
+        (client.reassembler.is_segment_pending_flush() ) )
     {
        // FIXIT-L flush_queued_segments is basically a noop when the 'clear' parameter
        //         is passed in as false... review what happens in 2.9.x probably related
        //         to ssl encryption support
-        server->reassembler->flush_queued_segments(flow, false);
-        client->reassembler->flush_queued_segments(flow, false);
+        server.reassembler.flush_queued_segments(flow, false);
+        client.reassembler.flush_queued_segments(flow, false);
     }
 }
 
index 874a3e23d376b2a2af094556a02f6cad178995f5..bf43f5b0a8d001e2d69e77d0a5b6211f167ba263 100644 (file)
 #ifndef TCP_SESSION_H
 #define TCP_SESSION_H
 
-#include "stream/libtcp/tcp_stream_session.h"
 #include "stream/libtcp/tcp_state_machine.h"
-#include "stream/tcp/tcp_tracker.h"
+#include "stream/libtcp/tcp_stream_session.h"
+#include "stream/libtcp/tcp_stream_tracker.h"
 
+namespace snort
+{
+class Flow;
+struct Packet;
+}
 class TcpEventLogger;
 
+
 class TcpSession : public TcpStreamSession
 {
 public:
@@ -42,11 +48,8 @@ public:
     void flush_server(snort::Packet*) override;
     void flush_talker(snort::Packet*, bool final_flush = false) override;
     void flush_listener(snort::Packet*, bool final_flush = false) override;
-
     void clear_session(bool free_flow_data, bool flush_segments, bool restart, snort::Packet* p = nullptr) override;
-
     void set_extra_data(snort::Packet*, uint32_t /*flag*/) override;
-
     void update_perf_base_state(char new_state) override;
     TcpStreamTracker::TcpState get_talker_state() override;
     TcpStreamTracker::TcpState get_listener_state() override;
@@ -61,7 +64,6 @@ public:
     bool check_for_window_slam(TcpSegmentDescriptor& tsd) override;
     void mark_packet_for_drop(TcpSegmentDescriptor&) override;
     void handle_data_segment(TcpSegmentDescriptor&) override;
-
     bool validate_packet_established_session(TcpSegmentDescriptor&) override;
 
 private:
@@ -79,8 +81,9 @@ private:
     void cleanup_session_if_expired(snort::Packet*);
     bool do_packet_analysis_pre_checks(snort::Packet*, TcpSegmentDescriptor&);
     void do_packet_analysis_post_checks(snort::Packet*);
-    void flush_tracker(TcpStreamTracker*, snort::Packet*, uint32_t dir, bool final_flush);
+    void flush_tracker(TcpStreamTracker&, snort::Packet*, uint32_t dir, bool final_flush);
 
+private:
     TcpStateMachine* tsm;
     bool splitter_init;
 };
index 9a871c8adb362b09e0a1fd7d4e7d53107e2f0bda..79b31a5f2059b3719be6fa14ca2b0380e3882df3 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "main/snort_debug.h"
 
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
 #include "tcp_session.h"
 
 #ifdef UNIT_TEST
@@ -43,7 +43,7 @@ TcpStateCloseWait::TcpStateCloseWait(TcpStateMachine& tsm) :
 
 bool TcpStateCloseWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
 
     if ( tsd.get_seg_len() )
         trk.session->handle_data_on_syn(tsd);
@@ -98,7 +98,7 @@ bool TcpStateCloseWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tr
     {
         DebugMessage(DEBUG_STREAM_STATE, "FIN beyond previous, ignoring\n");
         trk.session->tel.set_tcp_event(EVENT_BAD_FIN);
-        trk.normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+        trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
         trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
     }
     else
index d4e670a9075d6ec9fcbf6785ae4b36d91fa6189e..8cf517a1951fe262b4f5c41ad25090e1ca012b77 100644 (file)
@@ -164,8 +164,8 @@ TEST_CASE("TCP State Closed", "[tcp_closed_state][stream_tcp]")
     TcpSession* session = new TcpSession(flow);
     TcpStateMachine* tsm =  new TcpStateMachine;
     TcpStateHandler* tsh = new TcpStateClosed(*tsm, *session);
-    ctrk->normalizer = TcpNormalizerFactory::create(session, StreamPolicy::OS_LINUX, ctrk, strk);
-    strk->normalizer = TcpNormalizerFactory::create(session, StreamPolicy::OS_LINUX, strk, ctrk);
+    ctrk->normalizer = TcpNormalizerFactory::create(StreamPolicy::OS_LINUX, session, ctrk, strk);
+    strk->normalizer = TcpNormalizerFactory::create(StreamPolicy::OS_LINUX, session, strk, ctrk);
     ctrk->reassembler = TcpReassemblerFactory::create(session, ctrk, StreamPolicy::OS_LINUX,
         false);
     strk->reassembler = TcpReassemblerFactory::create(session, strk, StreamPolicy::OS_LINUX, true);
index 6229c922b5e0cd2bd087aabe5184bf4782a222bb..46506aefe20447e40146d41b051486310f85b402 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "main/snort_debug.h"
 
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
 #include "tcp_session.h"
 
 #ifdef UNIT_TEST
@@ -49,7 +49,7 @@ bool TcpStateClosing::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateClosing::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
     if ( tsd.get_seg_len() )
         trk.session->handle_data_on_syn(tsd);
     return true;
@@ -98,7 +98,7 @@ bool TcpStateClosing::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
     {
         DebugMessage(DEBUG_STREAM_STATE, "FIN beyond previous, ignoring\n");
         trk.session->tel.set_tcp_event(EVENT_BAD_FIN);
-        trk.normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+        trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
         trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
     }
 
index 2898155b6b02014e1f84c751ecbb079a555ac07a..27185ccd7712cf1a59b7b99e3656f7d8f7001ac8 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "tcp_state_established.h"
 
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
 #include "tcp_session.h"
 
 TcpStateEstablished::TcpStateEstablished(TcpStateMachine& tsm) :
@@ -42,7 +42,7 @@ bool TcpStateEstablished::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 bool TcpStateEstablished::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.session->check_for_repeated_syn(tsd);
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
     return true;
 }
 
@@ -59,7 +59,7 @@ bool TcpStateEstablished::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTrack
     }
 
     if ( trk.is_server_tracker() )
-        trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+        trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
 
     return true;
 }
@@ -91,16 +91,13 @@ bool TcpStateEstablished::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTrac
 
 bool TcpStateEstablished::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    TcpStreamTracker* listener = nullptr;
+    TcpStreamTracker& listener =
+        tsd.get_pkt()->is_from_client() ? trk.session->server : trk.session->client;
 
-    if ( tsd.get_pkt()->is_from_client() )
-        listener = trk.session->server;
-    else
-        listener = trk.session->client;
     trk.update_on_fin_sent(tsd);
 
-    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) )
+    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);
index 1ef5b52a95fe4702582e9e73626c58f7c82af039..bae4b73f628bac4ae3a2604d73b8500511da7b0c 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "main/snort_debug.h"
 
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
 #include "tcp_module.h"
 #include "tcp_session.h"
 
@@ -46,7 +46,7 @@ bool TcpStateFinWait1::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
 
 bool TcpStateFinWait1::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
     if ( tsd.get_seg_len() )
         trk.session->handle_data_on_syn(tsd);
     return true;
@@ -147,13 +147,13 @@ bool TcpStateFinWait1::check_for_window_slam(TcpSegmentDescriptor& tsd, TcpStrea
 
     if ( SEQ_EQ(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
     {
-        if ( (trk.normalizer->get_os_policy() == StreamPolicy::OS_WINDOWS)
+        if ( (trk.normalizer.get_os_policy() == StreamPolicy::OS_WINDOWS)
             && (tsd.get_seg_wnd() == 0))
         {
             trk.session->tel.set_tcp_event(EVENT_WINDOW_SLAM);
             inc_tcp_discards();
 
-            if (trk.normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
+            if (trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK))
             {
                 trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
                 return false;
index 9672a22591d27ded1323e1107ea846e38290c764..5706426fcbd908cf64f4b2f4578b26236786d091 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "tcp_state_fin_wait2.h"
 
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
 #include "tcp_session.h"
 
 using namespace std;
@@ -43,7 +43,7 @@ bool TcpStateFinWait2::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
 
 bool TcpStateFinWait2::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
     if ( tsd.get_seg_len() )
         trk.session->handle_data_on_syn(tsd);
     return true;
@@ -66,7 +66,7 @@ bool TcpStateFinWait2::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
 {
     if ( SEQ_GT(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
     {
-        trk.normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+        trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
         trk.session->tel.set_tcp_event(EVENT_BAD_ACK);
         trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
     }
@@ -88,7 +88,7 @@ bool TcpStateFinWait2::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker
 {
     if ( SEQ_GT(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
     {
-        trk.normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+        trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
         trk.session->tel.set_tcp_event(EVENT_BAD_ACK);
         trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
     }
index 924c35299a857f023cbe4c6fbe58de4e51867983..97547ff3ba8c3cbff5b31833e3ad2aee03fa7ff2 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "tcp_state_last_ack.h"
 
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
 #include "tcp_session.h"
 
 using namespace std;
@@ -43,7 +43,7 @@ bool TcpStateLastAck::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateLastAck::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
     if ( tsd.get_seg_len() )
         trk.session->handle_data_on_syn(tsd);
     return true;
index c5bf0229fa8c50774aaaaade9f778a51a1424b5f..d6c58aa76d2b7ef683a19260251e505934f92dce 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "tcp_state_listen.h"
 
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
 #include "tcp_session.h"
 
 using namespace snort;
@@ -49,8 +49,8 @@ bool TcpStateListen::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 bool TcpStateListen::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.init_on_syn_recv(tsd);
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
-    trk.session->set_pkt_action_flag(trk.normalizer->handle_paws(tsd) );
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
+    trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd) );
     if ( tsd.get_seg_len() > 0 )
         trk.session->handle_data_on_syn(tsd);
     return true;
@@ -64,7 +64,7 @@ bool TcpStateListen::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& t
     if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
     {
         trk.init_on_synack_sent(tsd);
-        trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+        trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
         trk.session->init_new_tcp_session(tsd);
     }
     else if ( trk.session->config->require_3whs() )
@@ -125,7 +125,8 @@ bool TcpStateListen::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         if ( !tsd.get_tcph()->is_rst() && ( flow->session_state & STREAM_STATE_SYN_ACK ) )
         {
             trk.init_on_3whs_ack_recv(tsd);
-            trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+            trk.normalizer.ecn_tracker(
+                tsd.get_tcph(), trk.session->config->require_3whs());
         }
     }
     else if ( trk.session->config->require_3whs() )
@@ -168,7 +169,7 @@ bool TcpStateListen::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
         flow->session_state |= STREAM_STATE_MIDSTREAM;
         flow->set_session_flags(SSNFLAG_MIDSTREAM);
         trk.init_on_data_seg_recv(tsd);
-        trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+        trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
         trk.session->handle_data_segment(tsd);
     }
     else if ( trk.session->config->require_3whs() )
@@ -207,7 +208,7 @@ bool TcpStateListen::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateListen::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    trk.normalizer->trim_rst_payload(tsd);
+    trk.normalizer.trim_rst_payload(tsd);
     return true;
 }
 
index a17884b5e2a2cb2183b713cb9ea53dbdd5aede8f..382933a20c14f0110a1849b135e6dce65c365c17 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "tcp_state_none.h"
 
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
 #include "tcp_session.h"
 
 using namespace snort;
@@ -62,7 +62,7 @@ bool TcpStateNone::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
         flow->session_state |= ( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK );
         trk.init_on_synack_sent(tsd);
         trk.session->init_new_tcp_session(tsd);
-        trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+        trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
     }
     else if ( trk.session->config->require_3whs() )
     {
@@ -77,7 +77,7 @@ bool TcpStateNone::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
     if ( trk.session->config->midstream_allowed(tsd.get_pkt() ) )
     {
         trk.init_on_synack_recv(tsd);
-        trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+        trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
         if ( tsd.get_seg_len() > 0 )
             trk.session->handle_data_segment(tsd);
     }
@@ -122,7 +122,8 @@ bool TcpStateNone::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         if ( !tsd.get_tcph()->is_rst() && ( flow->session_state & STREAM_STATE_SYN_ACK ) )
         {
             trk.init_on_3whs_ack_recv(tsd);
-            trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+            trk.normalizer.ecn_tracker(
+                tsd.get_tcph(), trk.session->config->require_3whs());
         }
     }
     else if ( trk.session->config->require_3whs() )
@@ -166,7 +167,7 @@ bool TcpStateNone::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tr
         flow->set_session_flags(SSNFLAG_MIDSTREAM);
 
         trk.init_on_data_seg_recv(tsd);
-        trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+        trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
         trk.session->handle_data_segment(tsd);
     }
     else if ( trk.session->config->require_3whs() )
@@ -243,8 +244,9 @@ TEST_CASE("TCP State None", "[tcp_none_state][stream_tcp]")
     TcpSession* session = new TcpSession(flow);
     TcpStateMachine* tsm =  new TcpStateMachine;
     TcpStateHandler* tsh = new TcpStateNone(*tsm, *session);
-    ctrk->normalizer = TcpNormalizerFactory::create(session, StreamPolicy::OS_LINUX, ctrk, strk);
-    strk->normalizer = TcpNormalizerFactory::create(session, StreamPolicy::OS_LINUX, strk, ctrk);
+
+    ctrk->normalizer = TcpNormalizerFactory::create(StreamPolicy::OS_LINUX, session, ctrk, strk);
+    strk->normalizer = TcpNormalizerFactory::create(StreamPolicy::OS_LINUX, session, strk, ctrk);
     ctrk->reassembler = TcpReassemblerFactory::create(session, ctrk, StreamPolicy::OS_LINUX,
         false);
     strk->reassembler = TcpReassemblerFactory::create(session, strk, StreamPolicy::OS_LINUX, true);
index 30a9ed355ce087f16b049a129f4f9a636bf50a7c..289d3cdac03b9c2c39dfd0248a6f75c737b45979 100644 (file)
@@ -26,7 +26,7 @@
 #include "tcp_state_syn_recv.h"
 
 #include "tcp_module.h"
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
 #include "tcp_session.h"
 
 using namespace snort;
@@ -42,7 +42,7 @@ bool TcpStateSynRecv::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
     Flow* flow = tsd.get_flow();
 
     trk.finish_server_init(tsd);
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
     trk.session->update_timestamp_tracking(tsd);
     if ( tsd.get_tcph()->are_flags_set(TH_ECE) &&
         ( flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY ) )
@@ -69,7 +69,7 @@ bool TcpStateSynRecv::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 
     // FIXIT-H verify ack being sent is valid...
     trk.finish_server_init(tsd);
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
     flow->session_state |= STREAM_STATE_SYN_ACK;
     return true;
 }
@@ -81,7 +81,7 @@ bool TcpStateSynRecv::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
         Flow* flow = tsd.get_flow();
 
         trk.update_tracker_ack_recv(tsd);
-        trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+        trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
         flow->set_session_flags(SSNFLAG_ESTABLISHED);
         flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
@@ -108,7 +108,7 @@ bool TcpStateSynRecv::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         Flow* flow = tsd.get_flow();
 
         trk.update_tracker_ack_recv(tsd);
-        trk.session->set_pkt_action_flag(trk.normalizer->handle_paws(tsd) );
+        trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
         tsd.get_pkt()->packet_flags |= PKT_STREAM_TWH;
         flow->set_session_flags(SSNFLAG_ESTABLISHED);
         flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
@@ -128,7 +128,7 @@ bool TcpStateSynRecv::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
     {
         trk.update_tracker_ack_recv(tsd);
         tsd.get_pkt()->packet_flags |= PKT_STREAM_TWH;
-        trk.session->set_pkt_action_flag(trk.normalizer->handle_paws(tsd) );
+        trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
         trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
     }
@@ -144,7 +144,7 @@ bool TcpStateSynRecv::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         Flow* flow = tsd.get_flow();
 
         trk.update_tracker_ack_recv(tsd);
-        trk.session->set_pkt_action_flag(trk.normalizer->handle_paws(tsd) );
+        trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
         flow->session_state |= STREAM_STATE_ACK;
         if ( tsd.get_seg_len() > 0 )
         {
@@ -163,20 +163,20 @@ bool TcpStateSynRecv::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateSynRecv::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    trk.normalizer->trim_rst_payload(tsd);
-    if ( trk.normalizer->validate_rst(tsd) )
+    trk.normalizer.trim_rst_payload(tsd);
+    if ( trk.normalizer.validate_rst(tsd) )
     {
         Flow* flow = tsd.get_flow();
 
         flow->set_session_flags(SSNFLAG_RESET);
-        if ( trk.normalizer->is_tcp_ips_enabled() )
+        if ( trk.normalizer.is_tcp_ips_enabled() )
             tcp_state = TcpStreamTracker::TCP_LISTEN;
     }
     else
     {
         DebugMessage(DEBUG_STREAM_STATE, "Received RST with bad sequence number\n");
         inc_tcp_discards();
-        trk.normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+        trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
         trk.session->tel.set_tcp_event(EVENT_BAD_RST);
     }
 
index b7c66b50287de7100f962cc4eb7aaca4f2e5c5f8..1abf966b0921c33dbc8525ad66da4088585e4aa7 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "main/snort_debug.h"
 
-#include "tcp_normalizer.h"
+#include "tcp_normalizers.h"
 #include "tcp_session.h"
 
 using namespace std;
@@ -45,7 +45,7 @@ bool TcpStateTimeWait::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
 
 bool TcpStateTimeWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs() );
+    trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->config->require_3whs());
     if ( tsd.get_seg_len() )
         trk.session->handle_data_on_syn(tsd);
 
@@ -73,7 +73,7 @@ bool TcpStateTimeWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
     {
         DebugMessage(DEBUG_STREAM_STATE, "FIN beyond previous, ignoring\n");
         trk.session->tel.set_tcp_event(EVENT_BAD_FIN);
-        trk.normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+        trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
         trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
     }
     else if ( tsd.get_seg_len() > 0 )
index 45752852fd4135b958032157a5d9e328191c1daf..8bd98b2ab58b1001c261539acf32c843d7e468c2 100644 (file)
@@ -35,7 +35,6 @@ public:
 
 private:
     TcpStreamStateMachine();
-    void initialize_tsm();
 
 };
 #endif
diff --git a/src/stream/tcp/tcp_tracker.cc b/src/stream/tcp/tcp_tracker.cc
deleted file mode 100644 (file)
index 4ba33c9..0000000
+++ /dev/null
@@ -1,606 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2015-2018 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// tcp_tracker.cc author davis mcpherson <davmcphe@@cisco.com>
-// Created on: Dec 1, 2015
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "tcp_tracker.h"
-
-#include "log/messages.h"
-#include "profiler/profiler_defs.h"
-
-#include "tcp_module.h"
-#include "tcp_normalizer.h"
-#include "tcp_reassembler.h"
-
-using namespace snort;
-
-TcpTracker::TcpTracker(bool client, TcpSession* ssn) :
-    TcpStreamTracker(client)
-{
-    session = ssn;
-}
-
-TcpTracker::~TcpTracker()
-{
-    delete splitter;
-    delete normalizer;
-    delete reassembler;
-}
-
-void TcpTracker::init_tcp_state( )
-{
-    tcp_state = ( client_tracker ) ?
-        TcpStreamTracker::TCP_STATE_NONE : TcpStreamTracker::TCP_LISTEN;
-    flush_policy = STREAM_FLPOLICY_IGNORE;
-    memset(&paf_state, 0, sizeof(paf_state));
-    snd_una = snd_nxt = snd_wnd = 0;
-    r_nxt_ack = r_win_base = iss = ts_last = ts_last_packet = 0;
-    small_seg_count = wscale = mss = 0;
-    tf_flags = 0;
-    alert_count = 0;
-    mac_addr_valid = false;
-    fin_final_seq = 0;
-    fin_seq_status = TcpStreamTracker::FIN_NOT_SEEN;
-    fin_seq_set = false;
-    rst_pkt_sent = false;
-}
-
-void TcpTracker::init_toolbox()
-{
-    delete splitter;
-    splitter = nullptr;
-    delete normalizer;
-    normalizer =  nullptr;
-    delete reassembler;
-    reassembler = nullptr;
-}
-
-//-------------------------------------------------------------------------
-// flush policy stuff
-//-------------------------------------------------------------------------
-
-void TcpTracker::init_flush_policy()
-{
-    if ( splitter == nullptr )
-        flush_policy = STREAM_FLPOLICY_IGNORE;
-    else if ( normalizer->is_tcp_ips_enabled() )
-        flush_policy = STREAM_FLPOLICY_ON_DATA;
-    else
-        flush_policy = STREAM_FLPOLICY_ON_ACK;
-}
-
-void TcpTracker::set_splitter(StreamSplitter* ss)
-{
-    if ( splitter )
-        delete splitter;
-
-    splitter = ss;
-
-    if ( ss )
-        paf_setup(&paf_state);
-    else
-        flush_policy = STREAM_FLPOLICY_IGNORE;
-}
-
-void TcpTracker::set_splitter(const Flow* flow)
-{
-    Inspector* ins = flow->gadget;
-
-    if ( !ins )
-        ins = flow->clouseau;
-
-    if ( ins )
-        set_splitter(ins->get_splitter(!client_tracker) );
-    else
-        set_splitter(new AtomSplitter(!client_tracker) );
-}
-
-void TcpTracker::reset_splitter( )
-{
-    if ( splitter )
-        splitter->reset();
-}
-
-void TcpTracker::init_on_syn_sent(TcpSegmentDescriptor& tsd)
-{
-    Profile profile(s5TcpNewSessPerfStats);
-
-    tsd.get_flow()->set_session_flags(SSNFLAG_SEEN_CLIENT);
-    if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
-        tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
-
-    iss = tsd.get_seg_seq();
-    snd_una = iss;
-    snd_nxt = tsd.get_end_seq();
-    snd_wnd =  tsd.get_seg_wnd();
-
-    ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
-    tf_flags |= normalizer->get_tcp_timestamp(tsd, false);
-    ts_last = tsd.get_ts();
-    if (ts_last == 0)
-        tf_flags |= TF_TSTAMP_ZERO;
-    tf_flags |= tsd.init_mss(&mss);
-    tf_flags |= tsd.init_wscale(&wscale);
-
-    cache_mac_address(tsd, FROM_CLIENT);
-    tcp_state = TcpStreamTracker::TCP_SYN_SENT;
-    tcpStats.sessions_on_syn++;
-}
-
-void TcpTracker::init_on_syn_recv(TcpSegmentDescriptor& tsd)
-{
-    Profile profile(s5TcpNewSessPerfStats);
-
-    irs = tsd.get_seg_seq();
-    // FIXIT-H can we really set the vars below now?
-    r_nxt_ack = tsd.get_seg_seq() + 1;
-    r_win_base = tsd.get_seg_seq() + 1;
-    reassembler->set_seglist_base_seq(tsd.get_seg_seq() + 1);
-
-    cache_mac_address(tsd, FROM_CLIENT);
-    tcp_state = TcpStreamTracker::TCP_SYN_RECV;
-}
-
-void TcpTracker::init_on_synack_sent(TcpSegmentDescriptor& tsd)
-{
-    Profile profile(s5TcpNewSessPerfStats);
-
-    DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on SYN_ACK!\n");
-
-    tsd.get_flow()->set_session_flags(SSNFLAG_SEEN_SERVER);
-    if (tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE))
-        tsd.get_flow()->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
-
-    iss = tsd.get_seg_seq();
-    irs = tsd.get_seg_ack() - 1;
-    snd_una = tsd.get_seg_seq();
-    snd_nxt = tsd.get_end_seq();
-    snd_wnd = tsd.get_seg_wnd();
-
-    r_win_base = tsd.get_seg_ack();
-    r_nxt_ack = tsd.get_seg_ack();
-    reassembler->set_seglist_base_seq(tsd.get_seg_ack() );
-
-    ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
-    tf_flags |= normalizer->get_tcp_timestamp(tsd, false);
-    ts_last = tsd.get_ts();
-    if ( ts_last == 0 )
-        tf_flags |= TF_TSTAMP_ZERO;
-    tf_flags |= tsd.init_mss(&mss);
-    tf_flags |= tsd.init_wscale(&wscale);
-
-    cache_mac_address(tsd, FROM_SERVER);
-    tcp_state = TcpStreamTracker::TCP_SYN_RECV;
-    tcpStats.sessions_on_syn_ack++;
-}
-
-void TcpTracker::init_on_synack_recv(TcpSegmentDescriptor& tsd)
-{
-    Profile profile(s5TcpNewSessPerfStats);
-
-    iss = tsd.get_seg_ack() - 1;
-    irs = tsd.get_seg_seq();
-    snd_una = tsd.get_seg_ack();
-    snd_nxt = snd_una;
-
-    r_nxt_ack = tsd.get_seg_seq() + 1;
-    r_win_base = tsd.get_seg_seq() + 1;
-    reassembler->set_seglist_base_seq(tsd.get_seg_seq() + 1);
-
-    cache_mac_address(tsd, FROM_SERVER);
-    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
-}
-
-void TcpTracker::init_on_3whs_ack_sent(TcpSegmentDescriptor& tsd)
-{
-    Profile profile(s5TcpNewSessPerfStats);
-
-    tsd.get_flow()->set_session_flags(SSNFLAG_SEEN_CLIENT);
-
-    if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
-        tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
-
-    iss = tsd.get_seg_seq();
-    snd_una = tsd.get_seg_seq();
-    snd_nxt = snd_una;
-    snd_wnd = tsd.get_seg_wnd();
-
-    r_win_base = tsd.get_seg_ack();
-    r_nxt_ack = tsd.get_seg_ack();
-
-    ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
-    tf_flags |= normalizer->get_tcp_timestamp(tsd, false);
-    ts_last = tsd.get_ts();
-    if (ts_last == 0)
-        tf_flags |= TF_TSTAMP_ZERO;
-    tf_flags |= tsd.init_mss(&mss);
-    tf_flags |= tsd.init_wscale(&wscale);
-
-    cache_mac_address(tsd, FROM_CLIENT);
-    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
-}
-
-void TcpTracker::init_on_3whs_ack_recv(TcpSegmentDescriptor& tsd)
-{
-    Profile profile(s5TcpNewSessPerfStats);
-
-    iss = tsd.get_seg_ack() - 1;
-    irs = tsd.get_seg_seq();
-    snd_una = tsd.get_seg_ack();
-    snd_nxt = snd_una;
-
-    r_nxt_ack = tsd.get_seg_seq();
-    r_win_base = tsd.get_seg_seq();
-    reassembler->set_seglist_base_seq(tsd.get_seg_seq() + 1);
-
-    cache_mac_address(tsd, FROM_CLIENT);
-    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
-    tcpStats.sessions_on_3way++;
-}
-
-void TcpTracker::init_on_data_seg_sent(TcpSegmentDescriptor& tsd)
-{
-    Profile profile(s5TcpNewSessPerfStats);
-
-    Flow* flow = tsd.get_flow();
-
-    if ( flow->ssn_state.direction == FROM_CLIENT )
-        flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
-    else
-        flow->set_session_flags(SSNFLAG_SEEN_SERVER);
-
-    // FIXIT-H should we init these?
-    iss = tsd.get_seg_seq();
-    irs = tsd.get_seg_ack();
-    snd_una = tsd.get_seg_seq();
-    snd_nxt = snd_una + tsd.get_seg_len();
-    snd_wnd = tsd.get_seg_wnd();
-
-    r_win_base = tsd.get_seg_ack();
-    r_nxt_ack = tsd.get_seg_ack();
-    reassembler->set_seglist_base_seq(tsd.get_seg_ack());
-
-    ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
-    tf_flags |= normalizer->get_tcp_timestamp(tsd, false);
-    ts_last = tsd.get_ts();
-    if (ts_last == 0)
-        tf_flags |= TF_TSTAMP_ZERO;
-    tf_flags |= ( tsd.init_mss(&mss) | tsd.init_wscale(&wscale) );
-
-    cache_mac_address(tsd, tsd.get_direction() );
-    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
-}
-
-void TcpTracker::init_on_data_seg_recv(TcpSegmentDescriptor& tsd)
-{
-    Profile profile(s5TcpNewSessPerfStats);
-
-    iss = tsd.get_seg_ack();
-    irs = tsd.get_seg_seq();
-    snd_una = tsd.get_seg_ack();
-    snd_nxt = snd_una;
-    snd_wnd = 0; /* reset later */
-
-    r_nxt_ack = tsd.get_seg_seq();
-    r_win_base = tsd.get_seg_seq();
-    reassembler->set_seglist_base_seq(tsd.get_seg_seq());
-
-    cache_mac_address(tsd, tsd.get_direction() );
-    tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
-    tcpStats.sessions_on_data++;
-}
-
-void TcpTracker::finish_server_init(TcpSegmentDescriptor& tsd)
-{
-    iss = tsd.get_seg_seq();
-    snd_una = tsd.get_seg_seq();
-    snd_nxt = tsd.get_end_seq();
-    snd_wnd = tsd.get_seg_wnd();
-
-    // FIXIT-H move this to fin handler for syn_recv state ..
-    //if ( tcph->is_fin() )
-    //    server->set_snd_nxt(server->get_snd_nxt() - 1);
-
-    tf_flags |= normalizer->get_tcp_timestamp(tsd, false);
-    ts_last = tsd.get_ts();
-    if ( ts_last != 0 )
-        ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
-    else
-        tf_flags |= TF_TSTAMP_ZERO;
-
-    tf_flags |= ( tsd.init_mss(&mss) | tsd.init_wscale(&wscale) );
-}
-
-void TcpTracker::finish_client_init(TcpSegmentDescriptor& tsd)
-{
-    Flow* flow = tsd.get_flow();
-
-    r_nxt_ack = tsd.get_end_seq();
-
-    if ( !( flow->session_state & STREAM_STATE_MIDSTREAM ) )
-    {
-        reassembler->set_seglist_base_seq(tsd.get_seg_seq() + 1);
-        r_win_base = tsd.get_end_seq();
-    }
-    else
-    {
-        reassembler->set_seglist_base_seq(tsd.get_seg_seq() );
-        r_win_base = tsd.get_seg_seq();
-    }
-}
-
-void TcpTracker::update_tracker_ack_recv(TcpSegmentDescriptor& tsd)
-{
-    if ( SEQ_GT(tsd.get_seg_ack(), snd_una) )
-    {
-        snd_una = tsd.get_seg_ack();
-        if ( snd_nxt < snd_una )
-            snd_nxt = snd_una;
-    }
-}
-
-void TcpTracker::update_tracker_ack_sent(TcpSegmentDescriptor& tsd)
-{
-    // ** this is how we track the last seq number sent
-    // as is l_unackd is the "last left" seq recvd
-    //snd_una = tsd.get_seg_seq();
-
-    // FIXIT-H add check to validate ack...
-
-    if ( SEQ_GT(tsd.get_end_seq(), snd_nxt) )
-        snd_nxt = tsd.get_end_seq();
-
-    if ( !SEQ_EQ(r_win_base, tsd.get_seg_ack() ) )
-        small_seg_count = 0;
-
-#ifdef S5_PEDANTIC
-    if ( SEQ_GT(tsd.get_seg_ack(), r_win_base) &&
-        SEQ_LEQ(tsd.get_seg_ack(), r_nxt_ack) )
-#else
-    if ( SEQ_GT(tsd.get_seg_ack(), r_win_base) )
-#endif
-        r_win_base = tsd.get_seg_ack();
-
-    if ( ( fin_seq_status == TcpStreamTracker::FIN_WITH_SEQ_SEEN )
-        && SEQ_EQ(r_win_base, fin_final_seq) )
-    {
-        fin_seq_status = TcpStreamTracker::FIN_WITH_SEQ_ACKED;
-    }
-
-    snd_wnd = tsd.get_seg_wnd();
-    reassembler->flush_on_ack_policy(tsd.get_pkt() );
-}
-
-bool TcpTracker::update_on_3whs_ack(TcpSegmentDescriptor& tsd)
-{
-    bool good_ack = true;
-
-    if ( is_ack_valid(tsd.get_seg_ack()) )
-    {
-        Flow* flow = tsd.get_flow();
-
-        irs = tsd.get_seg_seq();
-        finish_client_init(tsd);
-        update_tracker_ack_recv(tsd);
-        flow->set_session_flags(SSNFLAG_ESTABLISHED);
-        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
-        tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
-    }
-    else
-    {
-        DebugFormat(DEBUG_STREAM_STATE,
-            "Pkt Ack is Out of Bounds (%X, %X, %X) = (snd_una, snd_nxt, cur)\n",
-            snd_una, snd_nxt, tsd.get_seg_ack());
-        inc_tcp_discards();
-        normalizer->trim_win_payload(tsd);
-        good_ack = false;
-    }
-
-    return good_ack;
-}
-
-bool TcpTracker::update_on_rst_recv(TcpSegmentDescriptor& tsd)
-{
-    bool good_rst = true;
-
-    normalizer->trim_rst_payload(tsd);
-    if ( normalizer->validate_rst(tsd) )
-    {
-        Flow* flow = tsd.get_flow();
-
-        DebugMessage(DEBUG_STREAM_STATE, "Received Valid RST, bailing\n");
-        flow->set_session_flags(SSNFLAG_RESET);
-        if ( normalizer->is_tcp_ips_enabled() )
-            tcp_state = TcpStreamTracker::TCP_CLOSED;
-    }
-    else
-    {
-        DebugMessage(DEBUG_STREAM_STATE, "Received RST with bad sequence number, bailing\n");
-        inc_tcp_discards();
-        normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
-        good_rst = false;
-    }
-
-    return good_rst;
-}
-
-void TcpTracker::update_on_rst_sent()
-{
-    tcp_state = TcpStreamTracker::TCP_CLOSED;
-    rst_pkt_sent = true;
-}
-
-void TcpTracker::flush_data_on_fin_recv(TcpSegmentDescriptor& tsd)
-{
-    if ( (flush_policy != STREAM_FLPOLICY_ON_ACK)
-        && (flush_policy != STREAM_FLPOLICY_ON_DATA)
-        && normalizer->is_tcp_ips_enabled())
-    {
-        tsd.get_pkt()->packet_flags |= PKT_PDU_TAIL;
-    }
-
-    reassembler->flush_on_data_policy(tsd.get_pkt());
-}
-
-bool TcpTracker::update_on_fin_recv(TcpSegmentDescriptor& tsd)
-{
-    if ( SEQ_LT(tsd.get_end_seq(), r_win_base) )
-    {
-        DebugMessage(DEBUG_STREAM_STATE, "FIN inside r_win_base, bailing\n");
-        return false;
-    }
-
-    //--------------------------------------------------
-    // FIXIT-L don't bump r_nxt_ack unless FIN is in seq
-    // because it causes bogus 129:5 cases
-    // but doing so causes extra gaps
-    //if ( SEQ_EQ(tsd.end_seq, r_nxt_ack) )
-    r_nxt_ack++;
-
-    // set final seq # any packet rx'ed with seq > is bad
-    if ( !fin_seq_set )
-    {
-        fin_final_seq = tsd.get_end_seq();
-        fin_seq_set = true;
-        if( tsd.get_seg_len() == 0 )
-            fin_seq_status = TcpStreamTracker::FIN_WITH_SEQ_SEEN;
-    }
-
-    return true;
-}
-
-bool TcpTracker::update_on_fin_sent(TcpSegmentDescriptor& tsd)
-{
-    update_tracker_ack_sent(tsd);
-    snd_nxt++;
-    return true;
-}
-
-#ifdef S5_PEDANTIC
-// From RFC 793:
-//
-//    Segment Receive  Test
-//    Length  Window
-//    ------- -------  -------------------------------------------
-//
-//       0       0     SEG.SEQ = RCV.NXT
-//
-//       0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
-//
-//      >0       0     not acceptable
-//
-//      >0      >0     RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
-//                     or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
-//
-bool ValidSeq(const Packet* p, Flow* flow, TcpTracker* st, TcpSegmentDescriptor& tsd)
-{
-    uint32_t win = normalizer->get_stream_window(flow, st, tsd);
-
-    if ( !p->dsize )
-    {
-        if ( !win )
-        {
-            return ( tsd.get_seg_seq() == r_win_base );
-        }
-        return SEQ_LEQ(r_win_base, tsd.get_seg_seq()) &&
-               SEQ_LT(tsd.get_seg_seq(), r_win_base+win);
-    }
-    if ( !win )
-        return 0;
-
-    if ( SEQ_LEQ(r_win_base, tsd.get_seg_seq()) &&
-        SEQ_LT(tsd.get_seg_seq(), r_win_base+win) )
-        return 1;
-
-    return SEQ_LEQ(r_win_base, tsd.get_end_seq()) &&
-           SEQ_LT(tsd.get_end_seq(), r_win_base+win);
-}
-
-#endif
-
-bool TcpTracker::is_segment_seq_valid(TcpSegmentDescriptor& tsd)
-{
-    bool valid_seq = true;
-
-    int right_ok;
-    uint32_t left_seq;
-
-    DebugFormat(DEBUG_STREAM_STATE,
-        "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
-        tsd.get_end_seq(), r_win_base, tsd.get_seg_seq(),
-        r_nxt_ack + normalizer->get_stream_window(tsd));
-
-    if ( SEQ_LT(r_nxt_ack, r_win_base) )
-        left_seq = r_nxt_ack;
-    else
-        left_seq = r_win_base;
-
-    if ( tsd.get_seg_len() )
-        right_ok = SEQ_GT(tsd.get_end_seq(), left_seq);
-    else
-        right_ok = SEQ_GEQ(tsd.get_end_seq(), left_seq);
-
-    if ( right_ok )
-    {
-        uint32_t win = normalizer->get_stream_window(tsd);
-
-        if ( SEQ_LEQ(tsd.get_seg_seq(), r_win_base + win) )
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "seq is within window!\n");
-        }
-        else
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "seq is past the end of the window!\n");
-            valid_seq = false;
-        }
-    }
-    else
-    {
-        DebugMessage(DEBUG_STREAM_STATE, "end_seq is before win_base\n");
-        valid_seq = false;
-    }
-
-    if ( !valid_seq )
-    {
-        inc_tcp_discards();
-        normalizer->trim_win_payload(tsd);
-    }
-
-    return valid_seq;
-}
-
-void TcpTracker::print()
-{
-    LogMessage(" + TcpTracker +\n");
-    LogMessage("    state:              %s\n", tcp_state_names[ tcp_state ]);
-    LogMessage("    iss:                0x%X\n", iss);
-    LogMessage("    ts_last:            %u\n", ts_last);
-    LogMessage("    wscale:             %u\n", wscale);
-    LogMessage("    mss:                0x%08X\n", mss);
-    LogMessage("    snd_una:            %X\n", snd_una);
-    LogMessage("    snd_nxt:            %X\n", snd_nxt);
-    LogMessage("    snd_win:            %u\n", snd_wnd);
-    LogMessage("    rcv_nxt:            %X\n", rcv_nxt);
-    LogMessage("    r_win_base:         %X\n", r_win_base);
-}
-
diff --git a/src/stream/tcp/tcp_tracker.h b/src/stream/tcp/tcp_tracker.h
deleted file mode 100644 (file)
index ed39cc9..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2015-2018 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// tcp_tracker.h author davis mcpherson <davmcphe@@cisco.com>
-// Created on: Dec 1, 2015
-
-#ifndef TCP_TRACKER_H
-#define TCP_TRACKER_H
-
-#include "stream/libtcp/tcp_stream_tracker.h"
-
-//-------------------------------------------------------------------------
-// extra, extra - read all about it!
-// -- u2 is the only output plugin that currently supports extra data
-// -- extra data may be captured before or after alerts
-// -- extra data may be per packet or persistent (saved on session)
-//
-// -- per packet extra data is logged iff we alert on the packet
-//    containing the extra data - u2 drives this
-// -- an extra data mask is added to Packet to indicate when per packet
-//    extra data is available
-//
-// -- persistent extra data must be logged exactly once for each alert
-//    regardless of capture/alert ordering - s5 purge_alerts drives this
-// -- an extra data mask is added to the session trackers to indicate that
-//    persistent extra data is available
-//
-// -- event id and second are added to the session alert trackers so that
-//    the extra data can be correlated with events
-// -- event id and second are not available when check_alerted()
-//    is called; u2 calls StreamUpdateSessionAlertTcp as events are logged
-//    to set these fields
-//-------------------------------------------------------------------------
-
-class TcpTracker : public TcpStreamTracker
-{
-public:
-    TcpTracker(bool, class TcpSession*);
-    ~TcpTracker() override;
-
-    void init_tcp_state() override;
-    void print() override;
-    void init_flush_policy() override;
-    void set_splitter(snort::StreamSplitter* ss) override;
-    void set_splitter(const snort::Flow* flow) override;
-    void reset_splitter( ) override;
-
-    void init_on_syn_sent(TcpSegmentDescriptor&) override;
-    void init_on_syn_recv(TcpSegmentDescriptor&) override;
-    void init_on_synack_sent(TcpSegmentDescriptor&) override;
-    void init_on_synack_recv(TcpSegmentDescriptor&) override;
-    void init_on_3whs_ack_sent(TcpSegmentDescriptor&) override;
-    void init_on_3whs_ack_recv(TcpSegmentDescriptor&) override;
-    void init_on_data_seg_sent(TcpSegmentDescriptor&) override;
-    void init_on_data_seg_recv(TcpSegmentDescriptor&) override;
-    void finish_server_init(TcpSegmentDescriptor&) override;
-    void finish_client_init(TcpSegmentDescriptor&) override;
-
-    void update_tracker_ack_recv(TcpSegmentDescriptor&) override;
-    void update_tracker_ack_sent(TcpSegmentDescriptor&) override;
-    bool update_on_3whs_ack(TcpSegmentDescriptor&) override;
-    bool update_on_rst_recv(TcpSegmentDescriptor&) override;
-    void update_on_rst_sent() override;
-    bool update_on_fin_recv(TcpSegmentDescriptor&) override;
-    bool update_on_fin_sent(TcpSegmentDescriptor&) override;
-    bool is_segment_seq_valid(TcpSegmentDescriptor&) override;
-    void flush_data_on_fin_recv(TcpSegmentDescriptor&) override;
-
-    void init_toolbox() override;
-};
-
-#endif
-
index 2abbd45dc1769fa468571f31a6c69cfb5871e4ca..9fc4aba9ac1f9b5b738a2c7a5e21bd256464cf48 100644 (file)
@@ -122,14 +122,14 @@ TEST(tcp_normalizers, os_policy)
     StreamPolicy os_policy;
     Flow* flow = new FlowMock;
     TcpSession* session = new TcpSessionMock( flow );
+    TcpNormalizerState tns;
 
     for( os_policy = StreamPolicy::OS_FIRST; os_policy <= StreamPolicy::OS_PROXY; ++os_policy )
     {
-        TcpNormalizer* normalizer = TcpNormalizerFactory::create( session, os_policy,
-            session->client, session->server );
-        CHECK( normalizer->get_os_policy() == os_policy );
+        TcpNormalizer* normalizer = TcpNormalizerFactory::create(
+            tns, os_policy, session, session->client, session->server);
 
-        delete normalizer;
+        CHECK( normalizer.get_os_policy(tns) == os_policy );
     }
 
     delete flow;
@@ -141,24 +141,23 @@ TEST(tcp_normalizers, paws_fudge_config)
     StreamPolicy os_policy;
     Flow* flow = new FlowMock;
     TcpSession* session = new TcpSessionMock( flow );
+    TcpNormalizerState tns;
 
     for( os_policy = StreamPolicy::OS_FIRST; os_policy <= StreamPolicy::OS_PROXY; ++os_policy )
     {
-        TcpNormalizer* normalizer = TcpNormalizerFactory::create( session, os_policy,
-            session->client, session->server );
+        TcpNormalizer* normalizer = TcpNormalizerFactory::create(
+            tns, os_policy, session, session->client, session->server);
 
         switch ( os_policy )
         {
         case StreamPolicy::OS_LINUX:
-            CHECK( normalizer->get_paws_ts_fudge() == 1 );
+            CHECK( normalizer.get_paws_ts_fudge(tns) == 1 );
             break;
 
         default:
-            CHECK( normalizer->get_paws_ts_fudge() == 0 );
+            CHECK( normalizer.get_paws_ts_fudge(tns) == 0 );
             break;
         }
-
-        delete normalizer;
     }
 
     delete flow;
@@ -170,11 +169,12 @@ TEST(tcp_normalizers, paws_drop_zero_ts_config)
     StreamPolicy os_policy;
     Flow* flow = new FlowMock;
     TcpSession* session = new TcpSessionMock( flow );
+    TcpNormalizerState tns;
 
     for( os_policy = StreamPolicy::OS_FIRST; os_policy <= StreamPolicy::OS_PROXY; ++os_policy )
     {
-        TcpNormalizer* normalizer = TcpNormalizerFactory::create( session, os_policy,
-            session->client, session->server );
+        TcpNormalizer* normalizer = TcpNormalizerFactory::create(
+            tns, os_policy, session, session->client, session->server );
 
         switch ( os_policy )
         {
@@ -183,15 +183,13 @@ TEST(tcp_normalizers, paws_drop_zero_ts_config)
         case StreamPolicy::OS_WINDOWS:
         case StreamPolicy::OS_WINDOWS2K3:
         case StreamPolicy::OS_VISTA:
-            CHECK( !normalizer->is_paws_drop_zero_ts() );
+            CHECK( !normalizer.is_paws_drop_zero_ts(tns) );
             break;
 
         default:
-            CHECK( normalizer->is_paws_drop_zero_ts() );
+            CHECK( normalizer.is_paws_drop_zero_ts(tns) );
             break;
         }
-
-        delete normalizer;
     }
 
     delete flow;
@@ -207,36 +205,35 @@ TEST(tcp_normalizers, norm_options_enabled)
     norm_enabled = true;
     for( os_policy = StreamPolicy::OS_FIRST; os_policy <= StreamPolicy::OS_PROXY; ++os_policy )
     {
-        TcpNormalizer* normalizer = TcpNormalizerFactory::create( session, os_policy,
-            session->client, session->server );
-
-        CHECK( normalizer->get_opt_block() == NORM_MODE_ON );
-        CHECK( normalizer->get_strip_ecn() == NORM_MODE_ON );
-        CHECK( normalizer->get_tcp_block() == NORM_MODE_ON );
-        CHECK( normalizer->get_trim_syn() == NORM_MODE_ON );
-        CHECK( normalizer->get_trim_rst() == NORM_MODE_ON );
-        CHECK( normalizer->get_trim_mss() == NORM_MODE_ON );
-        CHECK( normalizer->get_trim_win() == NORM_MODE_ON );
-        CHECK( normalizer->is_tcp_ips_enabled() );
-
-        delete normalizer;
+        TcpNormalizerState tns;
+        TcpNormalizer* normalizer = TcpNormalizerFactory::create(
+            tns, os_policy, session, session->client, session->server);
+
+        CHECK( normalizer.get_opt_block(tns) == NORM_MODE_ON );
+        CHECK( normalizer.get_strip_ecn(tns) == NORM_MODE_ON );
+        CHECK( normalizer.get_tcp_block(tns) == NORM_MODE_ON );
+        CHECK( normalizer.get_trim_syn(tns) == NORM_MODE_ON );
+        CHECK( normalizer.get_trim_rst(tns) == NORM_MODE_ON );
+        CHECK( normalizer.get_trim_mss(tns) == NORM_MODE_ON );
+        CHECK( normalizer.get_trim_win(tns) == NORM_MODE_ON );
+        CHECK( normalizer.is_tcp_ips_enabled(tns) );
     }
 
     norm_enabled = false;
     for( os_policy = StreamPolicy::OS_FIRST; os_policy <= StreamPolicy::OS_PROXY; ++os_policy )
     {
-        TcpNormalizer* normalizer = TcpNormalizerFactory::create( session, os_policy,
-            session->client, session->server );
-
-        CHECK( normalizer->get_opt_block() == NORM_MODE_TEST );
-        CHECK( normalizer->get_strip_ecn() == NORM_MODE_TEST );
-        CHECK( normalizer->get_tcp_block() == NORM_MODE_TEST );
-        CHECK( normalizer->get_trim_syn() == NORM_MODE_TEST );
-        CHECK( normalizer->get_trim_rst() == NORM_MODE_TEST );
-        CHECK( normalizer->get_trim_mss() == NORM_MODE_TEST );
-        CHECK( normalizer->get_trim_win() == NORM_MODE_TEST );
-        CHECK( !normalizer->is_tcp_ips_enabled() );
-        delete normalizer;
+        TcpNormalizerState tns;
+        TcpNormalizer* normalizer = TcpNormalizerFactory::create(
+            tns, os_policy, session, session->client, session->server);
+
+        CHECK( normalizer.get_opt_block(tns) == NORM_MODE_TEST );
+        CHECK( normalizer.get_strip_ecn(tns) == NORM_MODE_TEST );
+        CHECK( normalizer.get_tcp_block(tns) == NORM_MODE_TEST );
+        CHECK( normalizer.get_trim_syn(tns) == NORM_MODE_TEST );
+        CHECK( normalizer.get_trim_rst(tns) == NORM_MODE_TEST );
+        CHECK( normalizer.get_trim_mss(tns) == NORM_MODE_TEST );
+        CHECK( normalizer.get_trim_win(tns) == NORM_MODE_TEST );
+        CHECK( !normalizer.is_tcp_ips_enabled(tns) );
     }
 
     delete flow;