]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #244 in SNORT/snort3 from refactor_process_tcp to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Mon, 8 Feb 2016 23:32:19 +0000 (18:32 -0500)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Mon, 8 Feb 2016 23:32:19 +0000 (18:32 -0500)
Squashed commit of the following:

commit 4b50ea6df55d95a969c48250633b4729876f9a76
Merge: 39f203a a79c98a
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Mon Feb 8 13:25:27 2016 -0500

    merge from origin

commit 39f203aed4047d0bc16dd2bfa9ee66c6a5766a69
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Thu Dec 17 11:18:50 2015 -0500

    continue refactoring of Process TCP into state machine
    miscellaneous fixs from code review comments - see TP user story 14128

commit a79c98a1c7787bc63d2b1e4efcfc174f160b05a3
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Mon Feb 8 11:49:13 2016 -0500

    uncrustify this code

commit b5fa677b0cacfa23d1aff58fb58a68dc22e75a53
Merge: 388199f aef8461
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Mon Feb 8 11:22:36 2016 -0500

    merge with origin to prep for pull request

commit 388199f5d32e9e1965a58181b48ba8b5f49abe0b
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Thu Dec 17 11:18:50 2015 -0500

    continue refactoring of Process TCP into state machine
    miscellaneous fixs from code review comments - see TP user story 14128

commit aef846189d4b96be21c0c9d9fcd065b993b6afa8
Merge: 50b1cc3 2d45273
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Thu Feb 4 06:49:35 2016 -0500

    merge with origin

commit 50b1cc325341e75422f03397daf2ff7ca3853e98
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Thu Dec 17 11:18:50 2015 -0500

    continue refactoring of Process TCP into state machine
    miscellaneous fixs from code review comments - see TP user story 14128

commit 2d45273464d3702e04a91b83486167b9225c1d80
Merge: 374cdb4 7401f08
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Wed Feb 3 14:54:17 2016 -0500

    fix merge issue from pull from origin

commit 374cdb427a1d61ed558f8e76355a174a141a3220
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Tue Feb 2 22:10:55 2016 -0500

    fix changes missed in rebase

commit 6c9f64c8b1de540919e50dc05f71d915dcfa1c2d
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Thu Dec 17 11:18:50 2015 -0500

    continue refactoring of Process TCP into state machine
    miscellaneous fixs from code review comments - see TP user story 14128

commit 7401f085bde0729c0b057c9b4ddb570285406440
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Thu Dec 17 11:18:50 2015 -0500

    continue refactoring of Process TCP into state machine

41 files changed:
src/protocols/packet.h
src/stream/libtcp/tcp_segment_descriptor.cc
src/stream/libtcp/tcp_segment_descriptor.h
src/stream/libtcp/tcp_state_handler.cc
src/stream/libtcp/tcp_state_handler.h
src/stream/libtcp/tcp_state_machine.cc
src/stream/libtcp/tcp_state_machine.h
src/stream/libtcp/tcp_stream_tracker.cc
src/stream/libtcp/tcp_stream_tracker.h
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_defs.h
src/stream/tcp/tcp_event_logger.cc
src/stream/tcp/tcp_event_logger.h
src/stream/tcp/tcp_normalizer.cc
src/stream/tcp/tcp_normalizer.h
src/stream/tcp/tcp_normalizers.cc
src/stream/tcp/tcp_reassembler.cc
src/stream/tcp/tcp_reassembler.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_wait1.h
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_syn_sent.cc
src/stream/tcp/tcp_state_time_wait.cc
src/stream/tcp/tcp_stream_config.cc
src/stream/tcp/tcp_stream_config.h
src/stream/tcp/tcp_tracker.cc
src/stream/tcp/tcp_tracker.h

index 53393a8a1a0f936847b3b0cc0aec0b3d47e5bafc..2ac036840639f0e687a2a40e63d5fbcb654b276c 100644 (file)
@@ -164,6 +164,9 @@ struct SO_PUBLIC Packet
     static const uint32_t max_dsize = IP_MAXPACKET;
 
     /*  Boolean functions - general information about this packet */
+    inline bool is_eth() const
+    { return proto_bits & PROTO_BIT__ETH; }
+
     inline bool has_ip() const
     { return ptrs.ip_api.is_ip(); }
 
@@ -283,14 +286,14 @@ struct SO_PUBLIC Packet
 static inline void SetExtraData(Packet* p, const uint32_t xid)
 { p->xtradata_mask |= BIT(xid); }
 
-static inline uint16_t EXTRACT_16BITS(const uint8_t* const p)
+static inline uint16_t extract_16bits(const uint8_t* const p)
 { return ntohs(*(uint16_t*)(p)); }
 
 #ifdef WORDS_MUSTALIGN
 
 #ifdef __GNUC__
 /* force word-aligned ntohl parameter */
-static inline uint32_t EXTRACT_32BITS(const uint8_t* p)
+static inline uint32_t extract_32bits(const uint8_t* p)
 {
     uint32_t tmp;
     memmove(&tmp, p, sizeof(uint32_t));
@@ -301,7 +304,7 @@ static inline uint32_t EXTRACT_32BITS(const uint8_t* p)
 #else
 
 /* allows unaligned ntohl parameter - dies w/SIGBUS on SPARCs */
-static inline uint32_t EXTRACT_32BITS(const uint8_t* p)
+static inline uint32_t extract_32bits(const uint8_t* p)
 { return ntohl(*(uint32_t*)p); }
 
 #endif
index 4034a777cfb90a164057f8b5970799f46ec88057..b3620f0cb3f8d33a69e86ef1cc5f699e382574b5 100644 (file)
 
 using namespace tcp;
 
-TcpSegmentDescriptor::TcpSegmentDescriptor(Flow* flow, Packet* pkt, TcpEventLogger* tel) :
+TcpSegmentDescriptor::TcpSegmentDescriptor(Flow* flow, Packet* pkt, TcpEventLogger& tel) :
     flow(flow), pkt(pkt)
 {
     tcph = pkt->ptrs.tcph;
-    src_port = ntohs(tcph->th_sport);
-    dst_port = ntohs(tcph->th_dport);
-    seq = ntohl(pkt->ptrs.tcph->th_seq);
-    ack = ntohl(pkt->ptrs.tcph->th_ack);
-    win = ntohs(pkt->ptrs.tcph->th_win);
-    end_seq = seq + (uint32_t)pkt->dsize;
+    src_port = tcph->src_port();
+    dst_port = tcph->dst_port();
+    seg_seq = tcph->seq();
+    seg_ack = tcph->ack();
+    seg_wnd = tcph->win();
+    end_seq = seg_seq + (uint32_t)pkt->dsize;
     ts = 0;
 
     // don't bump end_seq for fin here we will bump if/when fin is processed
@@ -45,7 +45,7 @@ TcpSegmentDescriptor::TcpSegmentDescriptor(Flow* flow, Packet* pkt, TcpEventLogg
     {
         end_seq++;
         if ( !tcph->is_ack() )
-            tel->set_tcp_internal_syn_event( );
+            tel.set_tcp_internal_syn_event( );
     }
 
     #ifdef DEBUG_STREAM_EX
@@ -67,7 +67,7 @@ uint32_t TcpSegmentDescriptor::init_mss(uint16_t* value)
     {
         if ( opt.code == TcpOptCode::MAXSEG )
         {
-            *value = EXTRACT_16BITS(opt.data);
+            *value = extract_16bits(opt.data);
             DebugFormat(DEBUG_STREAM_STATE, "Found MSS %u\n", *value);
             return TF_MSS;
         }
@@ -86,7 +86,6 @@ uint32_t TcpSegmentDescriptor::init_wscale(uint16_t* value)
 
     TcpOptIterator iter(tcph, pkt);
 
-    // using const because non-const is not supported
     for (const TcpOption& opt : iter)
     {
         if (opt.code == TcpOptCode::WSCALE)
@@ -94,12 +93,9 @@ uint32_t TcpSegmentDescriptor::init_wscale(uint16_t* value)
             *value = (uint16_t)opt.data[0];
             DebugFormat(DEBUG_STREAM_STATE, "Found wscale %d\n", *value);
 
-            /* If scale specified in option is larger than 14,
-             * use 14 because of limitation in the math of
-             * shifting a 32bit value (max scaled window is 2^30th).
-             *
-             * See RFC 1323 for details.
-             */
+            // If scale specified in option is larger than 14, use 14 because of limitation
+            // in the math of shifting a 32bit value (max scaled window is 2^30th).
+            // See RFC 1323 for details.
             if (*value > 14)
                 *value = 14;
 
@@ -113,21 +109,21 @@ uint32_t TcpSegmentDescriptor::init_wscale(uint16_t* value)
     return TF_NONE;
 }
 
-uint32_t TcpSegmentDescriptor::has_wscale(void)
+bool TcpSegmentDescriptor::has_wscale(void)
 {
     uint16_t wscale;
 
     DebugMessage(DEBUG_STREAM_STATE, "Checking for wscale...\n");
 
-    return init_wscale(&wscale);
+    return ( init_wscale(&wscale) & TF_WSCALE ) != TF_NONE;
 }
 
 void TcpSegmentDescriptor::print_tsd(void)
 {
     LogMessage("Tcp Segment Descriptor:\n");
-    LogMessage("    seq:    0x%08X\n", seq);
-    LogMessage("    ack:    0x%08X\n", ack);
-    LogMessage("    win:    %d\n", win);
+    LogMessage("    seq:    0x%08X\n", seg_seq);
+    LogMessage("    ack:    0x%08X\n", seg_ack);
+    LogMessage("    win:    %d\n", seg_wnd);
     LogMessage("    end:    0x%08X\n", end_seq);
 }
 
index eac2492f1fa7c6abbc48e0e0de7ba62eb985b0fd..6c09e344296ae85a12e7fe858c700728f7a72cb5 100644 (file)
 class TcpSegmentDescriptor
 {
 public:
-    TcpSegmentDescriptor(Flow*, Packet*, TcpEventLogger*);
+    TcpSegmentDescriptor(Flow*, Packet*, TcpEventLogger&);
     virtual ~TcpSegmentDescriptor();
 
     uint32_t init_mss(uint16_t* value);
     uint32_t init_wscale(uint16_t* value);
-    uint32_t has_wscale(void);
+    bool has_wscale(void);
 
     Flow* get_flow() const
     {
@@ -53,19 +53,24 @@ public:
         return tcph;
     }
 
-    void set_seq(uint32_t seq)
+    void set_seg_seq(uint32_t seq)
     {
-        this->seq = seq;
+        this->seg_seq = seq;
     }
 
-    uint32_t get_seq() const
+    void update_seg_seq(int32_t offset)
     {
-        return seq;
+        seg_seq += offset;
     }
 
-    uint32_t get_ack() const
+    uint32_t get_seg_seq() const
     {
-        return ack;
+        return seg_seq;
+    }
+
+    uint32_t get_seg_ack() const
+    {
+        return seg_ack;
     }
 
     void set_end_seq(uint32_t end_seq)
@@ -88,14 +93,14 @@ public:
         return ts;
     }
 
-    void set_win(uint32_t win)
+    void scale_seg_wnd(uint16_t wscale)
     {
-        this->win = win;
+        this->seg_wnd <<= wscale;
     }
 
-    uint32_t get_win() const
+    uint32_t get_seg_wnd() const
     {
-        return win;
+        return seg_wnd;
     }
 
     uint16_t get_dst_port() const
@@ -113,11 +118,33 @@ public:
         return flow->ssn_state.direction;
     }
 
-    uint32_t get_data_len() const
+    uint16_t get_seg_len() const
     {
         return pkt->dsize;
     }
 
+    void set_seg_len(uint16_t seg_len)
+    {
+        pkt->dsize = seg_len;
+    }
+
+    void update_seg_len(int32_t offset)
+    {
+        pkt->dsize += offset;
+    }
+
+    bool is_packet_from_server(void)
+    {
+        return pkt->packet_flags & PKT_FROM_SERVER;
+    }
+
+    void slide_segment_in_rcv_window(int32_t offset)
+    {
+        seg_seq += offset;
+        pkt->data += offset;
+        pkt->dsize -= offset;
+    }
+
     void print_tsd(void);
 
 private:
@@ -127,9 +154,9 @@ private:
     const tcp::TCPHdr* tcph;
     uint16_t src_port;
     uint16_t dst_port;
-    uint32_t seq;
-    uint32_t ack;
-    uint32_t win;
+    uint32_t seg_seq;
+    uint32_t seg_ack;
+    uint32_t seg_wnd;
     uint32_t end_seq;
     uint32_t ts;
 };
index f6fd6b4e40f6a939db06d987ca8ccf8ca521ec17..b5848e751dae9dd7f90980fc8c7512ef6f0e0a1a 100644 (file)
@@ -32,15 +32,14 @@ using namespace std;
 #include "stream_tcp_unit_test.h"
 #endif
 
-TcpStateHandler::TcpStateHandler(TcpStreamTracker::TcpStates state, TcpStateMachine& tsm) :
-    tsm(&tsm), tcp_state(state), tcp_event(TcpStreamTracker::TCP_MAX_EVENTS)
+TcpStateHandler::TcpStateHandler(TcpStreamTracker::TcpState state, TcpStateMachine& tsm) :
+    tsm(&tsm), tcp_state(state)
 {
     tsm.register_state_handler(state, *this);
 }
 
 TcpStateHandler::TcpStateHandler(void) :
-    tsm(nullptr), tcp_state(TcpStreamTracker::TCP_CLOSED),
-    tcp_event(TcpStreamTracker::TCP_MAX_EVENTS)
+    tsm(nullptr), tcp_state(TcpStreamTracker::TCP_CLOSED)
 {
 }
 
@@ -49,10 +48,22 @@ TcpStateHandler::~TcpStateHandler()
     // TODO Auto-generated destructor stub
 }
 
+void TcpStateHandler::do_pre_sm_packet_actions(TcpSegmentDescriptor& tsd)
+{
+    UNUSED(tsd);
+}
+
+void TcpStateHandler::do_post_sm_packet_actions(TcpSegmentDescriptor& tsd)
+{
+    UNUSED(tsd);
+}
+
 bool TcpStateHandler::eval(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
     bool handled = false;
 
+    do_pre_sm_packet_actions(tsd);
+
     switch ( tcp_event = tracker.get_tcp_event() )
     {
     case TcpStreamTracker::TCP_SYN_SENT_EVENT:
@@ -109,82 +120,81 @@ bool TcpStateHandler::eval(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
         break;
     }
 
+    do_post_sm_packet_actions(tsd);
     return handled;
 }
 
-bool TcpStateHandler::default_state_action(
-    TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker, const char* func_name)
+bool TcpStateHandler::default_state_action(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
 #ifdef DEBUG_MSGS
-    DebugFormat(DEBUG_STREAM_STATE, "Default Implementation of: %s tsd: %p tracker: %p\n",
-        func_name, &tsd, &tracker);
+    DebugFormat(DEBUG_STREAM_STATE, "tsd: %p tracker: %p state: %u event: %u\n",
+        &tsd, &tracker, tracker.get_tcp_state(), tracker.get_tcp_event() );
 #else
     UNUSED(tsd);
-    UNUSED(func_name);
+    UNUSED(tracker)
 #endif
 
-    tcp_event = tracker.get_tcp_event();
-    return false;
+    return true;
 }
 
 bool TcpStateHandler::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateHandler::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    return default_state_action(tsd, tracker);
 }
 
 #ifdef UNIT_TEST
@@ -196,7 +206,7 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
     TcpStateHandler* tsh = new TcpStateHandler;
     TcpStreamTracker* client_tracker = new TcpStreamTracker(true);
     TcpStreamTracker* server_tracker = new TcpStreamTracker(false);
-    TcpEventLogger* tel = new TcpEventLogger;
+    TcpEventLogger tel;
 
     GIVEN("a SYN Packet")
     {
index 2b96168d8b4c6afe539b2c8fffabdcbe7238322f..0532dbccc827ae93b3a3600fce80aa88b3b206dd 100644 (file)
@@ -31,28 +31,23 @@ class TcpStateMachine;
 class TcpStateHandler
 {
 public:
-    TcpStateHandler(TcpStreamTracker::TcpStates, TcpStateMachine&);
+    TcpStateHandler(TcpStreamTracker::TcpState, TcpStateMachine&);
     TcpStateHandler(void);
     virtual ~TcpStateHandler();
 
     virtual bool eval(TcpSegmentDescriptor&, TcpStreamTracker&);
 
-    TcpStreamTracker::TcpEvents get_tcp_event() const
+    TcpStreamTracker::TcpEvent get_tcp_event() const
     {
         return tcp_event;
     }
 
-    TcpStreamTracker::TcpStates get_tcp_state() const
+    TcpStreamTracker::TcpState get_tcp_state() const
     {
         return tcp_state;
     }
 
-    void set_tcp_state(TcpStreamTracker::TcpStates tcp_state)
-    {
-        this->tcp_state = tcp_state;
-    }
-
-    void set_tcp_event(TcpStreamTracker::TcpEvents tcp_event)
+    void set_tcp_event(TcpStreamTracker::TcpEvent tcp_event)
     {
         this->tcp_event = tcp_event;
     }
@@ -68,6 +63,9 @@ public:
     }
 
 protected:
+    virtual void do_pre_sm_packet_actions(TcpSegmentDescriptor&);
+    virtual void do_post_sm_packet_actions(TcpSegmentDescriptor&);
+
     virtual bool syn_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
     virtual bool syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
     virtual bool syn_ack_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
@@ -81,11 +79,11 @@ protected:
     virtual bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&);
     virtual bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&);
 
-    bool default_state_action(TcpSegmentDescriptor&, TcpStreamTracker&, const char*);
+    bool default_state_action(TcpSegmentDescriptor&, TcpStreamTracker&);
 
     const TcpStateMachine* tsm;
-    TcpStreamTracker::TcpStates tcp_state;
-    TcpStreamTracker::TcpEvents tcp_event;
+    TcpStreamTracker::TcpState tcp_state;
+    TcpStreamTracker::TcpEvent tcp_event = TcpStreamTracker::TCP_MAX_EVENTS;
 };
 
 #endif
index fee01408e8ce0e09c4908de5e7136033d9514ab2..bc4ba5cd179b9518d8db012668dca949d755d5cf 100644 (file)
 
 TcpStateMachine::TcpStateMachine(void)
 {
+    TcpStreamTracker::TcpState s;
     // register a default handler for each state...
-    for ( TcpStreamTracker::TcpStates state = TcpStreamTracker::TCP_LISTEN; state <
-        TcpStreamTracker::TCP_MAX_STATES; state++ )
+    for ( s = TcpStreamTracker::TCP_LISTEN; s < TcpStreamTracker::TCP_MAX_STATES; s++ )
     {
-        tcp_state_handlers[ state ] = nullptr;
-        new TcpStateHandler(state, *this);
+        tcp_state_handlers[ s ] = nullptr;
+        new TcpStateHandler(s, *this);
     }
 }
 
@@ -38,7 +38,7 @@ TcpStateMachine::~TcpStateMachine(void)
     // TODO Auto-generated destructor stub
 }
 
-void TcpStateMachine::register_state_handler(TcpStreamTracker::TcpStates state,
+void TcpStateMachine::register_state_handler(TcpStreamTracker::TcpState state,
     TcpStateHandler& handler)
 {
     if ( tcp_state_handlers[ state ] != nullptr )
index 286b25280d854b46eda6ba6f921582f9bdcc30fc..46d1d14b23eb3d393ea7700e590d55d39c97d2a1 100644 (file)
@@ -32,7 +32,7 @@ public:
     TcpStateMachine(void);
     virtual ~TcpStateMachine(void);
 
-    virtual void register_state_handler(TcpStreamTracker::TcpStates, TcpStateHandler&);
+    virtual void register_state_handler(TcpStreamTracker::TcpState, TcpStateHandler&);
     virtual bool eval(TcpSegmentDescriptor&, TcpStreamTracker&);
 
 private:
index f04b6da3c9a4ded8eeee1988c3e245925a2d3a45..b3914d247582ea4aba66ba66e7aedc1c5292596e 100644 (file)
@@ -41,13 +41,8 @@ const char* tcp_event_names[] = { "TCP_SYN_SENT_EVENT", "TCP_SYN_RECV_EVENT",
                                   "TCP_RST_RECV_EVENT" };
 
 TcpStreamTracker::TcpStreamTracker(bool client) :
-    client_tracker(client), require_3whs(false), snd_una(0), snd_nxt(0), snd_wnd(0), snd_up(0),
-    snd_wl1(0), snd_wl2(0), iss(0), rcv_nxt(0), rcv_wnd(0), rcv_up(0), irs(0),
-    ts_last_packet(0), ts_last(0), wscale(0), mss(0), flags(0)
+    client_tracker(client), tcp_state(client ? TCP_STATE_NONE : TCP_LISTEN)
 {
-    memset(mac_addr, '0', sizeof(mac_addr));
-    tcp_state =  TCP_STATE_NONE;
-    tcp_event = TCP_MAX_EVENTS;
 }
 
 TcpStreamTracker::~TcpStreamTracker()
@@ -55,7 +50,7 @@ TcpStreamTracker::~TcpStreamTracker()
     // TODO Auto-generated destructor stub
 }
 
-void TcpStreamTracker::set_tcp_event(TcpSegmentDescriptor& tsd)
+TcpStreamTracker::TcpEvent TcpStreamTracker::set_tcp_event(TcpSegmentDescriptor& tsd)
 {
     bool talker;
     const tcp::TCPHdr* tcph = tsd.get_tcph();
@@ -67,48 +62,52 @@ void TcpStreamTracker::set_tcp_event(TcpSegmentDescriptor& tsd)
 
     if ( talker )
     {
+        // talker events
         if ( tcph->is_syn_only() )
             tcp_event = TCP_SYN_SENT_EVENT;
         else if ( tcph->is_syn_ack() )
             tcp_event = TCP_SYN_ACK_SENT_EVENT;
+        else if ( tcph->is_rst() )
+            tcp_event = TCP_RST_SENT_EVENT;
+        else if ( tcph->is_fin( ) )
+            tcp_event = TCP_FIN_SENT_EVENT;
         else if ( tcph->is_ack() || tcph->is_psh() )
         {
-            if ( tsd.get_data_len() > 0 )
+            if ( tsd.get_seg_len() > 0 )
                 tcp_event = TCP_DATA_SEG_SENT_EVENT;
             else
                 tcp_event = TCP_ACK_SENT_EVENT;
         }
-        else if ( tcph->is_rst() )
-            tcp_event = TCP_RST_SENT_EVENT;
-        else if ( tcph->is_fin( ) )
-            tcp_event = TCP_FIN_SENT_EVENT;
 //        else if( tsd.get_data_len() > 0 )   // FIXIT - No flags set, how do we handle this?
 //            tcp_event = TCP_DATA_SEG_SENT_EVENT;
         else
             tcp_event = TCP_ACK_SENT_EVENT;
     }
-    else          // server is listening events
+    else
     {
+        // listener events
         if ( tcph->is_syn_only() )
             tcp_event = TCP_SYN_RECV_EVENT;
         else if ( tcph->is_syn_ack() )
             tcp_event = TCP_SYN_ACK_RECV_EVENT;
+        else if ( tcph->is_rst() )
+            tcp_event = TCP_RST_RECV_EVENT;
+        else if ( tcph->is_fin( ) )
+            tcp_event = TCP_FIN_RECV_EVENT;
         else if ( tcph->is_ack() || tcph->is_psh() )
         {
-            if ( tsd.get_data_len() > 0 )
+            if ( tsd.get_seg_len() > 0 )
                 tcp_event = TCP_DATA_SEG_RECV_EVENT;
             else
                 tcp_event = TCP_ACK_RECV_EVENT;
         }
-        else if ( tcph->is_rst() )
-            tcp_event = TCP_RST_RECV_EVENT;
-        else if ( tcph->is_fin( ) )
-            tcp_event = TCP_FIN_RECV_EVENT;
-//         else if( tsd.get_data_len() > 0 )    // FIXIT - No flags set, how do we handle this?
+//       else if( tsd.get_data_len() > 0 )    // FIXIT - No flags set, how do we handle this?
 //             tcp_event = TCP_DATA_SEG_RECV_EVENT;
         else
             tcp_event = TCP_ACK_RECV_EVENT;
     }
+
+    return tcp_event;
 }
 
 // Use a for loop and byte comparison, which has proven to be faster on pipelined architectures
@@ -116,6 +115,9 @@ void TcpStreamTracker::set_tcp_event(TcpSegmentDescriptor& tsd)
 // there is no guarantee of memory alignment (and thus performance issues similar to memcmp).
 bool TcpStreamTracker::compare_mac_addresses(const uint8_t eth_addr[])
 {
+    if ( !mac_addr_valid )
+        return true;
+
     for ( int i = 0; i < 6; ++i )
         if ( mac_addr[i] != eth_addr[i] )
             return false;
@@ -128,29 +130,33 @@ void TcpStreamTracker::cache_mac_address(TcpSegmentDescriptor& tsd, uint8_t dire
     int i;
 
     /* Not Ethernet based, nothing to do */
-    if ( !( tsd.get_pkt()->proto_bits & PROTO_BIT__ETH ) )
-        return;
-
-    // if flag is set, guaranteed to have an eth layer
-    const eth::EtherHdr* eh = layer::get_eth_layer(tsd.get_pkt() );
-
-    if ( direction == FROM_CLIENT )
+    if ( tsd.get_pkt()->is_eth() )
     {
-        if ( client_tracker )
-            for ( i = 0; i < 6; i++ )
-                mac_addr[i] = eh->ether_src[i];
-        else
-            for ( i = 0; i < 6; i++ )
-                mac_addr[i] = eh->ether_dst[i];
-    }
-    else
-    {
-        if ( client_tracker )
-            for ( i = 0; i < 6; i++ )
-                mac_addr[i] = eh->ether_dst[i];
+        // if flag is set, guaranteed to have an eth layer
+        const eth::EtherHdr* eh = layer::get_eth_layer(tsd.get_pkt() );
+
+        if ( direction == FROM_CLIENT )
+        {
+            if ( client_tracker )
+                for ( i = 0; i < 6; i++ )
+                    mac_addr[i] = eh->ether_src[i];
+            else
+                for ( i = 0; i < 6; i++ )
+                    mac_addr[i] = eh->ether_dst[i];
+        }
         else
-            for ( i = 0; i < 6; i++ )
-                mac_addr[i] = eh->ether_src[i];
+        {
+            if ( client_tracker )
+                for ( i = 0; i < 6; i++ )
+                    mac_addr[i] = eh->ether_dst[i];
+            else
+                for ( i = 0; i < 6; i++ )
+                    mac_addr[i] = eh->ether_src[i];
+        }
+
+        mac_addr_valid = true;
     }
+
+    mac_addr_valid = true;
 }
 
index bd633d2a31b30dc219609e9cb8734e94ec5ff36a..e69ca1baa68775653b4bb04506c8f0d179174ab2 100644 (file)
@@ -32,7 +32,7 @@ extern const char* tcp_event_names[];
 class TcpStreamTracker
 {
 public:
-    enum TcpStates
+    enum TcpState
     {
         TCP_LISTEN,
         TCP_SYN_SENT,
@@ -49,7 +49,7 @@ public:
         TCP_MAX_STATES
     };
 
-    enum TcpEvents
+    enum TcpEvent
     {
         TCP_SYN_SENT_EVENT,
         TCP_SYN_RECV_EVENT,
@@ -74,34 +74,29 @@ public:
         return client_tracker;
     }
 
-    bool is_3whs_required() const
+    bool is_server_tracker() const
     {
-        return require_3whs;
+        return !client_tracker;
     }
 
-    void set_require_3whs(bool require3_whs)
-    {
-        this->require_3whs = require3_whs;
-    }
-
-    TcpStates get_tcp_state() const
+    TcpState get_tcp_state() const
     {
         return tcp_state;
     }
 
-    void set_tcp_state(TcpStates tcp_state)
+    void set_tcp_state(TcpState tcp_state)
     {
         this->tcp_state = tcp_state;
     }
 
-    TcpEvents get_tcp_event() const
+    TcpEvent get_tcp_event() const
     {
         return tcp_event;
     }
 
-    void set_tcp_event(TcpSegmentDescriptor& tsd);
+    TcpEvent set_tcp_event(TcpSegmentDescriptor& tsd);
 
-    void set_tcp_event(TcpEvents tcp_event)
+    void set_tcp_event(TcpEvent tcp_event)
     {
         this->tcp_event = tcp_event;
     }
@@ -228,6 +223,8 @@ public:
 
     bool is_ack_valid(uint32_t cur)
     {
+        // FIXIT - do we need this check? we've alwasy seen something by the time
+        // we get here
         /* If we haven't seen anything, ie, low & high are 0, return true */
         if ( ( snd_una == 0 ) && ( snd_una == snd_nxt ) )
             return 1;
@@ -238,7 +235,52 @@ public:
     // ack number must ack syn
     bool is_rst_valid_in_syn_sent(TcpSegmentDescriptor& tsd)
     {
-        return tsd.get_ack() == snd_una;
+        return tsd.get_seg_ack() == snd_una;
+    }
+
+    uint32_t get_ts_last() const
+    {
+        return ts_last;
+    }
+
+    void set_ts_last(uint32_t ts_last)
+    {
+        this->ts_last = ts_last;
+    }
+
+    uint8_t get_tf_flags() const
+    {
+        return tf_flags;
+    }
+
+    void set_tf_flags(uint16_t flags)
+    {
+        this->tf_flags |= flags;
+    }
+
+    void clear_tf_flags(uint16_t flags)
+    {
+        this->tf_flags &= ~flags;
+    }
+
+    uint16_t get_wscale() const
+    {
+        return wscale;
+    }
+
+    void set_wscale(uint16_t wscale)
+    {
+        this->wscale = wscale;
+    }
+
+    uint16_t get_mss() const
+    {
+        return mss;
+    }
+
+    void set_mss(uint16_t mss)
+    {
+        this->mss = mss;
     }
 
     void cache_mac_address(TcpSegmentDescriptor& tsd, uint8_t direction);
@@ -246,45 +288,50 @@ public:
 
 protected:
     bool client_tracker;
-    bool require_3whs;
+    TcpState tcp_state;
+    TcpEvent tcp_event = TCP_MAX_EVENTS;
+    bool require_3whs = false;
+
+    uint32_t snd_una = 0; // SND.UNA - send unacknowledged
+    uint32_t snd_nxt = 0; // SND.NXT - send next
+    uint32_t snd_wnd = 0; // SND.WND - send window
+    uint16_t snd_up = 0;  // SND.UP  - send urgent pointer
+    uint32_t snd_wl1 = 0; // SND.WL1 - segment sequence number used for last window update
+    uint32_t snd_wl2 = 0; // SND.WL2 - segment acknowledgment number used for last window update
+    uint32_t iss = 0;     // ISS     - initial send sequence number
 
-    uint32_t snd_una; // SND.UNA - send unacknowledged
-    uint32_t snd_nxt; // SND.NXT - send next
-    uint32_t snd_wnd; // SND.WND - send window
-    uint16_t snd_up;  // SND.UP  - send urgent pointer
-    uint32_t snd_wl1; // SND.WL1 - segment sequence number used for last window update
-    uint32_t snd_wl2; // SND.WL2 - segment acknowledgment number used for last window update
-    uint32_t iss;     // ISS     - initial send sequence number
+    uint32_t rcv_nxt = 0; // RCV.NXT - receive next
+    uint32_t rcv_wnd = 0; // RCV.WND - receive window
+    uint16_t rcv_up = 0;  // RCV.UP  - receive urgent pointer
+    uint32_t irs = 0;     // IRS     - initial receive sequence number
 
-    uint32_t rcv_nxt; // RCV.NXT - receive next
-    uint32_t rcv_wnd; // RCV.WND - receive window
-    uint16_t rcv_up;  // RCV.UP  - receive urgent pointer
-    uint32_t irs;     // IRS     - initial receive sequence number
+// FIXIT - make these non-public
 
-    uint32_t ts_last_packet; // timestamp of last packet we got
+public:
+    uint32_t r_nxt_ack = 0; /* next expected ack from remote side */
+    uint32_t r_win_base = 0; /* remote side window base sequence number
+     * (i.e. the last ack we got) */
+
+protected:
+    uint32_t ts_last_packet = 0;
+    uint32_t ts_last = 0; /* last timestamp (for PAWS) */
+    uint16_t tf_flags = 0;
 
-    // FIXIT - make this protected
+    uint8_t mac_addr[6] = {};
+    bool mac_addr_valid = false;
+
+    // FIXIT - make this protected...
 
 public:
-    uint32_t ts_last; /* last timestamp (for PAWS) */
     uint16_t wscale; /* window scale setting */
     uint16_t mss; /* max segment size */
-
-    uint8_t mac_addr[6];
-    uint8_t flags; /* bitmap flags (TF_xxx) */
-
-protected:
-    TcpStates tcp_state;
-    TcpEvents tcp_event;
 };
 
-inline TcpStreamTracker::TcpStates& operator++(TcpStreamTracker::TcpStates& state, int)  // <---
-                                                                                         // note --
-                                                                                         // must be
-                                                                                         // a reference
+// <--- note -- the 'state' parameter must be a reference
+inline TcpStreamTracker::TcpState& operator++(TcpStreamTracker::TcpState& state, int)
 {
     const int i = static_cast<int>(state);
-    state = static_cast<TcpStreamTracker::TcpStates>((i + 1) % ( TcpStreamTracker::TCP_MAX_EVENTS +
+    state = static_cast<TcpStreamTracker::TcpState>((i + 1) % ( TcpStreamTracker::TCP_MAX_EVENTS +
         1 ) );
     return state;
 }
index f644fb1c11d9f4ce65c71e52f76f8bfb2b53eb12..ef758258bb4f4e4c18762322d5b14a41bc66fc7c 100644 (file)
@@ -131,7 +131,7 @@ int SegmentOverlapEditor::generate_bad_segment_event(void)
 {
     DebugFormat(DEBUG_STREAM_STATE, "bad segment: overlap with invalid sequence number"
         "(seq: %X  seq_end: %X overlap: %lu\n", seq, seq_end, overlap);
-    session->tel->EventBadSegment();
+    session->tel.EventBadSegment();
     inc_tcp_discards();
     return STREAM_INSERT_ANOMALY;
 }
@@ -142,7 +142,7 @@ int SegmentOverlapEditor::left_overlap_keep_first(void)
 
     DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", overlap);
 
-    len = tsd->get_pkt()->dsize;
+    len = tsd->get_seg_len();
     overlap = left->seq + left->payload_size - seq;
     if ( overlap > 0 )
     {
@@ -152,24 +152,24 @@ int SegmentOverlapEditor::left_overlap_keep_first(void)
         overlap_count++;
 
         DebugMessage(DEBUG_STREAM_STATE, "left overlap, honoring old data\n");
-        if ( SEQ_LT(left->seq, tsd->get_seq() ) && SEQ_GT(left->seq + left->payload_size,
-            tsd->get_seq() + tsd->get_pkt()->dsize) )
+        if ( SEQ_LT(left->seq, tsd->get_seg_seq() ) && SEQ_GT(left->seq + left->payload_size,
+            tsd->get_seg_seq() + tsd->get_seg_len() ) )
         {
             if (tcp_ips_data == NORM_MODE_ON)
             {
-                unsigned offset = tsd->get_seq() - left->seq;
+                unsigned offset = tsd->get_seg_seq() - left->seq;
                 memcpy( ( uint8_t* )tsd->get_pkt()->data, left->payload + offset,
-                    tsd->get_pkt()->dsize);
+                    tsd->get_seg_len() );
                 tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
             }
             tcp_norm_stats[PC_TCP_IPS_DATA][tcp_ips_data]++;
         }
-        else if ( SEQ_LT(left->seq, tsd->get_seq() ) )
+        else if ( SEQ_LT(left->seq, tsd->get_seg_seq() ) )
         {
             if ( tcp_ips_data == NORM_MODE_ON )
             {
-                unsigned offset = tsd->get_seq() - left->seq;
-                unsigned length = left->seq + left->payload_size - tsd->get_seq();
+                unsigned offset = tsd->get_seg_seq() - left->seq;
+                unsigned length = left->seq + left->payload_size - tsd->get_seg_seq();
                 memcpy( ( uint8_t* )tsd->get_pkt()->data, left->payload + offset, length);
                 tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
             }
@@ -191,7 +191,7 @@ int SegmentOverlapEditor::left_overlap_trim_first(void)
 
     DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", overlap);
 
-    len = tsd->get_pkt()->dsize;
+    len = tsd->get_seg_len();
     overlap = left->seq + left->payload_size - seq;
     if ( overlap > 0 )
     {
@@ -222,7 +222,7 @@ int SegmentOverlapEditor::left_overlap_keep_last(void)
 
     DebugFormat(DEBUG_STREAM_STATE, "left overlap %d\n", overlap);
 
-    len = tsd->get_pkt()->dsize;
+    len = tsd->get_seg_len();
     overlap = left->seq + left->payload_size - seq;
     if ( overlap > 0 )
     {
@@ -283,8 +283,8 @@ void SegmentOverlapEditor::right_overlap_truncate_new(void)
 {
     if (tcp_ips_data == NORM_MODE_ON)
     {
-        unsigned offset = right->seq - tsd->get_seq();
-        unsigned length = tsd->get_seq() + tsd->get_pkt()->dsize - right->seq;
+        unsigned offset = right->seq - tsd->get_seg_seq();
+        unsigned length = tsd->get_seg_seq() + tsd->get_seg_len() - right->seq;
         memcpy( ( uint8_t* )tsd->get_pkt()->data + offset, right->payload, length);
         tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
     }
@@ -301,7 +301,7 @@ int SegmentOverlapEditor::full_right_overlap_truncate_new(void)
 
     if ( tcp_ips_data == NORM_MODE_ON )
     {
-        unsigned offset = right->seq - tsd->get_seq();
+        unsigned offset = right->seq - tsd->get_seg_seq();
         memcpy( ( uint8_t* )tsd->get_pkt()->data + offset, right->payload, right->payload_size);
         tsd->get_pkt()->packet_flags |= PKT_MODIFIED;
     }
@@ -327,7 +327,7 @@ int SegmentOverlapEditor::full_right_overlap_truncate_new(void)
 
         /* 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_seq();
+        slide = seq - tsd->get_seg_seq();
         int rc = add_reassembly_segment(*tsd, len, slide, trunc_len, seq, left);
         if ( rc != STREAM_INSERT_OK )
             return rc;
index 1e7218d9a002bd3ab5e5eeb819874c90708ff0e2..a78991f1ba4b3a732c149f3f70e179eed6800b33 100644 (file)
@@ -36,12 +36,6 @@ class SegmentOverlapEditor
 protected:
 
     SegmentOverlapEditor(void)
-        : session(nullptr), reassembly_policy(ReassemblyPolicy::OS_DEFAULT), 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), seq(0), seq_end(0),
-        len(0), overlap(0), slide(0), trunc_len(0), rdata(nullptr),
-        rsize(0), rseq(0), keep_segment(true)
     {
         tcp_ips_data = Normalize_GetMode(NORM_TCP_IPS);
     }
@@ -53,15 +47,15 @@ protected:
         this->tsd = &tsd;
         this->left = left;
         this->right = right;
-        seq = tsd.get_seq();
+        seq = tsd.get_seg_seq();
         seq_end = tsd.get_end_seq();
-        len = tsd.get_data_len();
+        len = tsd.get_seg_len();
         overlap = 0;
         slide = 0;
         trunc_len = 0;
         rdata = tsd.get_pkt()->data;
-        rsize = tsd.get_data_len();
-        rseq = tsd.get_seq();
+        rsize = tsd.get_seg_len();
+        rseq = tsd.get_seg_seq();
         keep_segment = true;
     }
 
@@ -87,41 +81,37 @@ protected:
     virtual int insert_left_overlap(void) = 0;
     virtual void insert_right_overlap(void) = 0;
     virtual int insert_full_overlap(void) = 0;
-    virtual int add_reassembly_segment(TcpSegmentDescriptor&, int16_t len, uint32_t slide, uint32_t
-        trunc,
-        uint32_t seq, TcpSegmentNode*) = 0;
-    virtual int dup_reassembly_segment(Packet* p, TcpSegmentNode* left, TcpSegmentNode** retSeg) =
-        0;
-    virtual int delete_reassembly_segment(TcpSegmentNode* seg) = 0;
-
+    virtual int add_reassembly_segment(TcpSegmentDescriptor&, int16_t, uint32_t, uint32_t, uint32_t, TcpSegmentNode*) = 0;
+    virtual int dup_reassembly_segment(Packet*, TcpSegmentNode*, TcpSegmentNode**) = 0;
+    virtual int delete_reassembly_segment(TcpSegmentNode*) = 0;
     virtual void print(void);
 
-    TcpSession* session;
-    ReassemblyPolicy reassembly_policy;
+    TcpSession* session = nullptr;
+    ReassemblyPolicy reassembly_policy = ReassemblyPolicy::OS_DEFAULT;
     NormMode tcp_ips_data;
 
     TcpSegmentList seglist;
-    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 */
-
-    TcpSegmentDescriptor* tsd;
-    TcpSegmentNode* left;
-    TcpSegmentNode* right;
-    uint32_t seq;
-    uint32_t seq_end;
-    uint16_t len;
-    int32_t overlap;
-    int32_t slide;
-    int32_t trunc_len;
-    const uint8_t* rdata;
-    uint16_t rsize;
-    uint32_t rseq;
-    bool keep_segment;
+    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;
 };
 
 #endif
index 33e327d5fd9e7d529ba4ee52169e1acc6962c0fe..80b9550fa1e2f002877287c36e5426ae24361d10 100644 (file)
@@ -58,17 +58,18 @@ static inline void TraceEvent(const Packet* p, TcpSegmentDescriptor*, uint32_t t
 
     // force relative ack to zero if not conveyed
     if (flags[1] != 'A')
-        rxd = ntohl(h->th_ack);
+        rxd = h->ack();   // FIXIT - SYN's seen with ack > 0 and ACK flag not set...
 
     if (p->packet_flags & PKT_STREAM_ORDER_OK)
         order = " (ins)";
     else if (p->packet_flags & PKT_STREAM_ORDER_BAD)
         order = " (oos)";
 
+    uint32_t rseq = ( txd ) ? h->seq() - txd : h->seq();
+    uint32_t rack = ( rxd ) ? h->ack() - rxd : h->ack();
     fprintf(stdout, "\n" FMTu64("-3") " %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4u Len=%-4u%s\n",
         //"\n" FMTu64("-3") " %s=0x%02x Seq=%-4u Ack=%-4u Win=%-4u Len=%-4u End=%-4u%s\n",
-        pc.total_from_daq, flags, h->th_flags, ntohl(h->th_seq) - txd, ntohl(h->th_ack) - rxd,
-        ntohs(h->th_win), p->dsize, order);
+        pc.total_from_daq, flags, h->th_flags, rseq, rack, h->win(), p->dsize, order);
 }
 
 static inline void TraceSession(const Flow* lws)
@@ -79,11 +80,13 @@ static inline void TraceSession(const Flow* lws)
 
 static inline void TraceState(const TcpTracker* a, const TcpTracker* b, const char* s)
 {
-    uint32_t why = a->get_snd_nxt() ? LCL(a, get_snd_nxt) : 0;
+    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;
 
-    fprintf(stdout, "    %s ST=%s:%02x   UA=%-4u NS=%-4u LW=%-5u RN=%-4u RW=%-4u ", s,
-        statext[a->get_tcp_state()], a->s_mgr.sub_state, LCL(a, get_snd_una), why,
-        a->get_snd_wnd( ), RMT(a, r_nxt_ack, b), RMT(a, r_win_base, b));
+    fprintf(stdout,
+        "    %s ST=%s:%02x   UA=%-4u NS=%-4u LW=%-5u RN=%-4u RW=%-4u ISS=%-4u IRS=%-4u ",
+        s, statext[a->get_tcp_state()], a->s_mgr.sub_state, ua, ns, a->get_snd_wnd( ),
+        RMT(a, r_nxt_ack, b), RMT(a, r_win_base, b), a->get_iss(), a->get_irs());
 
     if ( a->s_mgr.state_queue != TcpStreamTracker::TCP_STATE_NONE )
         fprintf(stdout, "QS=%s QC=0x%02x QA=%-4u", statext[a->s_mgr.state_queue],
@@ -118,28 +121,19 @@ static inline void TraceTCP(const Packet* p, const Flow* lws, TcpSegmentDescript
         sdir = "SRV>";
         cdir = "CLI<";
 
-        if (ssn->tcp_init)
-        {
-            txd = srv->get_iss();
-            rxd = cli->get_iss();
-        }
+        txd = srv->get_iss();
+        rxd = srv->get_irs();
     }
     else if (p->packet_flags & PKT_FROM_CLIENT)
     {
         sdir = "SRV<";
         cdir = "CLI>";
 
-        if (ssn->tcp_init)
-        {
-            txd = cli->get_iss();
-            rxd = srv->get_iss();
-        }
+        txd = cli->get_iss();
+        rxd = cli->get_irs();
     }
     TraceEvent(p, tsd, txd, rxd);
 
-    if (!ssn->tcp_init)
-        return;
-
     if (lws && ssn->lws_init)
         TraceSession(lws);
 
index 48a3811a4a0eb9892ef1cf19c418a1ae7fb1f54c..cc898d6296ce966bd986defa9aaf0c990a308e79 100644 (file)
 #include "main/snort_debug.h"
 #include "protocols/packet.h"
 
-#if 0
-/* TCP states */
-#define TCP_STATE_NONE         0
-#define TCP_STATE_LISTEN       1
-#define TCP_STATE_SYN_RCVD     2
-#define TCP_STATE_SYN_SENT     3
-#define TCP_STATE_ESTABLISHED  4
-#define TCP_STATE_CLOSE_WAIT   5
-#define TCP_STATE_LAST_ACK     6
-#define TCP_STATE_FIN_WAIT_1   7
-#define TCP_STATE_CLOSING      8
-#define TCP_STATE_FIN_WAIT_2   9
-#define TCP_STATE_TIME_WAIT   10
-#define TCP_STATE_CLOSED      11
-#endif
-
 /* actions */
 #define ACTION_NOTHING                  0x00000000
 #define ACTION_FLUSH_SENDER_STREAM      0x00000001
@@ -70,6 +54,7 @@
 #define PAWS_WINDOW         60
 #define PAWS_24DAYS         2073600         /* 24 days in seconds */
 
+#define SUB_STATE_NONE 0x00
 #define SUB_SYN_SENT  0x01
 #define SUB_ACK_SENT  0x02
 #define SUB_SETUP_OK  0x03
@@ -160,17 +145,6 @@ enum FlushPolicy
     STREAM_FLPOLICY_ON_DATA, /* protocol aware ips */
 };
 
-#if 0
-struct TcpDataBlock
-{
-    Packet* pkt;
-    uint32_t seq;
-    uint32_t ack;
-    uint32_t win;
-    uint32_t end_seq;
-    uint32_t ts;
-};
-#endif
 
 //#define DEBUG_STREAM_EX
 #ifdef DEBUG_STREAM_EX
index 94b7fc933316de7488858d28c98c845094f9935e..2efbbbfaa6bb5e990438b0a361ac0929935e0a4e 100644 (file)
@@ -16,7 +16,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
 
-// tcp_events.cc author davis mcpherson <davmcphe@@cisco.com>
+// tcp_event_logger.cc author davis mcpherson <davmcphe@@cisco.com>
 // Created on: Jul 30, 2015
 
 #include "main/snort_config.h"
index 74527bd853ca0c2b161bd427a20072c0dd3b5edf..007cd0e197043f9584e40b1b9f1db8363c6a84e8 100644 (file)
@@ -16,7 +16,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
 
-// tcp_events.h author davis mcpherson <davmcphe@@cisco.com>
+// tcp_event_logger.h author davis mcpherson <davmcphe@@cisco.com>
 // Created on: Jul 30, 2015
 
 #ifndef TCP_EVENT_LOGGER_H
index 9f71ce30d6add3fc85d5bea612530d04c5cca128..ab888ae8c6e076dae6d1a771aa334e1e3fe355d2 100644 (file)
@@ -45,8 +45,7 @@ static inline int SetupOK(const TcpTracker* st)
 }
 
 TcpNormalizer::TcpNormalizer(StreamPolicy os_policy, TcpSession* session, TcpTracker* tracker) :
-    os_policy(os_policy), session(session), tracker(tracker),
-    peer_tracker(nullptr)
+    os_policy(os_policy), session(session), tracker(tracker)
 {
     tcp_ips_enabled = Normalize_IsEnabled(NORM_TCP_IPS);
     trim_syn = Normalize_GetMode(NORM_TCP_TRIM_SYN);
@@ -56,9 +55,6 @@ TcpNormalizer::TcpNormalizer(StreamPolicy os_policy, TcpSession* session, TcpTra
     strip_ecn = Normalize_GetMode(NORM_TCP_ECN_STR);
     tcp_block = Normalize_GetMode(NORM_TCP_BLOCK);
     opt_block = Normalize_GetMode(NORM_TCP_OPT);
-
-    paws_ts_fudge = 0;
-    paws_drop_zero_ts = true;
 }
 
 const PegInfo* TcpNormalizer::get_normalization_pegs()
@@ -77,8 +73,8 @@ void TcpNormalizer::trim_payload(
 {
     if (mode == NORM_MODE_ON)
     {
-        uint16_t fat = tsd.get_pkt()->dsize - max;
-        tsd.get_pkt()->dsize = max;
+        uint16_t fat = tsd.get_seg_len() - max;
+        tsd.set_seg_len(max);
         tsd.get_pkt()->packet_flags |= (PKT_MODIFIED | PKT_RESIZED);
         tsd.set_end_seq(tsd.get_end_seq() - fat);
     }
@@ -196,9 +192,9 @@ uint32_t TcpNormalizer::get_tcp_timestamp(TcpSegmentDescriptor& tsd, bool strip)
     tcp::TcpOptIterator iter(tsd.get_tcph(), tsd.get_pkt() );
 
     // using const because non-const is not supported
-    for (const tcp::TcpOption& opt : iter)
+    for ( const tcp::TcpOption& opt : iter )
     {
-        if (opt.code == tcp::TcpOptCode::TIMESTAMP)
+        if ( opt.code == tcp::TcpOptCode::TIMESTAMP )
         {
             bool stripped = false;
 
@@ -207,7 +203,7 @@ uint32_t TcpNormalizer::get_tcp_timestamp(TcpSegmentDescriptor& tsd, bool strip)
 
             if (!stripped)
             {
-                tsd.set_ts(EXTRACT_32BITS(opt.data) );
+                tsd.set_ts(extract_32bits(opt.data) );
                 DebugFormat(DEBUG_STREAM_STATE, "Found timestamp %lu\n", tsd.get_ts());
                 return TF_TSTAMP;
             }
@@ -224,10 +220,10 @@ bool TcpNormalizer::validate_rst_seq_geq(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_seq(), tracker->r_nxt_ack +
+        tsd.get_end_seq(), tracker->r_win_base, tsd.get_seg_seq(), tracker->r_nxt_ack +
         get_stream_window(tsd));
 
-    if (SEQ_GEQ(tsd.get_seq(), tracker->r_nxt_ack))
+    if ( ( tracker->r_nxt_ack == 0 ) || SEQ_GEQ(tsd.get_seg_seq(), tracker->r_nxt_ack) )
     {
         DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (>= next seq)!\n");
         return true;
@@ -241,13 +237,17 @@ bool TcpNormalizer::validate_rst_end_seq_geq(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_seq(), tracker->r_nxt_ack +
+        tsd.get_end_seq(), tracker->r_win_base, tsd.get_seg_seq(), tracker->r_nxt_ack +
         get_stream_window(tsd));
 
-    if (SEQ_GEQ(tsd.get_end_seq(), tracker->r_win_base))
+    // FIXIT - check for r_win_base == 0 is hack for uninitialized r_win_base, fix this
+    if ( tracker->r_win_base == 0 )
+        return true;
+
+    if ( SEQ_GEQ(tsd.get_end_seq(), tracker->r_win_base))
     {
         // reset must be admitted when window closed
-        if (SEQ_LEQ(tsd.get_seq(), tracker->r_win_base + get_stream_window(tsd)))
+        if (SEQ_LEQ(tsd.get_seg_seq(), tracker->r_win_base + get_stream_window(tsd)))
         {
             DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (within window)!\n");
             return true;
@@ -262,10 +262,11 @@ bool TcpNormalizer::validate_rst_seq_eq(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_seq(), tracker->r_nxt_ack +
+        tsd.get_end_seq(), tracker->r_win_base, tsd.get_seg_seq(), tracker->r_nxt_ack +
         get_stream_window(tsd));
 
-    if (SEQ_EQ(tsd.get_seq(), tracker->r_nxt_ack))
+    // FIXIT - 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) )
     {
         DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (next seq)!\n");
         return true;
@@ -286,16 +287,16 @@ bool TcpNormalizer::validate_rst(TcpSegmentDescriptor& tsd)
 
 int TcpNormalizer::validate_paws_timestamp(TcpSegmentDescriptor& tsd)
 {
-    if ( ( (int)( ( tsd.get_ts() - peer_tracker->ts_last ) + paws_ts_fudge ) ) < 0 )
+    if ( ( (int)( ( tsd.get_ts() - peer_tracker->get_ts_last() ) + 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);
+        ( ( TcpSession* )tsd.get_flow()->session )->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
         packet_dropper(tsd, NORM_TCP_OPT);
         return ACTION_BAD_PKT;
     }
-    else if ( ( peer_tracker->ts_last != 0 )
+    else if ( ( peer_tracker->get_ts_last() != 0 )
         && ( ( uint32_t )tsd.get_pkt()->pkth->ts.tv_sec > peer_tracker->get_ts_last_packet() +
         PAWS_24DAYS ) )
     {
@@ -304,7 +305,7 @@ int TcpNormalizer::validate_paws_timestamp(TcpSegmentDescriptor& tsd)
             "packet PAWS timestamp way too far ahead of last packet %d %d...\n",
             tsd.get_pkt()->pkth->ts.tv_sec, peer_tracker->get_ts_last_packet() );
         //inc_tcp_discards();
-        ( ( TcpSession* )tsd.get_flow()->session )->tel->set_tcp_event(EVENT_BAD_TIMESTAMP);
+        ( ( TcpSession* )tsd.get_flow()->session )->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
         packet_dropper(tsd, NORM_TCP_OPT);
         return ACTION_BAD_PKT;
     }
@@ -320,10 +321,10 @@ bool TcpNormalizer::is_paws_ts_checked_required(TcpSegmentDescriptor&)
     return true;
 }
 
-int TcpNormalizer::validate_paws(TcpSegmentDescriptor& tsd, int* got_ts)
+int TcpNormalizer::validate_paws(TcpSegmentDescriptor& tsd)
 {
-    *got_ts = get_tcp_timestamp(tsd, false);
-    if ( *got_ts )
+    tcp_ts_flags = get_tcp_timestamp(tsd, false);
+    if ( tcp_ts_flags )
     {
         bool check_ts = is_paws_ts_checked_required(tsd);
 
@@ -339,18 +340,18 @@ int TcpNormalizer::validate_paws(TcpSegmentDescriptor& tsd, int* got_ts)
         //   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);
+        ( ( TcpSession* )tsd.get_flow()->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->flags &= ~TF_TSTAMP;
+            tracker->clear_tf_flags(TF_TSTAMP);
 
         packet_dropper(tsd, NORM_TCP_OPT);
         return ACTION_NOTHING;
     }
 }
 
-int TcpNormalizer::handle_paws_no_timestamps(TcpSegmentDescriptor& tsd, int* got_ts)
+int TcpNormalizer::handle_paws_no_timestamps(TcpSegmentDescriptor& tsd)
 {
     // if we are not handling timestamps, and this isn't a syn (only), and we have seen a
     // valid 3way setup, then we strip (nop) the timestamp option.  this includes the cases
@@ -358,23 +359,25 @@ int TcpNormalizer::handle_paws_no_timestamps(TcpSegmentDescriptor& tsd, int* got
     int strip = ( SetupOK(peer_tracker) && SetupOK(tracker) );
     DebugMessage(DEBUG_STREAM_STATE, "listener not doing timestamps...\n");
 
-    *got_ts = get_tcp_timestamp(tsd, strip);
-    if (*got_ts)
+    tcp_ts_flags = get_tcp_timestamp(tsd, strip);
+    if (tcp_ts_flags)
     {
-        if (!(peer_tracker->flags & TF_TSTAMP))
+        if (!(peer_tracker->get_tf_flags() & TF_TSTAMP))
         {
             // SYN skipped, may have missed talker's timestamp , so set it now.
-            peer_tracker->flags |= TF_TSTAMP;
             if (tsd.get_ts() == 0)
-                peer_tracker->flags |= TF_TSTAMP_ZERO;
+                peer_tracker->set_tf_flags(TF_TSTAMP | TF_TSTAMP_ZERO);
+            else
+                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->flags & TF_TSTAMP ) )
+        if ( ( paws_drop_zero_ts && ( tsd.get_ts() == 0 ) ) && ( 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);
+            ( ( TcpSession* )tsd.get_flow()->session )->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
             return ACTION_BAD_PKT;
         }
     }
@@ -382,7 +385,7 @@ int TcpNormalizer::handle_paws_no_timestamps(TcpSegmentDescriptor& tsd, int* got
     return ACTION_NOTHING;
 }
 
-int TcpNormalizer::handle_paws(TcpSegmentDescriptor& tsd, int* got_ts)
+int TcpNormalizer::handle_paws(TcpSegmentDescriptor& tsd)
 {
     if ( tsd.get_tcph()->is_rst() )
         return ACTION_NOTHING;
@@ -396,22 +399,22 @@ int TcpNormalizer::handle_paws(TcpSegmentDescriptor& tsd, int* got_ts)
     }
 #endif
 
-    if ((peer_tracker->flags & TF_TSTAMP) && (tracker->flags & TF_TSTAMP))
+    if ((peer_tracker->get_tf_flags() & TF_TSTAMP) && (tracker->get_tf_flags() & TF_TSTAMP))
     {
         DebugMessage(DEBUG_STREAM_STATE, "Checking timestamps for PAWS\n");
-        return validate_paws(tsd, got_ts);
+        return validate_paws(tsd);
     }
     else if (tsd.get_tcph()->is_syn_only())
     {
-        *got_ts = get_tcp_timestamp(tsd, 0);
-        if (*got_ts)
-            peer_tracker->flags |= TF_TSTAMP;
+        tcp_ts_flags = get_tcp_timestamp(tsd, 0);
+        if (tcp_ts_flags)
+            peer_tracker->set_tf_flags(TF_TSTAMP);
 
         return ACTION_NOTHING;
     }
     else
     {
-        return handle_paws_no_timestamps(tsd, got_ts);
+        return handle_paws_no_timestamps(tsd);
     }
 }
 
index 9a3f86d408f81dd30afe4bb04f40699478d10d0c..2df6dfb5c5afd72cf3d9bb61232e46a5e508a6be 100644 (file)
@@ -60,7 +60,7 @@ public:
     virtual void ecn_stripper(Packet*);
     virtual uint32_t get_stream_window(TcpSegmentDescriptor&);
     virtual uint32_t get_tcp_timestamp(TcpSegmentDescriptor&, bool strip);
-    virtual int handle_paws(TcpSegmentDescriptor&, int*);
+    virtual int handle_paws(TcpSegmentDescriptor&);
     virtual bool validate_rst(TcpSegmentDescriptor&);
     virtual int handle_repeated_syn(TcpSegmentDescriptor&) = 0;
     virtual uint16_t set_urg_offset(const tcp::TCPHdr* tcph, uint16_t dsize);
@@ -128,6 +128,16 @@ public:
         return tcp_ips_enabled;
     }
 
+    bool handling_timestamps(void) const
+    {
+        return tcp_ts_flags != TF_NONE;
+    }
+
+    uint32_t get_timestamp_flags(void)
+    {
+        return tcp_ts_flags;
+    }
+
 protected:
     TcpNormalizer(StreamPolicy, TcpSession*, TcpTracker*);
     virtual void trim_payload(TcpSegmentDescriptor&, uint32_t, NormMode, TcpPegCounts);
@@ -138,13 +148,13 @@ protected:
 
     virtual int validate_paws_timestamp(TcpSegmentDescriptor&);
     virtual bool is_paws_ts_checked_required(TcpSegmentDescriptor&);
-    virtual int validate_paws(TcpSegmentDescriptor&, int*);
-    virtual int handle_paws_no_timestamps(TcpSegmentDescriptor&, int*);
+    virtual int validate_paws(TcpSegmentDescriptor&);
+    virtual int handle_paws_no_timestamps(TcpSegmentDescriptor&);
 
     StreamPolicy os_policy;
-    TcpSession* session;
-    TcpTracker* tracker;
-    TcpTracker* peer_tracker;
+    TcpSession* session = nullptr;
+    TcpTracker* tracker = nullptr;
+    TcpTracker* peer_tracker = nullptr;
     bool tcp_ips_enabled;
     NormMode trim_syn;
     NormMode trim_rst;
@@ -153,8 +163,9 @@ protected:
     NormMode strip_ecn;
     NormMode tcp_block;
     NormMode opt_block;
-    int32_t paws_ts_fudge;
-    bool paws_drop_zero_ts;
+    int32_t paws_ts_fudge = 0;
+    bool paws_drop_zero_ts = true;
+    int tcp_ts_flags = 0;
 };
 
 #endif
index ec43fd7d48950839ee884d74a82e48fb4f9cf0a6..bcc71368c937c5fb6e2887c613c93ef288fe73fc 100644 (file)
@@ -187,7 +187,7 @@ public:
     { }
 
     bool validate_rst(TcpSegmentDescriptor&) override;
-    int handle_paws(TcpSegmentDescriptor&, int*) override;
+    int handle_paws(TcpSegmentDescriptor&) override;
     int handle_repeated_syn(TcpSegmentDescriptor&) override;
 };
 
@@ -269,7 +269,7 @@ static inline int handle_repeated_syn_mswin(TcpTracker* talker, TcpTracker* list
     /* Windows has some strange behaviour here.  If the sequence of the reset is the
      *  next expected sequence, it Resets.  Otherwise it ignores the 2nd SYN.
      */
-    if (SEQ_EQ(tsd.get_seq(), listener->r_nxt_ack))
+    if (SEQ_EQ(tsd.get_seg_seq(), listener->r_nxt_ack))
     {
         DebugMessage(DEBUG_STREAM_STATE,
             "Got syn on established windows ssn, which causes Reset, bailing\n");
@@ -290,7 +290,7 @@ static inline int handle_repeated_syn_bsd(TcpTracker* talker, TcpSegmentDescript
     TcpSession* session)
 {
     /* If its not a retransmission of the actual SYN... RESET */
-    if (!SEQ_EQ(tsd.get_seq(), talker->get_iss()))
+    if (!SEQ_EQ(tsd.get_seg_seq(), talker->get_iss()))
     {
         DebugMessage(DEBUG_STREAM_STATE,
             "Got syn on established ssn, which causes Reset, bailing\n");
@@ -312,10 +312,10 @@ static inline bool paws_3whs_zero_ts_not_supported(TcpTracker* talker, TcpTracke
 {
     bool check_ts = true;
 
-    if (talker->flags & TF_TSTAMP_ZERO)
+    if (talker->get_tf_flags() & TF_TSTAMP_ZERO)
     {
-        talker->flags &= ~TF_TSTAMP;
-        listener->flags &= ~TF_TSTAMP;
+        talker->clear_tf_flags(TF_TSTAMP);
+        listener->clear_tf_flags(TF_TSTAMP);
         check_ts = false;
     }
 
@@ -328,13 +328,13 @@ static inline bool paws_3whs_zero_ts_supported(TcpTracker* talker, TcpTracker* l
 {
     bool check_ts = true;
 
-    if ( talker->flags & TF_TSTAMP_ZERO )
+    if ( talker->get_tf_flags() & TF_TSTAMP_ZERO )
     {
-        talker->flags &= ~TF_TSTAMP_ZERO;
-        if ( SEQ_EQ(listener->r_nxt_ack, tsd.get_seq() ) )
+        talker->clear_tf_flags(TF_TSTAMP_ZERO);
+        if ( SEQ_EQ(listener->r_nxt_ack, tsd.get_seg_seq() ) )
         {
             // Ignore timestamp for this first packet, save to check on next
-            talker->ts_last = tsd.get_ts();
+            talker->set_ts_last(tsd.get_ts() );
             check_ts = false;
         }
     }
@@ -452,7 +452,8 @@ bool TcpNormalizerHpux11::validate_rst(TcpSegmentDescriptor& tsd)
 bool TcpNormalizerHpux11::is_paws_ts_checked_required(TcpSegmentDescriptor& tsd)
 {
     /* HPUX 11 ignores timestamps for out of order segments */
-    if ((tracker->flags & TF_MISSING_PKT) || !SEQ_EQ(tracker->r_nxt_ack, tsd.get_seq()))
+    if ((tracker->get_tf_flags() & TF_MISSING_PKT) || !SEQ_EQ(tracker->r_nxt_ack,
+        tsd.get_seg_seq()))
         return false;
     else
         return true;
@@ -509,14 +510,14 @@ bool TcpNormalizerProxy::validate_rst(TcpSegmentDescriptor& tsd)
     {
         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_seq(), tracker->r_nxt_ack +
+            tsd.get_end_seq(), tracker->r_win_base, tsd.get_seg_seq(), tracker->r_nxt_ack +
             get_stream_window(tsd));
     }
 
     return false;
 }
 
-int TcpNormalizerProxy::handle_paws(TcpSegmentDescriptor&, int*)
+int TcpNormalizerProxy::handle_paws(TcpSegmentDescriptor&)
 {
     return ACTION_NOTHING;
 }
index f7ac2d3ffd7a45209b92dd5ca36744ab43a0b2ce..7ba1bb1359f635e22a5a549c9052bf52fcae2127 100644 (file)
@@ -202,10 +202,10 @@ void TcpReassembler::queue_reassembly_segment(TcpSegmentNode* prev, TcpSegmentNo
 
 bool TcpReassembler::is_segment_fasttrack(TcpSegmentNode* tail, TcpSegmentDescriptor& tsd)
 {
-    DebugFormat(DEBUG_STREAM_STATE,  "Checking seq for fast track: %X > %X\n", tsd.get_seq(),
+    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_seq(), tail->seq + tail->payload_size) )
+    if ( SEQ_EQ(tsd.get_seg_seq(), tail->seq + tail->payload_size) )
         return true;
 
     return false;
@@ -249,7 +249,7 @@ int TcpReassembler::add_reassembly_segment(TcpSegmentDescriptor& tsd, int16_t le
     }
 
     // FIXIT-L don't allocate overlapped part
-    tsn = TcpSegmentNode::init(tsd.get_pkt()->pkth->ts, tsd.get_pkt()->data, tsd.get_pkt()->dsize);
+    tsn = TcpSegmentNode::init(tsd);
     if ( !tsn )
         return STREAM_INSERT_FAILED;
     else if ( TcpSegmentNode::needs_pruning() )
@@ -266,7 +266,7 @@ int TcpReassembler::add_reassembly_segment(TcpSegmentDescriptor& tsd, int16_t le
     // FIXIT - 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_pkt()->dsize);
+    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;
@@ -285,7 +285,7 @@ int TcpReassembler::add_reassembly_segment(TcpSegmentDescriptor& tsd, int16_t le
 int TcpReassembler::dup_reassembly_segment(Packet* p, TcpSegmentNode* left,
     TcpSegmentNode** retSeg)
 {
-    TcpSegmentNode* tsn = TcpSegmentNode::init(left->tv, left->payload, left->payload_size);
+    TcpSegmentNode* tsn = TcpSegmentNode::init(*left);
     if ( !tsn )
         return STREAM_INSERT_FAILED;
     if ( TcpSegmentNode::needs_pruning() )
@@ -414,15 +414,15 @@ int TcpReassembler::purge_to_seq(uint32_t flush_seq)
 
     if ( !server_side )
     {
-        int32_t delta = last_ts - session->server->ts_last;
+        int32_t delta = last_ts - session->server->get_ts_last();
         if ( delta > 0 )
-            session->server->ts_last = last_ts;
+            session->server->set_ts_last(last_ts);
     }
     else
     {
-        int32_t delta = last_ts - session->client->ts_last;
+        int32_t delta = last_ts - session->client->get_ts_last();
         if ( delta > 0 )
-            session->client->ts_last = last_ts;
+            session->client->set_ts_last(last_ts);
     }
 
     return purged_bytes;
@@ -467,8 +467,7 @@ int TcpReassembler::purge_flushed_ackd(void)
 
 void TcpReassembler::show_rebuilt_packet(Packet* pkt)
 {
-    if ( ( session->config->flags & STREAM_CONFIG_SHOW_PACKETS )
-        || ( session->config->flags & STREAM_CONFIG_SHOW_PACKETS ) )
+    if ( session->config->flags & STREAM_CONFIG_SHOW_PACKETS )
     {
         LogFlow(pkt);
         LogNetData(pkt->data, pkt->dsize, pkt);
@@ -564,12 +563,12 @@ int TcpReassembler::flush_data_segments(Packet* p, uint32_t toSeq, uint8_t* flus
         // FIXIT-L FIN may be in toSeq causing bogus gap counts.
         if (((tsn->next && (tsn->seq + tsn->payload_size != tsn->next->seq))
             || (!tsn->next && (tsn->seq + tsn->payload_size < toSeq)))
-            && !(tracker->flags & TF_FIRST_PKT_MISSING))
+            && !(tracker->get_tf_flags() & TF_FIRST_PKT_MISSING))
         {
             if ( tsn->next )
                 seglist.next = tsn->next;
 
-            tracker->flags |= TF_MISSING_PKT;
+            tracker->set_tf_flags(TF_MISSING_PKT);
             break;
         }
         seglist.next = tsn->next;
@@ -698,23 +697,18 @@ int TcpReassembler::_flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
         const uint8_t* s5_pkt_end = s5_pkt->data + s5_pkt->max_dsize;
         flushed_bytes = flush_data_segments(p, stop_seq, ( uint8_t* )s5_pkt->data, s5_pkt_end);
 
-        if ( !flushed_bytes )
+        if ( flushed_bytes == 0 )
             break; /* No more data... bail */
 
-        else if ( !s5_pkt->dsize )
-        {
-            tcpStats.rebuilt_buffers++;
-            bytes_processed += flushed_bytes;
-        }
-        else
-        {
-            s5_pkt->packet_flags |= ( PKT_REBUILT_STREAM | PKT_STREAM_EST );
-
-            if ( ( p->packet_flags & PKT_PDU_TAIL ) )
-                s5_pkt->packet_flags |= PKT_PDU_TAIL;
+        bytes_processed += flushed_bytes;
+        seglist_base_seq += flushed_bytes;
 
-            tcpStats.rebuilt_packets++;
-            bytes_processed += flushed_bytes;
+        if ( s5_pkt->dsize )
+        {
+            if ( p->packet_flags & PKT_PDU_TAIL )
+                s5_pkt->packet_flags |= ( PKT_REBUILT_STREAM | PKT_STREAM_EST | PKT_PDU_TAIL );
+            else
+                s5_pkt->packet_flags |= ( PKT_REBUILT_STREAM | PKT_STREAM_EST );
 
             // FIXIT - this came with merge should it be here?
             //s5_pkt->application_protocol_ordinal =
@@ -724,32 +718,30 @@ int TcpReassembler::_flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
             tcpStats.rebuilt_packets++;
             tcpStats.rebuilt_bytes += flushed_bytes;
 
-            {
-                ProfileExclude profile_exclude(s5TcpFlushPerfStats);
-                Snort::detect_rebuilt_packet(s5_pkt);
-            }
+            ProfileExclude profile_exclude(s5TcpFlushPerfStats);
+            Snort::detect_rebuilt_packet(s5_pkt);
+        }
+        else
+        {
+            tcpStats.rebuilt_buffers++;
+            tcpStats.rebuilt_buffers++;
         }
-
-        seglist_base_seq += flushed_bytes;
 
         DebugFormat(DEBUG_STREAM_STATE, "setting seglist_base_seq to 0x%X\n", seglist_base_seq);
 
         if ( tracker->splitter )
             tracker->splitter->update();
 
-        // TBD abort should be by PAF callback only since
-        // recovery may be possible in some cases
-        if ( tracker->flags & TF_MISSING_PKT )
+        // FIXIT - abort should be by PAF callback only since recovery may be
+        // possible in some cases
+        if ( tracker->get_tf_flags() & TF_MISSING_PKT )
         {
-            tracker->flags |= TF_MISSING_PREV_PKT;
-            tracker->flags |= TF_PKT_MISSED;
-            tracker->flags &= ~TF_MISSING_PKT;
+            tracker->set_tf_flags(TF_MISSING_PREV_PKT | TF_PKT_MISSED);
+            tracker->clear_tf_flags(TF_MISSING_PKT);
             tcpStats.gaps++;
         }
         else
-        {
-            tracker->flags &= ~TF_MISSING_PREV_PKT;
-        }
+            tracker->clear_tf_flags(TF_MISSING_PREV_PKT);
     }
     while ( seglist.next and flush_data_ready( ) );
 
@@ -776,27 +768,25 @@ int TcpReassembler::flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
         return 0;
     }
 
-    if ( !flush_data_ready( ) && !( tracker->flags & TF_FORCE_FLUSH ) )
+    if ( !flush_data_ready( ) && !( tracker->get_tf_flags() & TF_FORCE_FLUSH ) )
     {
         DebugMessage(DEBUG_STREAM_STATE, "only 1 packet in seglist no need to flush\n");
         return 0;
     }
 
-    tracker->flags &= ~TF_MISSING_PKT;
-    tracker->flags &= ~TF_MISSING_PREV_PKT;
+    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)
-        && !( tracker->flags & TF_FIRST_PKT_MISSING ) )
+        && !( tracker->get_tf_flags() & TF_FIRST_PKT_MISSING ) )
     {
         uint32_t missed = seglist.next->seq - seglist_base_seq;
 
         if ( missed <= bytes )
             bytes -= missed;
 
-        tracker->flags |= TF_MISSING_PREV_PKT;
-        tracker->flags |= TF_PKT_MISSED;
+        tracker->set_tf_flags(TF_MISSING_PREV_PKT | TF_PKT_MISSED);
 
         tcpStats.gaps++;
         seglist_base_seq = seglist.next->seq;
@@ -805,7 +795,7 @@ int TcpReassembler::flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
             return 0;
     }
 
-    tracker->flags &= ~TF_FIRST_PKT_MISSING;
+    tracker->clear_tf_flags(TF_FIRST_PKT_MISSING);
 
     return _flush_to_seq(bytes, p, pkt_flags);
 }
@@ -896,12 +886,12 @@ void TcpReassembler::final_flush(Packet* p, PegCount& peg, uint32_t dir)
         tmp_pcap_hdr->ts.tv_usec = seglist.head->tv.tv_usec;
     }
 
-    tracker->flags |= TF_FORCE_FLUSH;
+    tracker->set_tf_flags(TF_FORCE_FLUSH);
 
     if ( flush_stream(p, dir) )
         purge_flushed_ackd( );
 
-    tracker->flags &= ~TF_FORCE_FLUSH;
+    tracker->clear_tf_flags(TF_FORCE_FLUSH);
 }
 
 void TcpReassembler::flush_queued_segments(Flow* flow, bool clear, Packet* p)
@@ -1219,7 +1209,7 @@ void TcpReassembler::insert_segment_in_empty_seglist(TcpSegmentDescriptor& tsd)
     const tcp::TCPHdr* tcph = tsd.get_tcph();
 
     uint32_t overlap = 0;
-    uint32_t seq = tsd.get_seq();
+    uint32_t seq = tsd.get_seg_seq();
 
     if ( tcph->is_syn() )
         seq++;
@@ -1227,8 +1217,8 @@ void TcpReassembler::insert_segment_in_empty_seglist(TcpSegmentDescriptor& tsd)
     if ( SEQ_GT(tracker->r_win_base, seq) )
     {
         DebugMessage(DEBUG_STREAM_STATE, "segment overlaps ack'd data...\n");
-        overlap = tracker->r_win_base - tsd.get_seq();
-        if ( overlap >= tsd.get_pkt()->dsize )
+        overlap = 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");
             return;
@@ -1236,11 +1226,11 @@ void TcpReassembler::insert_segment_in_empty_seglist(TcpSegmentDescriptor& tsd)
     }
 
     // BLOCK add new block to seglist containing data
-    add_reassembly_segment(tsd, tsd.get_pkt()->dsize, overlap, 0, tsd.get_seq() + overlap, NULL);
+    add_reassembly_segment(tsd, tsd.get_seg_len(), overlap, 0, tsd.get_seg_seq() + overlap, NULL);
 
     DebugFormat(DEBUG_STREAM_STATE,
         "Attached new queue to seglist, %d bytes queued, base_seq 0x%X\n",
-        tsd.get_pkt()->dsize - overlap, seglist_base_seq);
+        tsd.get_seg_len() - overlap, seglist_base_seq);
 }
 
 void TcpReassembler::init_overlap_editor(TcpSegmentDescriptor& tsd)
@@ -1258,15 +1248,15 @@ void TcpReassembler::init_overlap_editor(TcpSegmentDescriptor& tsd)
 
     if ( seglist.head && seglist.tail )
     {
-        if ( SEQ_GT(tsd.get_seq(), seglist.head->seq) )
-            dist_head = tsd.get_seq() - seglist.head->seq;
+        if ( SEQ_GT(tsd.get_seg_seq(), seglist.head->seq) )
+            dist_head = tsd.get_seg_seq() - seglist.head->seq;
         else
-            dist_head = seglist.head->seq - tsd.get_seq();
+            dist_head = seglist.head->seq - tsd.get_seg_seq();
 
-        if ( SEQ_GT(tsd.get_seq(), seglist.tail->seq) )
-            dist_tail = tsd.get_seq() - seglist.tail->seq;
+        if ( SEQ_GT(tsd.get_seg_seq(), seglist.tail->seq) )
+            dist_tail = tsd.get_seg_seq() - seglist.tail->seq;
         else
-            dist_tail = seglist.tail->seq - tsd.get_seq();
+            dist_tail = seglist.tail->seq - tsd.get_seg_seq();
     }
     else
         dist_head = dist_tail = 0;
@@ -1286,7 +1276,7 @@ void TcpReassembler::init_overlap_editor(TcpSegmentDescriptor& tsd)
                 );
 
             right = tsn;
-            if ( SEQ_GEQ(right->seq, tsd.get_seq() ) )
+            if ( SEQ_GEQ(right->seq, tsd.get_seg_seq() ) )
                 break;
             left = right;
         }
@@ -1309,7 +1299,7 @@ void TcpReassembler::init_overlap_editor(TcpSegmentDescriptor& tsd)
                 );
 
             left = tsn;
-            if ( SEQ_LT(left->seq, tsd.get_seq() ) )
+            if ( SEQ_LT(left->seq, tsd.get_seg_seq() ) )
                 break;
             right = left;
         }
@@ -1332,7 +1322,8 @@ int TcpReassembler::insert_segment_in_seglist(TcpSegmentDescriptor& tsd)
 
     DebugFormat(DEBUG_STREAM_STATE,
         "Queuing %d bytes on stream!\nbase_seq: %X seq: %X  seq_end: %X\n",
-        tsd.get_end_seq() - tsd.get_seq(), seglist_base_seq, tsd.get_seq(), tsd.get_end_seq());
+        tsd.get_end_seq() - tsd.get_seg_seq(), seglist_base_seq, tsd.get_seg_seq(),
+        tsd.get_end_seq());
 
     DebugFormat(DEBUG_STREAM_STATE, "%d segments on seglist\n", get_pending_segment_count(0));
     DebugMessage(DEBUG_STREAM_STATE, "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n");
@@ -1348,7 +1339,7 @@ int TcpReassembler::insert_segment_in_seglist(TcpSegmentDescriptor& tsd)
             seglist.tail->seq, seglist.tail->payload_size);
 
         // BLOCK add to existing block and/or allocate new block
-        rc = add_reassembly_segment(tsd, tsd.get_pkt()->dsize, 0, 0, tsd.get_seq(), left);
+        rc = add_reassembly_segment(tsd, tsd.get_seg_len(), 0, 0, tsd.get_seg_seq(), left);
         return rc;
     }
 
@@ -1364,7 +1355,7 @@ int TcpReassembler::insert_segment_in_seglist(TcpSegmentDescriptor& tsd)
     if ( keep_segment )
     {
         /* Adjust slide so that is correct relative to orig seq */
-        slide = seq - tsd.get_seq();
+        slide = seq - tsd.get_seg_seq();
         rc = add_reassembly_segment(tsd, len, slide, trunc_len, seq, left);
     }
     else
@@ -1388,21 +1379,15 @@ int TcpReassembler::queue_packet_for_reassembly(TcpSegmentDescriptor& tsd)
         return STREAM_INSERT_OK;
     }
 
-    if ( SEQ_GT(tracker->r_win_base, tsd.get_seq() ) )
+    if ( SEQ_GT(tracker->r_win_base, tsd.get_seg_seq() ) )
     {
-        uint32_t offset = tracker->r_win_base - tsd.get_seq();
+        int32_t offset = tracker->r_win_base - tsd.get_seg_seq();
 
-        if ( offset < tsd.get_pkt()->dsize )
+        if ( offset < tsd.get_seg_len() )
         {
-            tsd.set_seq(tsd.get_seq() + offset);
-            tsd.get_pkt()->data += offset;
-            tsd.get_pkt()->dsize -= (uint16_t)offset;
-
+            tsd.slide_segment_in_rcv_window(offset);
             rc = insert_segment_in_seglist(tsd);
-
-            tsd.get_pkt()->dsize += (uint16_t)offset;
-            tsd.get_pkt()->data -= offset;
-            tsd.set_seq(tsd.get_seq() - offset);
+            tsd.slide_segment_in_rcv_window(-offset);
         }
     }
     else
index 878e3a9c08391a6582ba2e7f3b4ed4ab9c2a0cd5..0363c19efc700919bf4885cec0216f6be4314442 100644 (file)
@@ -110,15 +110,8 @@ public:
     void trace_segments(void);
 
 protected:
-    bool server_side;
-    TcpTracker* tracker;
-    uint8_t ignore_dir;
-    uint8_t packet_dir;
-    uint32_t flush_count; /* number of flushed queued segments */
-    uint32_t xtradata_mask; /* extra data available to log */
-
     TcpReassembler(TcpSession* session, TcpTracker* tracker, StreamPolicy os_policy, bool server) :
-        server_side(server), tracker(tracker), flush_count(0), xtradata_mask(0)
+       server_side(server), tracker(tracker)
     {
         this->session = session;
         set_tcp_reassembly_policy(os_policy);
@@ -172,6 +165,13 @@ protected:
     void fallback(void);
     uint32_t flush_pdu_ackd(uint32_t* flags);
     int purge_to_seq(uint32_t flush_seq);
+
+    bool server_side;
+    TcpTracker* 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 */
 };
 
 #endif
index 2dfca120b0c46515e97f7b9ec8058835716fb330..6285d1af881ac5cab1cb1b562263b6cb4b0bf2f9 100644 (file)
@@ -40,6 +40,15 @@ TcpSegmentNode::~TcpSegmentNode()
 //-------------------------------------------------------------------------
 // TcpSegment stuff
 //-------------------------------------------------------------------------
+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)
+{
+    return init(tsn.tv, tsn.payload, tsn.payload_size);
+}
 
 TcpSegmentNode* TcpSegmentNode::init(const struct timeval& tv, const uint8_t* data, unsigned dsize)
 {
index 90b05c024dd05a6f9296308abe85a0cdc6731936..635d1bfe5d4047cb67c785a7dd8eb971b071d043 100644 (file)
@@ -26,6 +26,8 @@
 #include "protocols/packet.h"
 #include "flow/memcap.h"
 
+#include "stream/libtcp/tcp_segment_descriptor.h"
+
 extern THREAD_LOCAL Memcap* tcp_memcap;
 
 //-----------------------------------------------------------------
@@ -40,6 +42,8 @@ public:
     TcpSegmentNode();
     virtual ~TcpSegmentNode();
 
+    static TcpSegmentNode* init(TcpSegmentDescriptor& tsd);
+    static TcpSegmentNode* init(TcpSegmentNode& tsn);
     static TcpSegmentNode* init(const struct timeval&, const uint8_t*, unsigned);
     static bool needs_pruning(void)
     {
index cb6788d9ccdf7fbfb212363d9c681c9641f974f0..cd2a020d9996b504308aacdef56aab4298d4dbb8 100644 (file)
@@ -111,6 +111,134 @@ const char* const flush_policy_names[] =
 };
 #endif
 
+DEBUG_WRAP(const char* t = NULL; const char* l = NULL; )
+
+TcpSession::TcpSession(Flow* flow) :
+    Session(flow), client(new TcpTracker(true)), server(new TcpTracker(false))
+{
+    // initialize stream tracker state machine...
+    new TcpStateNone(tsm, *this);
+    new TcpStateClosed(tsm, *this);
+    new TcpStateListen(tsm, *this);
+    new TcpStateSynSent(tsm, *this);
+    new TcpStateSynRecv(tsm, *this);
+    new TcpStateEstablished(tsm, *this);
+    new TcpStateFinWait1(tsm, *this);
+    new TcpStateFinWait2(tsm, *this);
+    new TcpStateClosing(tsm, *this);
+    new TcpStateCloseWait(tsm, *this);
+    new TcpStateLastAck(tsm, *this);
+    new TcpStateTimeWait(tsm, *this);
+}
+
+TcpSession::~TcpSession(void)
+{
+    if (tcp_init)
+    {
+        clear_session(1);
+
+        delete client;
+        delete server;
+    }
+}
+
+void TcpSession::reset(void)
+{
+    if (tcp_init)
+        clear_session(2);
+}
+
+bool TcpSession::setup(Packet*)
+{
+    // FIXIT-L this it should not be necessary to reset here
+    reset();
+
+    client->init_tracker( );
+    server->init_tracker( );
+    lws_init = tcp_init = false;
+    no_3whs = false;
+    pkt_action_mask = ACTION_NOTHING;
+    ecn = 0;
+    ingress_index = egress_index = 0;
+    ingress_group = egress_group = 0;
+    daq_flags = address_space_id = 0;
+
+    tcpStats.sessions++;
+    return true;
+}
+
+void TcpSession::cleanup(void)
+{
+    // this flushes data and then calls TcpSessionClear()
+    cleanup_session(1);
+}
+
+void TcpSession::clear(void)
+{
+    if ( tcp_init )
+        // this does NOT flush data
+        clear_session(1);
+}
+
+void TcpSession::restart(Packet* p)
+{
+    // sanity check since this is called externally
+    assert(p->ptrs.tcph);
+
+    TcpTracker* talker, * listener;
+
+    if (p->packet_flags & PKT_FROM_SERVER)
+    {
+        talker = server;
+        listener = client;
+    }
+    else
+    {
+        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);
+
+    if (p->ptrs.tcph->is_ack())
+        talker->reassembler->flush_on_ack_policy(p);
+}
+
+void TcpSession::print(void)
+{
+    char buf[64];
+
+    LogMessage("TcpSession:\n");
+    sfip_ntop(&flow->server_ip, buf, sizeof(buf));
+    LogMessage("    server IP:          %s\n", buf);
+    sfip_ntop(&flow->client_ip, buf, sizeof(buf));
+    LogMessage("    client IP:          %s\n", buf);
+    LogMessage("    server port:        %d\n", flow->server_port);
+    LogMessage("    client port:        %d\n", flow->client_port);
+    LogMessage("    flags:              0x%X\n", flow->get_session_flags());
+    LogMessage("Client Tracker:\n");
+    client->print();
+    LogMessage("Server Tracker:\n");
+    server->print();
+}
+
+void TcpSession::set_splitter(bool to_server, StreamSplitter* ss)
+{
+    TcpTracker* trk = ( to_server ) ? server : client;
+
+    trk->set_splitter(ss);
+}
+
+StreamSplitter* TcpSession::get_splitter(bool to_server)
+{
+    if ( to_server )
+        return server->splitter;
+    else
+        return client->splitter;
+}
+
 void TcpSession::update_perf_base_state(char newState)
 {
     uint32_t session_flags = flow->get_session_flags();
@@ -281,153 +409,6 @@ static inline int is_mac_address_valid(TcpTracker* talker, TcpTracker* listener,
     return event_code;
 }
 
-#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
-//
-static inline int ValidSeq(const Packet* p, Flow* flow, TcpTracker* st, TcpSegmentDescriptor& tsd)
-{
-    uint32_t win = st->normalizer->get_stream_window(flow, st, tsd);
-
-    if ( !p->dsize )
-    {
-        if ( !win )
-        {
-            return ( tsd.get_seq() == st->r_win_base );
-        }
-        return SEQ_LEQ(st->r_win_base, tsd.get_seq()) &&
-               SEQ_LT(tsd.get_seq(), st->r_win_base+win);
-    }
-    if ( !win )
-        return 0;
-
-    if ( SEQ_LEQ(st->r_win_base, tsd.get_seq()) &&
-        SEQ_LT(tsd.get_seq(), st->r_win_base+win) )
-        return 1;
-
-    return SEQ_LEQ(st->r_win_base, tsd.get_end_seq()) &&
-           SEQ_LT(tsd.get_end_seq(), st->r_win_base+win);
-}
-
-#else
-static inline int ValidSeq(TcpTracker* st, TcpSegmentDescriptor& tsd)
-{
-    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(), st->r_win_base, tsd.get_seq(), st->r_nxt_ack +
-        st->normalizer->get_stream_window(tsd));
-
-    if ( SEQ_LT(st->r_nxt_ack, st->r_win_base) )
-        left_seq = st->r_nxt_ack;
-    else
-        left_seq = st->r_win_base;
-
-    if ( tsd.get_pkt()->dsize )
-        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 = st->normalizer->get_stream_window(tsd);
-
-        if ( SEQ_LEQ(tsd.get_seq(), st->r_win_base + win) )
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "seq is within window!\n");
-            return 1;
-        }
-        else
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "seq is past the end of the window!\n");
-        }
-    }
-    else
-    {
-        DebugMessage(DEBUG_STREAM_STATE, "end_seq is before win_base\n");
-    }
-    return 0;
-}
-
-#endif
-
-static inline void UpdateSsn(TcpTracker* rcv, TcpTracker* snd, TcpSegmentDescriptor& tsd)
-{
-#if 0
-    // FIXIT-L these checks are a hack to avoid off by one normalization
-    // due to FIN ... if last segment filled a hole, r_nxt_ack is not at
-    // end of data, FIN is ignored so sequence isn't bumped, and this
-    // forces seq-- on ACK of FIN.  :(
-    if ( rcv->get_tcp_state() == TcpStreamTracker::TCP_ESTABLISHED &&
-        rcv->s_mgr.state_queue == TcpStreamTracker::TCP_STATE_NONE &&
-        Normalize_IsEnabled(NORM_TCP_IPS) )
-    {
-        // walk the seglist until a gap or tsd.ack whichever is first
-        // if a gap exists prior to ack, move ack back to start of gap
-        TcpSegment* seg = snd->seglist;
-
-        // FIXIT-L must check ack oob with empty seglist
-        // FIXIT-L add lower gap bound to tracker for efficiency?
-        while ( seg )
-        {
-            uint32_t seq = seg->seq + seg->size;
-            if ( SEQ_LEQ(tsd.get_ack(), seq) )
-                break;
-
-            seg = seg->next;
-
-            if ( !seg || seg->seq > seq )
-            {
-                // normalize here
-                tsd.set_ack(seq);
-                tcph->th_ack = htonl(seq);
-                p->packet_flags |= PKT_MODIFIED;
-                break;
-            }
-        }
-    }
-#endif
-    // ** if we don't see a segment, we can't track seq at ** below
-    // so we update the seq by the ack if it is beyond next expected
-    if ( SEQ_GT(tsd.get_ack(), rcv->get_snd_una() ) )
-        rcv->set_snd_una(tsd.get_ack() );
-
-    // ** this is how we track the last seq number sent
-    // as is l_unackd is the "last left" seq recvd
-    snd->set_snd_una(tsd.get_seq() );
-
-    if ( SEQ_GT(tsd.get_end_seq(), snd->get_snd_nxt() ) )
-        snd->set_snd_nxt(tsd.get_end_seq() );
-
-    if ( !SEQ_EQ(snd->r_win_base, tsd.get_ack() ) )
-    {
-        snd->small_seg_count = 0;
-    }
-#ifdef S5_PEDANTIC
-    if ( SEQ_GT(tsd.get_ack(), snd->r_win_base) &&
-        SEQ_LEQ(tsd.get_ack(), snd->r_nxt_ack) )
-#else
-    if ( SEQ_GT(tsd.get_ack(), snd->r_win_base) )
-#endif
-        snd->r_win_base = tsd.get_ack();
-
-    snd->set_snd_wnd(tsd.get_win() );
-}
-
 void TcpSession::clear_session(int freeApplicationData)
 {
     // update stats
@@ -475,7 +456,7 @@ void TcpSession::clear_session(int freeApplicationData)
         flow->clear(freeApplicationData);
 
     // generate event for rate filtering
-    tel->EventInternal(INTERNAL_EVENT_SESSION_DEL);
+    tel.EventInternal(INTERNAL_EVENT_SESSION_DEL);
 
     DebugFormat(DEBUG_STREAM_STATE, "After cleaning, %lu bytes in use\n", tcp_memcap->used());
 
@@ -494,55 +475,6 @@ void TcpSession::cleanup_session(int freeApplicationData, Packet* p)
     clear_session(freeApplicationData);
 }
 
-#if 0
-static inline int IsWellFormed(Packet* p, TcpTracker* ts)
-{
-    return ( !ts->mss || (p->dsize <= ts->mss) );
-}
-
-#endif
-
-void TcpSession::FinishServerInit(TcpSegmentDescriptor& tsd)
-{
-    const tcp::TCPHdr* tcph = tsd.get_tcph();
-
-    server->set_snd_wnd(tsd.get_win() );
-    server->set_snd_una(tsd.get_seq() + 1);
-    server->set_snd_nxt(server->get_snd_una() );
-    server->set_iss(tsd.get_seq() );
-
-    client->r_nxt_ack = tsd.get_end_seq();
-
-    if ( tcph->is_fin() )
-        server->set_snd_nxt(server->get_snd_nxt() - 1);
-
-    if ( !( flow->session_state & STREAM_STATE_MIDSTREAM ) )
-    {
-        server->set_tcp_state(TcpStreamTracker::TCP_SYN_RECV);
-        client->reassembler->set_seglist_base_seq(server->get_snd_una() );
-        client->r_win_base = tsd.get_end_seq();
-    }
-    else
-    {
-        client->reassembler->set_seglist_base_seq(tsd.get_seq() );
-        client->r_win_base = tsd.get_seq();
-    }
-
-    server->flags |= server->normalizer->get_tcp_timestamp(tsd, false);
-    server->ts_last = tsd.get_ts();
-    if (server->ts_last == 0)
-        server->flags |= TF_TSTAMP_ZERO;
-    else
-        server->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
-
-    server->flags |= tsd.init_mss(&server->mss);
-    server->flags |= tsd.init_wscale(&server->wscale);
-
-#ifdef DEBUG_STREAM_EX
-    PrintTcpSession(ssn);
-#endif
-}
-
 void TcpSession::EndOfFileHandle(Packet* p)
 {
     flow->call_handlers(p, true);
@@ -559,7 +491,7 @@ bool TcpSession::flow_exceeds_config_thresholds(TcpTracker* rcv, TcpSegmentDescr
     if ( ( config->flags & STREAM_CONFIG_NO_ASYNC_REASSEMBLY ) && !flow->two_way_traffic() )
         return true;
 
-    if ( config->max_consec_small_segs && ( tsd.get_pkt()->dsize <
+    if ( config->max_consec_small_segs && ( tsd.get_seg_len() <
         config->max_consec_small_seg_size ) )
     {
         rcv->small_seg_count++;
@@ -568,7 +500,7 @@ bool TcpSession::flow_exceeds_config_thresholds(TcpTracker* rcv, TcpSegmentDescr
         {
             /* Above threshold, log it...  in this TCP policy,
              * action controlled by preprocessor rule. */
-            tel->EventMaxSmallSegsExceeded();
+            tel.EventMaxSmallSegsExceeded();
             /* Reset counter, so we're not too noisy */
             rcv->small_seg_count = 0;
         }
@@ -594,7 +526,7 @@ bool TcpSession::flow_exceeds_config_thresholds(TcpTracker* rcv, TcpSegmentDescr
 void TcpSession::process_tcp_stream(TcpTracker* rcv, TcpSegmentDescriptor& tsd)
 {
     DebugFormat(DEBUG_STREAM_STATE, "In ProcessTcpStream(), %d bytes to queue\n",
-        tsd.get_pkt()->dsize);
+        tsd.get_seg_len());
 
     if (tsd.get_pkt()->packet_flags & PKT_IGNORE)
         return;
@@ -611,7 +543,7 @@ void TcpSession::process_tcp_stream(TcpTracker* rcv, TcpSegmentDescriptor& tsd)
     if ( ( config->overlap_limit )
         && ( rcv->reassembler->get_overlap_count() > config->overlap_limit ) )
     {
-        tel->EventExcessiveOverlap();
+        tel.EventExcessiveOverlap();
         rcv->reassembler->set_overlap_count(0);
     }
 }
@@ -621,7 +553,7 @@ int TcpSession::process_tcp_data(TcpTracker* listener, TcpSegmentDescriptor& tsd
     Profile profile(s5TcpDataPerfStats);
 
     const tcp::TCPHdr* tcph = tsd.get_tcph();
-    uint32_t seq = tsd.get_seq();
+    uint32_t seq = tsd.get_seg_seq();
 
     if ( tcph->is_syn() )
     {
@@ -653,7 +585,7 @@ int TcpSession::process_tcp_data(TcpTracker* listener, TcpSegmentDescriptor& tsd
         if ( listener->s_mgr.state_queue == TcpStreamTracker::TCP_STATE_NONE )
             listener->r_nxt_ack = tsd.get_end_seq();
 
-        if (tsd.get_pkt()->dsize != 0)
+        if (tsd.get_seg_len() != 0)
         {
             if (!( flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD))
                 tsd.get_pkt()->packet_flags |= PKT_STREAM_ORDER_OK;
@@ -673,7 +605,7 @@ int TcpSession::process_tcp_data(TcpTracker* listener, TcpSegmentDescriptor& tsd
         // some cases.
         DebugFormat(DEBUG_STREAM_STATE,
             "out of order segment (tsd.seq: 0x%X l->r_nxt_ack: 0x%X!\n",
-            tsd.get_seq(), listener->r_nxt_ack);
+            tsd.get_seg_seq(), listener->r_nxt_ack);
 
         if (listener->s_mgr.state_queue == TcpStreamTracker::TCP_STATE_NONE)
         {
@@ -698,11 +630,11 @@ int TcpSession::process_tcp_data(TcpTracker* listener, TcpSegmentDescriptor& tsd
             }
         }
 
-        if (tsd.get_pkt()->dsize != 0)
+        if (tsd.get_seg_len() != 0)
         {
             if (!( flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD))
             {
-                if (!SEQ_LEQ((tsd.get_seq() + tsd.get_pkt()->dsize), listener->r_nxt_ack))
+                if (!SEQ_LEQ((tsd.get_seg_seq() + tsd.get_seg_len()), listener->r_nxt_ack))
                     flow->set_session_flags(SSNFLAG_STREAM_ORDER_BAD);
             }
             process_tcp_stream(listener, tsd);
@@ -778,11 +710,10 @@ void TcpSession::init_new_tcp_session(TcpSegmentDescriptor& tsd)
     flow->set_expire(tsd.get_pkt(), config->session_timeout);
 
     update_perf_base_state(TcpStreamTracker::TCP_SYN_SENT);
-    tel->EventInternal(INTERNAL_EVENT_SESSION_ADD);
+    tel.EventInternal(INTERNAL_EVENT_SESSION_ADD);
 
-    //assert( !tcp_init );
     tcp_init = true;
-    new_ssn = true;
+    lws_init = true;
 
     // FIXIT - this state is bogus... move to tracker init...
     tcpStats.created++;
@@ -804,25 +735,37 @@ void TcpSession::NewTcpSessionOnSynAck(TcpSegmentDescriptor& tsd)
     tcpStats.sessions_on_syn_ack++;
 }
 
-void TcpSession::update_session_state(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd)
+void TcpSession::update_timestamp_tracking(TcpSegmentDescriptor& tsd)
+{
+    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);
+        talker->set_ts_last(tsd.get_ts());
+    }
+}
+
+void TcpSession::update_session_on_syn_ack(void)
 {
     /* If session is already marked as established */
-    if (!(flow->session_state & STREAM_STATE_ESTABLISHED)
-        && (!require_3whs || config->midstream_allowed(tsd.get_pkt())))
+    if ( !( flow->session_state & STREAM_STATE_ESTABLISHED ) )
     {
-        /* If not requiring 3-way Handshake...
-           TCP session created on TH_SYN above, or maybe on SYN-ACK, or anything else
-           Need to update Lightweight session state */
-        if (tcph->is_syn_ack())
+        /* SYN-ACK from server */
+        if (flow->session_state != STREAM_STATE_NONE)
         {
-            /* SYN-ACK from server */
-            if (flow->session_state != STREAM_STATE_NONE)
-            {
-                flow->session_state |= STREAM_STATE_SYN_ACK;
-                update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
-            }
+            flow->session_state |= STREAM_STATE_SYN_ACK;
+            update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
         }
-        else if (tcph->is_ack() && (flow->session_state & STREAM_STATE_SYN_ACK))
+    }
+}
+
+void TcpSession::update_session_on_ack(void)
+{
+    /* If session is already marked as established */
+    if ( !( flow->session_state & STREAM_STATE_ESTABLISHED ) )
+    {
+        if ( flow->session_state & STREAM_STATE_SYN_ACK )
         {
             flow->session_state |= STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED;
             update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
@@ -830,30 +773,20 @@ void TcpSession::update_session_state(const tcp::TCPHdr* tcph, TcpSegmentDescrip
     }
 }
 
-void TcpSession::update_session_on_server_packet(const tcp::TCPHdr* tcph,
-    TcpSegmentDescriptor& tsd)
+void TcpSession::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;
 
-    if (tcp_init)
-    {
-        talker = server;
-        listener = client;
-    }
-
-    if ( talker and (talker->get_tcp_state() == TcpStreamTracker::TCP_LISTEN)
-        and tcph->is_syn_only() )
-    {
-        tel->set_tcp_event(EVENT_4WHS);
-    }
     /* If we picked this guy up midstream, finish the initialization */
-    if ((flow->session_state & STREAM_STATE_MIDSTREAM) && !(flow->session_state &
-        STREAM_STATE_ESTABLISHED))
+    if ( !( flow->session_state & STREAM_STATE_ESTABLISHED )
+        && ( flow->session_state & STREAM_STATE_MIDSTREAM ) )
     {
-        FinishServerInit(tsd);
-        if (tcph->are_flags_set(TH_ECE) && (flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY))
+        if (tsd.get_tcph()->are_flags_set(TH_ECE)
+            && (flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY))
             flow->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
 
         if (flow->get_session_flags() & SSNFLAG_SEEN_CLIENT)
@@ -875,14 +808,11 @@ void TcpSession::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);
-    if (tcp_init)
-    {
-        talker = client;
-        listener = server;
-    }
+    talker = client;
+    listener = server;
 
-    if ((flow->session_state & STREAM_STATE_MIDSTREAM)
-        && !(flow->session_state & STREAM_STATE_ESTABLISHED))
+    if ( !( flow->session_state & STREAM_STATE_ESTABLISHED )
+        && ( flow->session_state & STREAM_STATE_MIDSTREAM ) )
     {
         /* Midstream and seen server. */
         if (flow->get_session_flags() & SSNFLAG_SEEN_SERVER)
@@ -896,10 +826,12 @@ void TcpSession::update_session_on_client_packet(TcpSegmentDescriptor& tsd)
         flow->set_ttl(tsd.get_pkt(), true);
 }
 
-bool TcpSession::handle_syn_on_reset_session(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd)
+bool TcpSession::handle_syn_on_reset_session(TcpSegmentDescriptor& tsd)
 {
-    if ( !tcp_init || ( listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED )
-        || ( talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED ) )
+    const tcp::TCPHdr* tcph = tsd.get_tcph();
+    if ( tcph->is_syn() &&
+        ( ( listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED )
+        || ( talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED ) ) )
     {
         /* Listener previously issued a reset Talker is re-SYN-ing */
         // FIXIT-L this leads to bogus 129:20
@@ -933,7 +865,7 @@ bool TcpSession::handle_syn_on_reset_session(const tcp::TCPHdr* tcph, TcpSegment
             tcpStats.resyns++;
             listener = server;
             talker = client;
-            listener->normalizer->ecn_tracker( (tcp::TCPHdr*)tcph, require_3whs);
+            listener->normalizer->ecn_tracker( (tcp::TCPHdr*)tcph, config->require_3whs() );
             flow->update_session_flags(SSNFLAG_SEEN_CLIENT);
         }
         else if (tcph->is_syn_ack())
@@ -949,7 +881,7 @@ bool TcpSession::handle_syn_on_reset_session(const tcp::TCPHdr* tcph, TcpSegment
 
             listener = client;
             talker = server;
-            listener->normalizer->ecn_tracker( (tcp::TCPHdr*)tcph, require_3whs);
+            listener->normalizer->ecn_tracker( (tcp::TCPHdr*)tcph, config->require_3whs() );
             flow->update_session_flags(SSNFLAG_SEEN_SERVER);
         }
     }
@@ -965,497 +897,186 @@ void TcpSession::update_ignored_session(TcpSegmentDescriptor& tsd)
     // s5_ignored_session() may be disabling detection too soon if we really want to flush
     if (stream.ignored_session(flow, tsd.get_pkt()))
     {
-        if (talker && (talker->flags & TF_FORCE_FLUSH))
+        if ( talker && ( talker->get_tf_flags() & TF_FORCE_FLUSH ) )
         {
-            flush_talker(tsd.get_pkt());
-            talker->flags &= ~TF_FORCE_FLUSH;
+            flush_talker(tsd.get_pkt() );
+            talker->clear_tf_flags(TF_FORCE_FLUSH);
         }
-        if (listener && (listener->flags & TF_FORCE_FLUSH))
+
+        if ( listener && ( listener->get_tf_flags() & TF_FORCE_FLUSH ) )
         {
-            flush_listener(tsd.get_pkt());
-            listener->flags &= ~TF_FORCE_FLUSH;
+            flush_listener(tsd.get_pkt() );
+            listener->clear_tf_flags(TF_FORCE_FLUSH);
         }
+
         tsd.get_pkt()->packet_flags |= PKT_IGNORE;
         pkt_action_mask |= ACTION_DISABLE_INSPECTION;
     }
 }
 
-void TcpSession::handle_data_on_syn(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd)
+void TcpSession::handle_data_on_syn(TcpSegmentDescriptor& tsd)
 {
-    /* Handle data on SYN */
-    if ((tsd.get_pkt()->dsize) && tcph->is_syn())
+    /* MacOS accepts data on SYN, so don't alert if policy is MACOS */
+    if (talker->normalizer->get_os_policy() != StreamPolicy::OS_MACOS)
     {
-        /* MacOS accepts data on SYN, so don't alert if policy is MACOS */
-        if (talker->normalizer->get_os_policy() != StreamPolicy::OS_MACOS)
-        {
-            // remove data on SYN
-            listener->normalizer->trim_syn_payload(tsd);
+        // remove data on SYN
+        listener->normalizer->trim_syn_payload(tsd);
 
-            if (Normalize_GetMode(NORM_TCP_TRIM_SYN) == NORM_MODE_OFF)
-            {
-                DebugMessage(DEBUG_STREAM_STATE, "Got data on SYN packet, not processing it\n");
-                //EventDataOnSyn(config);
-                tel->set_tcp_event(EVENT_DATA_ON_SYN);
-                pkt_action_mask |= ACTION_BAD_PKT;
-            }
+        if (Normalize_GetMode(NORM_TCP_TRIM_SYN) == NORM_MODE_OFF)
+        {
+            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;
         }
     }
 }
 
-void TcpSession::process_tcp_packet(TcpSegmentDescriptor& tsd)
+void TcpSession::update_session_on_rst(TcpSegmentDescriptor& tsd, bool flush)
 {
-    Profile profile(s5TcpStatePerfStats);
+    if ( flush )
+    {
+        flush_listener(tsd.get_pkt());
+        flush_talker(tsd.get_pkt());
+        set_splitter(true, nullptr);
+        set_splitter(false, nullptr);
+        flow->free_application_data();
+    }
 
-    int got_ts = 0;
-    talker = nullptr;
-    listener = nullptr;
-    const tcp::TCPHdr* tcph = tsd.get_tcph();
+    talker->update_on_rst_sent( );
+}
 
-    DEBUG_WRAP(const char* t = NULL; const char* l = NULL; );
+void TcpSession::update_paws_timestamps(TcpSegmentDescriptor& tsd)
+{
+    // update PAWS timestamps
+    DebugFormat(DEBUG_STREAM_STATE, "PAWS update tsd.seq %lu > listener->r_win_base %lu\n",
+        tsd.get_seg_seq(), listener->r_win_base);
 
-    /* If session is already marked as established */
-    update_session_state(tcph, tsd);
-
-    if ( tcph->is_syn() )
-        server->normalizer->ecn_tracker( (tcp::TCPHdr*)tcph, config->require_3whs() );
-
-    if ( tsd.get_pkt()->packet_flags & PKT_FROM_SERVER )
+    if ( listener->normalizer->handling_timestamps()
+        && SEQ_EQ(listener->r_win_base, tsd.get_seg_seq() ) )
     {
-        update_session_on_server_packet(tcph, tsd);
-        DEBUG_WRAP(t = "Server"; l = "Client");
+        if ( ( (int32_t)(tsd.get_ts() - talker->get_ts_last() ) >= 0 )
+            ||
+            ( ( uint32_t )tsd.get_pkt()->pkth->ts.tv_sec >=
+            talker->get_ts_last_packet() + PAWS_24DAYS ) )
+        {
+            DebugMessage(DEBUG_STREAM_STATE, "updating timestamps...\n");
+            talker->set_ts_last(tsd.get_ts());
+            talker->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
+        }
     }
     else
     {
-        update_session_on_client_packet(tsd);
-        DEBUG_WRAP(t = "Server"; l = "Client");
+        DebugMessage(DEBUG_STREAM_STATE, "not updating timestamps...\n");
     }
+}
 
-    //check for SYN on reset session
-    if ( ( flow->get_session_flags() & SSNFLAG_RESET ) && tcph->is_syn() )
-        if ( !handle_syn_on_reset_session(tcph, tsd) )
-            return;
-
-    update_ignored_session(tsd);
-
-    handle_data_on_syn(tcph, tsd);
-
-    if (!tcp_init)
-        return;
-
-    DebugFormat(DEBUG_STREAM_STATE, "   %s [talker] state: %s\n", t,
-        tcp_state_names[talker->get_tcp_state()]);
-    DebugFormat(DEBUG_STREAM_STATE, "   %s state: %s(%d)\n", l,
-        tcp_state_names[listener->get_tcp_state()], listener->get_tcp_state());
-
-    // may find better placement to eliminate redundant flag checks
-    if ( tcph->is_syn() )
-        talker->s_mgr.sub_state |= SUB_SYN_SENT;
-    if ( tcph->is_ack() )
-        talker->s_mgr.sub_state |= SUB_ACK_SENT;
-
-    // process SYN ACK on unestablished sessions
-    if ( ( TcpStreamTracker::TCP_SYN_SENT == listener->get_tcp_state() ) &&
-        ( TcpStreamTracker::TCP_LISTEN == talker->get_tcp_state() ) )
+void TcpSession::check_for_session_hijack(TcpSegmentDescriptor& tsd)
+{
+ #ifdef DAQ_PKT_FLAG_PRE_ROUTING
+    if (!(tsd.get_pkt()->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING))
+#endif
     {
-        if ( tcph->is_ack() )
-        {
-            // make sure we've got a valid segment
-            if (!listener->is_ack_valid(tsd.get_ack() ) )
-            {
-                DebugFormat(DEBUG_STREAM_STATE,
-                    "Pkt Ack is Out of Bounds (%X, %X, %X) = (snd_una, snd_nxt, cur)\n",
-                    listener->get_snd_una(), listener->get_snd_nxt(), tsd.get_ack());
-                inc_tcp_discards();
-                listener->normalizer->trim_win_payload(tsd);
-                pkt_action_mask |= ACTION_BAD_PKT;
-                return;
-            }
-        }
-
-        talker->flags |= talker->normalizer->get_tcp_timestamp(tsd, false);
-        if (tsd.get_ts() == 0)
-            talker->flags |= TF_TSTAMP_ZERO;
-
-        // catch resets sent by server
-        if ( tcph->is_rst() )
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "got RST\n");
-
-            listener->normalizer->trim_rst_payload(tsd);
-
-            // Reset is valid when in SYN_SENT if the ack field ACKs the SYN.
-            if ( listener->is_rst_valid_in_syn_sent(tsd) )
-            {
-                DebugMessage(DEBUG_STREAM_STATE, "got RST, closing talker\n");
-                /* Reset is valid */
-                /* Mark session as reset... Leave it around so that any
-                 * additional data sent from one side or the other isn't
-                 * processed (and is dropped in inline mode).
-                 */
-                flow->set_session_flags(SSNFLAG_RESET);
-                talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
-                update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
-                /* Leave listener open, data may be in transit */
-                pkt_action_mask |= ACTION_RST;
-                return;
-            }
-            /* Reset not valid. */
-            DebugMessage(DEBUG_STREAM_STATE, "bad sequence number, bailing\n");
-            inc_tcp_discards();
-            tel->set_tcp_event(EVENT_BAD_RST);
-            listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
-            return;
-        }
-
-        // finish up server init
-        if ( tcph->is_syn() )
-        {
-            FinishServerInit(tsd);
-            if (talker->flags & TF_TSTAMP)
-            {
-                talker->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
-                talker->ts_last = tsd.get_ts();
-            }
+        tel.set_tcp_event(is_mac_address_valid(talker, listener, tsd.get_pkt()));
+    }
+}
 
-            DebugMessage(DEBUG_STREAM_STATE, "Finish server init got called!\n");
-        }
-        else
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "Finish server init didn't get called!\n");
-        }
+void TcpSession::handle_fin_recv_in_fw1(TcpSegmentDescriptor& tsd)
+{
+    Flow* flow = tsd.get_flow();
 
-        if ( tcph->are_flags_set(TH_ECE) && 
-             ( flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY ) )
-            flow->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
+    DebugMessage(DEBUG_STREAM_STATE, "seq ok, setting state!\n");
 
-        // explicitly set the state
-        listener->set_tcp_state(TcpStreamTracker::TCP_SYN_SENT);
-        DebugMessage(DEBUG_STREAM_STATE, "Accepted SYN ACK\n");
-        return;
+    if ( talker->s_mgr.state_queue == TcpStreamTracker::TCP_STATE_NONE )
+    {
+        talker->set_tcp_state(TcpStreamTracker::TCP_LAST_ACK);
+        EndOfFileHandle(tsd.get_pkt() );
     }
 
-    /*
-     * scale the window.  Only if BOTH client and server specified
-     * wscale option as part of 3-way handshake.
-     * This is per RFC 1323.
-     */
-    if ((talker->flags & TF_WSCALE) && (listener->flags & TF_WSCALE))
-        tsd.set_win(tsd.get_win() << talker->wscale);
-
-    /* Check for session hijacking -- compare mac address to the ones
-     * that were recorded at session startup. */
-#ifdef DAQ_PKT_FLAG_PRE_ROUTING
-    if (!(tsd.get_pkt()->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING))
-#endif
+    if ( flow->get_session_flags() & SSNFLAG_MIDSTREAM )
     {
-        tel->set_tcp_event(is_mac_address_valid (talker, listener, tsd.get_pkt() ) );
+        // FIXIT-L this should be handled below in fin section
+        // but midstream sessions fail the seq test
+        listener->s_mgr.state_queue = TcpStreamTracker::TCP_TIME_WAIT;
+        listener->s_mgr.transition_seq = tsd.get_end_seq();
+        listener->s_mgr.expected_flags = TH_ACK;
     }
+}
 
-    pkt_action_mask |= listener->normalizer->handle_paws(tsd, &got_ts);
-
-    // check RST validity
+#if 0
+// process SYN ACK on unestablished sessions
+if ( ( listener->get_tcp_state() != TcpStreamTracker::TCP_ESTABLISHED &&
+    TcpStreamTracker::TCP_SYN_ACK_RECV_EVENT == listener->get_tcp_event() ) &&
+    ( TcpStreamTracker::TCP_SYN_ACK_SENT_EVENT == talker->get_tcp_event() ) )
+{
+    // catch resets sent by server
     if ( tcph->is_rst() )
     {
+        DebugMessage(DEBUG_STREAM_STATE, "got RST\n");
+
         listener->normalizer->trim_rst_payload(tsd);
 
-        if (listener->normalizer->validate_rst(tsd))
+        // Reset is valid when in SYN_SENT if the ack field ACKs the SYN.
+        if ( listener->is_rst_valid_in_syn_sent(tsd) )
         {
-            DebugMessage(DEBUG_STREAM_STATE, "Got RST, bailing\n");
-
-            if (listener->get_tcp_state() == TcpStreamTracker::TCP_FIN_WAIT1
-                || listener->get_tcp_state() == TcpStreamTracker::TCP_FIN_WAIT2
-                || listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSE_WAIT
-                || listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSING)
-            {
-                flush_talker(tsd.get_pkt());
-                flush_listener(tsd.get_pkt());
-                set_splitter(true, nullptr);
-                set_splitter(false, nullptr);
-                flow->free_application_data();
-            }
-
+            DebugMessage(DEBUG_STREAM_STATE, "got RST, closing talker\n");
+            /* Reset is valid */
+            /* Mark session as reset... Leave it around so that any
+             * additional data sent from one side or the other isn't
+             * processed (and is dropped in inline mode).
+             */
             flow->set_session_flags(SSNFLAG_RESET);
             talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
-            talker->s_mgr.sub_state |= SUB_RST_SENT;
             update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
-
-            if ( listener->normalizer->is_tcp_ips_enabled() )
-                listener->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
-
-            /* else for ids: leave listener open, data may be in transit */
+            /* Leave listener open, data may be in transit */
             pkt_action_mask |= ACTION_RST;
             return;
         }
         /* Reset not valid. */
         DebugMessage(DEBUG_STREAM_STATE, "bad sequence number, bailing\n");
         inc_tcp_discards();
-        tel->set_tcp_event(EVENT_BAD_RST);
+        tel.set_tcp_event(EVENT_BAD_RST);
         listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
         return;
     }
-    else
-    {
-        /* check for valid seqeuence/retrans */
-        if (config->policy != StreamPolicy::OS_PROXY
-            and (listener->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED)
-            and !ValidSeq(listener, tsd))
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "bad sequence number, bailing\n");
-            inc_tcp_discards();
-            listener->normalizer->trim_win_payload(tsd);
-            return;
-        }
-    }
-
-    if ( pkt_action_mask & ACTION_BAD_PKT )
-    {
-        DebugMessage(DEBUG_STREAM_STATE, "bad timestamp, bailing\n");
-        inc_tcp_discards();
-        return;
-    }
-
-    // update PAWS timestamps
-    DebugFormat(DEBUG_STREAM_STATE, "PAWS update tsd.seq %lu > listener->r_win_base %lu\n",
-        tsd.get_seq(), listener->r_win_base);
-    if (got_ts && SEQ_EQ(listener->r_win_base, tsd.get_seq()))
-    {
-        if ( ( int32_t )( tsd.get_ts() - talker->ts_last ) >= 0 ||
-            (uint32_t)tsd.get_pkt()->pkth->ts.tv_sec >= talker->get_ts_last_packet() + PAWS_24DAYS)
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "updating timestamps...\n");
-            talker->ts_last = tsd.get_ts();
-            talker->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
-        }
-    }
-    else
-    {
-        DebugMessage(DEBUG_STREAM_STATE, "not updating timestamps...\n");
-    }
-
-    // check for repeat SYNs
-    if ( !new_ssn && tcph->is_syn_only() )
-    {
-        int action;
-        if (!SEQ_EQ(tsd.get_seq(), talker->get_iss()) &&
-             listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
-            action = ACTION_BAD_PKT;
-        else if (talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED)
-            action = listener->normalizer->handle_repeated_syn(tsd);
-        else
-            action = ACTION_NOTHING;
-
-        if (action != ACTION_NOTHING)
-        {
-            /* got a bad SYN on the session, alert! */
-            tel->set_tcp_event(EVENT_SYN_ON_EST);
-            pkt_action_mask |= action;
-            return;
-        }
-    }
-
-    // Check that the window is within the limits
-    if (config->policy != StreamPolicy::OS_PROXY)
-    {
-        if (config->max_window && (tsd.get_win() > config->max_window))
-        {
-            DebugMessage(DEBUG_STREAM_STATE,
-                "Got window that was beyond the allowed policy value, bailing\n");
-            /* 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);
-            pkt_action_mask |= ACTION_BAD_PKT;
-            return;
-        }
-        else if ((tsd.get_pkt()->packet_flags & PKT_FROM_CLIENT) && (tsd.get_win() <= SLAM_MAX)
-            && (tsd.get_ack() == listener->get_iss() + 1)
-            && !( tcph->is_fin() | tcph->is_rst() )
-            && !(flow->get_session_flags() & SSNFLAG_MIDSTREAM))
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "Window slammed shut!\n");
-            /* got a window slam alert! */
-            tel->set_tcp_event(EVENT_WINDOW_SLAM);
-            inc_tcp_discards();
-
-            if (listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
-            {
-                pkt_action_mask |= ACTION_BAD_PKT;
-                return;
-            }
-        }
-    }
-
-    if (talker->s_mgr.state_queue != TcpStreamTracker::TCP_STATE_NONE)
-    {
-        DebugFormat(DEBUG_STREAM_STATE,
-            "Found queued state transition on ack 0x%X, current 0x%X!\n",
-            talker->s_mgr.transition_seq, tsd.get_ack());
-
-        if (tsd.get_ack() == talker->s_mgr.transition_seq)
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "accepting transition!\n");
-            talker->set_tcp_state(talker->s_mgr.state_queue);
-            talker->s_mgr.state_queue = TcpStreamTracker::TCP_STATE_NONE;
-        }
-    }
-
-    // process ACK flags
-    if ( tcph->is_ack() )
-    {
-        DebugMessage(DEBUG_STREAM_STATE, "Got an ACK...\n");
-        DebugFormat(DEBUG_STREAM_STATE, " %s [listener] state: %s\n", l,
-            tcp_state_names[listener->get_tcp_state()]);
-
-        switch ( listener->get_tcp_state() )
-        {
-        case TcpStreamTracker::TCP_SYN_SENT:
-            break;
-
-        case TcpStreamTracker::TCP_SYN_RECV:
-            DebugMessage(DEBUG_STREAM_STATE, "listener state is SYN_SENT...\n");
-            if ( listener->is_ack_valid(tsd.get_ack() ) )
-            {
-                UpdateSsn(listener, talker, tsd);
-                flow->set_session_flags(SSNFLAG_ESTABLISHED);
-                flow->session_state |= STREAM_STATE_ESTABLISHED;
-                listener->set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
-                talker->set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
-                update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
-                /* Indicate this packet completes 3-way handshake */
-                tsd.get_pkt()->packet_flags |= PKT_STREAM_TWH;
-            }
-
-            talker->flags |= got_ts;
-            if (got_ts && SEQ_EQ(listener->r_nxt_ack, tsd.get_seq()))
-            {
-                talker->set_ts_last_packet(tsd.get_pkt()->pkth->ts.tv_sec);
-                talker->ts_last = tsd.get_ts();
-            }
-
-            break;
-
-        case TcpStreamTracker::TCP_ESTABLISHED:
-        case TcpStreamTracker::TCP_CLOSE_WAIT:
-            UpdateSsn(listener, talker, tsd);
-            break;
-
-        case TcpStreamTracker::TCP_FIN_WAIT1:
-            UpdateSsn(listener, talker, tsd);
-
-            DebugFormat(DEBUG_STREAM_STATE, "tsd.ack %X >= talker->r_nxt_ack %X\n", tsd.get_ack(),
-                talker->r_nxt_ack);
-
-            if ( SEQ_EQ(tsd.get_ack(), listener->get_snd_nxt() ) )
-            {
-                if ((listener->normalizer->get_os_policy() == StreamPolicy::OS_WINDOWS) &&
-                    (tsd.get_win() == 0))
-                {
-                    tel->set_tcp_event(EVENT_WINDOW_SLAM);
-                    inc_tcp_discards();
-
-                    if (listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
-                    {
-                        pkt_action_mask |= ACTION_BAD_PKT;
-                        return;
-                    }
-                }
-
-                listener->set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT2);
-
-                if ( tcph->is_fin() )
-                {
-                    DebugMessage(DEBUG_STREAM_STATE, "seq ok, setting state!\n");
-
-                    if ( talker->s_mgr.state_queue == TcpStreamTracker::TCP_STATE_NONE )
-                    {
-                        talker->set_tcp_state(TcpStreamTracker::TCP_LAST_ACK);
-                        EndOfFileHandle(tsd.get_pkt() );
-                    }
-                    if ( flow->get_session_flags() & SSNFLAG_MIDSTREAM )
-                    {
-                        // FIXIT-L this should be handled below in fin section
-                        // but midstream sessions fail the seq test
-                        listener->s_mgr.state_queue = TcpStreamTracker::TCP_TIME_WAIT;
-                        listener->s_mgr.transition_seq = tsd.get_end_seq();
-                        listener->s_mgr.expected_flags = TH_ACK;
-                    }
-                }
-                else if ( listener->s_mgr.state_queue == TcpStreamTracker::TCP_CLOSING )
-                {
-                    listener->s_mgr.state_queue = TcpStreamTracker::TCP_TIME_WAIT;
-                    listener->s_mgr.transition_seq = tsd.get_end_seq();
-                    listener->s_mgr.expected_flags = TH_ACK;
-                }
-            }
-            else
-            {
-                DebugMessage(DEBUG_STREAM_STATE, "bad ack!\n");
-            }
-            break;
-
-        case TcpStreamTracker::TCP_FIN_WAIT2:
-            UpdateSsn(listener, talker, tsd);
-            if ( SEQ_GT(tsd.get_ack(), listener->get_snd_nxt() ) )
-            {
-                tel->set_tcp_event(EVENT_BAD_ACK);
-                listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
-                pkt_action_mask |= ACTION_BAD_PKT;
-                return;
-            }
-            break;
-
-        case TcpStreamTracker::TCP_CLOSING:
-            UpdateSsn(listener, talker, tsd);
-            if (SEQ_GEQ(tsd.get_end_seq(), listener->r_nxt_ack))
-                listener->set_tcp_state(TcpStreamTracker::TCP_TIME_WAIT);
-            break;
-
-        case TcpStreamTracker::TCP_LAST_ACK:
-            UpdateSsn(listener, talker, tsd);
-
-            if ( SEQ_EQ(tsd.get_ack(), listener->get_snd_nxt() ) )
-                listener->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
-            break;
-
-        default:
-            // FIXIT-L safe to ignore when inline?
-            break;
-        }
 
-        talker->reassembler->flush_on_ack_policy(tsd.get_pkt() );
-    }
+    // explicitly set the state
+    //listener->set_tcp_state( TcpStreamTracker::TCP_SYN_SENT );
+    DebugMessage(DEBUG_STREAM_STATE, "Accepted SYN ACK\n");
+    return;
+}
+#endif
 
+void TcpSession::handle_data_segment(TcpSegmentDescriptor& tsd)
+{
     // handle data in the segment
-    if (tsd.get_pkt()->dsize)
+    if (tsd.get_seg_len())
     {
         DebugFormat(DEBUG_STREAM_STATE, "   %s state: %s(%d) getting data\n",
             l, tcp_state_names[listener->get_tcp_state()], listener->get_tcp_state());
 
         // FIN means only that sender is done talking, other side may continue yapping.
-        if ( TcpStreamTracker::TCP_FIN_WAIT2 == talker->get_tcp_state() ||
-            TcpStreamTracker::TCP_TIME_WAIT == talker->get_tcp_state() )
+        if (TcpStreamTracker::TCP_FIN_WAIT2 == talker->get_tcp_state()
+            || TcpStreamTracker::TCP_TIME_WAIT == talker->get_tcp_state())
         {
             // data on a segment when we're not accepting data any more alert!
-            //EventDataOnClosed(talker->config);
-            tel->set_tcp_event(EVENT_DATA_ON_CLOSED);
+            tel.set_tcp_event(EVENT_DATA_ON_CLOSED);
             pkt_action_mask |= ACTION_BAD_PKT;
             listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
         }
-        else if ( TcpStreamTracker::TCP_CLOSED == talker->get_tcp_state() )
+        else if (TcpStreamTracker::TCP_CLOSED == talker->get_tcp_state())
         {
             // data on a segment when we're not accepting data any more alert!
             if (flow->get_session_flags() & SSNFLAG_RESET)
             {
                 //EventDataAfterReset(listener->config);
                 if (talker->s_mgr.sub_state & SUB_RST_SENT)
-                    tel->set_tcp_event(EVENT_DATA_AFTER_RESET);
+                    tel.set_tcp_event(EVENT_DATA_AFTER_RESET);
                 else
-                    tel->set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
+                    tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
             }
             else
             {
-                //EventDataOnClosed(listener->config);
-                tel->set_tcp_event(EVENT_DATA_ON_CLOSED);
+                tel.set_tcp_event(EVENT_DATA_ON_CLOSED);
             }
             pkt_action_mask |= ACTION_BAD_PKT;
             listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
@@ -1466,6 +1087,7 @@ void TcpSession::process_tcp_packet(TcpSegmentDescriptor& tsd)
                 flush_policy_names[talker->flush_policy],
                 flush_policy_names[listener->flush_policy]);
 
+            // FIXIT - move this to normalizer base class, handle OS_PROXY in derived class
             if (config->policy != StreamPolicy::OS_PROXY)
             {
                 // these normalizations can't be done if we missed setup. and
@@ -1477,149 +1099,155 @@ void TcpSession::process_tcp_packet(TcpSegmentDescriptor& tsd)
                     TcpTracker* 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->mss)
-                        st->normalizer->trim_mss_payload(tsd, st->mss);
+                    if (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());
                 }
             }
+
             // dunno if this is RFC but fragroute testing expects it  for the record,
             // I've seen FTP data sessions that send data packets with no tcp flags set
-            if ((tcph->th_flags != 0)
-                or (config->policy == StreamPolicy::OS_LINUX)
+            if ((tsd.get_tcph()->th_flags != 0)or (config->policy == StreamPolicy::OS_LINUX)
                 or (config->policy == StreamPolicy::OS_PROXY))
             {
                 process_tcp_data(listener, tsd);
             }
             else
             {
-                tel->set_tcp_event(EVENT_DATA_WITHOUT_FLAGS);
+                tel.set_tcp_event(EVENT_DATA_WITHOUT_FLAGS);
                 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());
     }
+}
 
-    if ( tcph->is_fin() )
-    {
-        DebugMessage(DEBUG_STREAM_STATE, "Got a FIN...\n");
-        DebugFormat(DEBUG_STREAM_STATE,  "   %s state: %s(%d)\n", l,
-            tcp_state_names[talker->get_tcp_state()], talker->get_tcp_state());
-        DebugFormat(DEBUG_STREAM_STATE, "checking ack (0x%X) vs nxt_ack (0x%X)\n",
-            tsd.get_end_seq(), listener->r_win_base);
+bool TcpSession::handle_fin_recv(TcpSegmentDescriptor& tsd)
+{
+    if ( !tsd.get_tcph()->is_fin() )
+        return true;
 
-        if ( SEQ_LT(tsd.get_end_seq(), listener->r_win_base) )
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "FIN inside r_win_base, bailing\n");
-            goto dupfin;
-        }
-        else
+    DebugMessage(DEBUG_STREAM_STATE, "Got a FIN...\n");
+    DebugFormat(DEBUG_STREAM_STATE,  "   %s state: %s(%d)\n", l,
+        tcp_state_names[talker->get_tcp_state()], talker->get_tcp_state());
+    DebugFormat(DEBUG_STREAM_STATE, "checking ack (0x%X) vs nxt_ack (0x%X)\n",
+        tsd.get_end_seq(), listener->r_win_base);
+
+    if ( SEQ_LT(tsd.get_end_seq(), listener->r_win_base) )
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "FIN inside r_win_base, bailing\n");
+        return true;
+    }
+    else
+    {
+        // need substate since we don't change state immediately
+        if ( (talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED )
+            && !( talker->s_mgr.sub_state & SUB_FIN_SENT ) )
         {
-            // need substate since we don't change state immediately
-            if ( (talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED )
-                && !( talker->s_mgr.sub_state & SUB_FIN_SENT ) )
-            {
-                talker->set_snd_nxt(talker->get_snd_nxt() + 1);
+            talker->set_snd_nxt(talker->get_snd_nxt() + 1);
 
-                //--------------------------------------------------
-                // 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, listener->r_nxt_ack) )
-                listener->r_nxt_ack++;
-                //--------------------------------------------------
+            //--------------------------------------------------
+            // 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, listener->r_nxt_ack) )
+            listener->r_nxt_ack++;
+            //--------------------------------------------------
 
-                talker->s_mgr.sub_state |= SUB_FIN_SENT;
+            talker->s_mgr.sub_state |= SUB_FIN_SENT;
 
-                if ( ( listener->flush_policy != STREAM_FLPOLICY_ON_ACK )
-                    && ( listener->flush_policy != STREAM_FLPOLICY_ON_DATA )
-                    && listener->normalizer->is_tcp_ips_enabled() )
-                {
-                    tsd.get_pkt()->packet_flags |= PKT_PDU_TAIL;
-                }
-            }
-            switch (talker->get_tcp_state())
+            if ( ( listener->flush_policy != STREAM_FLPOLICY_ON_ACK )
+                && ( listener->flush_policy != STREAM_FLPOLICY_ON_DATA )
+                && listener->normalizer->is_tcp_ips_enabled() )
             {
-            case TcpStreamTracker::TCP_SYN_RECV:
-            case TcpStreamTracker::TCP_ESTABLISHED:
-                if ( talker->s_mgr.state_queue == TcpStreamTracker::TCP_CLOSE_WAIT )
-                    talker->s_mgr.state_queue = TcpStreamTracker::TCP_CLOSING;
-
-                talker->set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT1);
-                EndOfFileHandle(tsd.get_pkt() );
+                tsd.get_pkt()->packet_flags |= PKT_PDU_TAIL;
+            }
+        }
+        switch (talker->get_tcp_state())
+        {
+        case TcpStreamTracker::TCP_SYN_RECV:
+        case TcpStreamTracker::TCP_ESTABLISHED:
+            if ( talker->s_mgr.state_queue == TcpStreamTracker::TCP_CLOSE_WAIT )
+                talker->s_mgr.state_queue = TcpStreamTracker::TCP_CLOSING;
 
-                if ( !tsd.get_pkt()->dsize )
-                    listener->reassembler->flush_on_data_policy(tsd.get_pkt() );
+            talker->set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT1);
+            EndOfFileHandle(tsd.get_pkt() );
 
-                update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
-                break;
+            if ( !tsd.get_seg_len() )
+                listener->reassembler->flush_on_data_policy(tsd.get_pkt() );
 
-            case TcpStreamTracker::TCP_CLOSE_WAIT:
-                talker->set_tcp_state(TcpStreamTracker::TCP_LAST_ACK);
-                break;
+            update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+            break;
 
-            case TcpStreamTracker::TCP_FIN_WAIT1:
-                if (!tsd.get_pkt()->dsize)
-                    retransmit_handle(tsd.get_pkt() );
-                break;
+        case TcpStreamTracker::TCP_CLOSE_WAIT:
+            talker->set_tcp_state(TcpStreamTracker::TCP_LAST_ACK);
+            break;
 
-            default:
-                /* all other states stay where they are */
-                break;
-            }
+        case TcpStreamTracker::TCP_FIN_WAIT1:
+            if (!tsd.get_seg_len())
+                retransmit_handle(tsd.get_pkt() );
+            break;
 
-            if ((talker->get_tcp_state() == TcpStreamTracker::TCP_FIN_WAIT1) ||
-                (talker->get_tcp_state() == TcpStreamTracker::TCP_LAST_ACK))
-            {
-                uint32_t end_seq = (flow->get_session_flags() & SSNFLAG_MIDSTREAM)
-                    ? tsd.get_end_seq() - 1 : tsd.get_end_seq();
+        default:
+            /* all other states stay where they are */
+            break;
+        }
 
-                if ((listener->s_mgr.expected_flags == TH_ACK) && SEQ_GEQ(end_seq,
-                    listener->s_mgr.transition_seq))
-                {
-                    DebugMessage(DEBUG_STREAM_STATE, "FIN beyond previous, ignoring\n");
-                    tel->set_tcp_event(EVENT_BAD_FIN);
-                    listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
-                    pkt_action_mask |= ACTION_BAD_PKT;
-                    return;
-                }
-            }
+        if ((talker->get_tcp_state() == TcpStreamTracker::TCP_FIN_WAIT1) ||
+            (talker->get_tcp_state() == TcpStreamTracker::TCP_LAST_ACK))
+        {
+            uint32_t end_seq = (flow->get_session_flags() & SSNFLAG_MIDSTREAM)
+                ? tsd.get_end_seq() - 1 : tsd.get_end_seq();
 
-            switch ( listener->get_tcp_state() )
+            if ((listener->s_mgr.expected_flags == TH_ACK) && SEQ_GEQ(end_seq,
+                listener->s_mgr.transition_seq))
             {
-            case TcpStreamTracker::TCP_ESTABLISHED:
-                listener->s_mgr.state_queue = TcpStreamTracker::TCP_CLOSE_WAIT;
-                listener->s_mgr.transition_seq = tsd.get_end_seq() + 1;
-                listener->s_mgr.expected_flags = TH_ACK;
-                break;
-
-            case TcpStreamTracker::TCP_FIN_WAIT1:
-                listener->s_mgr.state_queue = TcpStreamTracker::TCP_CLOSING;
-                listener->s_mgr.transition_seq = tsd.get_end_seq() + 1;
-                listener->s_mgr.expected_flags = TH_ACK;
-                break;
-
-            case TcpStreamTracker::TCP_FIN_WAIT2:
-                listener->s_mgr.state_queue = TcpStreamTracker::TCP_TIME_WAIT;
-                listener->s_mgr.transition_seq = tsd.get_end_seq() + 1;
-                listener->s_mgr.expected_flags = TH_ACK;
-                break;
-
-            default:
-                // FIXIT - put this here quickly to make compiler happy, what should
-                // be done when not in one of the 3 states above?
-                DebugMessage(DEBUG_STREAM_STATE, "No Action In This State\n");
-                break;
+                DebugMessage(DEBUG_STREAM_STATE, "FIN beyond previous, ignoring\n");
+                tel.set_tcp_event(EVENT_BAD_FIN);
+                listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+                pkt_action_mask |= ACTION_BAD_PKT;
+                return false;
             }
         }
+
+        switch ( listener->get_tcp_state() )
+        {
+        case TcpStreamTracker::TCP_ESTABLISHED:
+            listener->s_mgr.state_queue = TcpStreamTracker::TCP_CLOSE_WAIT;
+            listener->s_mgr.transition_seq = tsd.get_end_seq() + 1;
+            listener->s_mgr.expected_flags = TH_ACK;
+            break;
+
+        case TcpStreamTracker::TCP_FIN_WAIT1:
+            listener->s_mgr.state_queue = TcpStreamTracker::TCP_CLOSING;
+            listener->s_mgr.transition_seq = tsd.get_end_seq() + 1;
+            listener->s_mgr.expected_flags = TH_ACK;
+            break;
+
+        case TcpStreamTracker::TCP_FIN_WAIT2:
+            listener->s_mgr.state_queue = TcpStreamTracker::TCP_TIME_WAIT;
+            listener->s_mgr.transition_seq = tsd.get_end_seq() + 1;
+            listener->s_mgr.expected_flags = TH_ACK;
+            break;
+
+        default:
+            // FIXIT - put this here quickly to make compiler happy, what should
+            // be done when not in one of the 3 states above?
+            DebugMessage(DEBUG_STREAM_STATE, "No Action In This State\n");
+            break;
+        }
     }
 
-dupfin:
+    return true;
+}
 
+void TcpSession::finalize_tcp_packet_processing(TcpSegmentDescriptor& tsd)
+{
     DebugFormat(DEBUG_STREAM_STATE, "   %s [talker] state: %s\n", t,
         tcp_state_names[talker->get_tcp_state()]);
     DebugFormat(DEBUG_STREAM_STATE, "   %s state: %s(%d)\n", l,
@@ -1627,10 +1255,10 @@ dupfin:
 
     // handle TIME_WAIT timer stuff
     if (!flow->two_way_traffic() &&
-        (talker->get_tcp_state() >= TcpStreamTracker::TCP_FIN_WAIT1 || listener->get_tcp_state() >=
-        TcpStreamTracker::TCP_FIN_WAIT1))
+        (talker->get_tcp_state() >= TcpStreamTracker::TCP_FIN_WAIT1
+        || listener->get_tcp_state() >= TcpStreamTracker::TCP_FIN_WAIT1))
     {
-        if (tcph->is_fin() && tcph->is_ack())
+        if (tsd.get_tcph()->is_fin() && tsd.get_tcph()->is_ack())
         {
             if (talker->get_tcp_state() >= TcpStreamTracker::TCP_FIN_WAIT1)
                 talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
@@ -1638,7 +1266,7 @@ dupfin:
             if (listener->get_tcp_state() >= TcpStreamTracker::TCP_FIN_WAIT1)
                 listener->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
 
-            listener->flags |= TF_FORCE_FLUSH;
+            listener->set_tf_flags(TF_FORCE_FLUSH);
         }
     }
 
@@ -1648,7 +1276,9 @@ dupfin:
         talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED)
         || (listener->get_tcp_state() == TcpStreamTracker::TCP_TIME_WAIT &&
         talker->get_tcp_state() ==  TcpStreamTracker::TCP_TIME_WAIT)
-        || (!flow->two_way_traffic() && (talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED ||
+        || (!flow->two_way_traffic() &&
+        (talker->get_tcp_state() == TcpStreamTracker::TCP_CLOSED
+        ||
         listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED)))
     {
         // The last ACK is a part of the session. Delete the session after processing is complete.
@@ -1660,154 +1290,110 @@ dupfin:
     else if ( listener->get_tcp_state() == TcpStreamTracker::TCP_CLOSED
         && talker->get_tcp_state() == TcpStreamTracker::TCP_SYN_SENT )
     {
-        if ( tcph->is_syn_only() )
+        if ( tsd.get_tcph()->is_syn_only() )
             flow->set_expire(tsd.get_pkt(), config->session_timeout);
     }
 }
 
-//-------------------------------------------------------------------------
-// TcpSession methods
-//-------------------------------------------------------------------------
-
-TcpSession::TcpSession(Flow* flow) :
-    Session(flow), config(nullptr), client(new TcpTracker(true) ),
-    server(new TcpTracker(false) ), ecn(0), ingress_index(0),
-    ingress_group(0), egress_index(0), egress_group(0), daq_flags(0), address_space_id(0),
-    pkt_action_mask(ACTION_NOTHING), require_3whs(true), no_3whs(false)
+void TcpSession::process_tcp_packet(TcpSegmentDescriptor& tsd)
 {
-    lws_init = tcp_init = false;
-    new_ssn = false;
+    Profile profile(s5TcpStatePerfStats);
+    const tcp::TCPHdr* tcph = tsd.get_tcph();
 
-    tel = new TcpEventLogger;
+    check_for_session_hijack(tsd);
 
-    // initialize stream tracker state machine...
-    new TcpStateNone(tsm, *this);
-    new TcpStateClosed(tsm, *this);
-    new TcpStateListen(tsm, *this);
-    new TcpStateSynSent(tsm, *this);
-    new TcpStateSynRecv(tsm, *this);
-    new TcpStateEstablished(tsm, *this);
-    new TcpStateFinWait1(tsm, *this);
-    new TcpStateFinWait2(tsm, *this);
-    new TcpStateClosing(tsm, *this);
-    new TcpStateCloseWait(tsm, *this);
-    new TcpStateLastAck(tsm, *this);
-    new TcpStateTimeWait(tsm, *this);
-}
+    /* check for valid seqeuence/retrans */
+    if ( ( config->policy != StreamPolicy::OS_PROXY )
+        && !listener->is_segment_seq_valid(tsd) )
+        return;
 
-TcpSession::~TcpSession(void)
-{
-    if (tcp_init)
+    if ( pkt_action_mask & ACTION_BAD_PKT )
     {
-        clear_session(1);
-
-        delete client;
-        delete server;
+        DebugMessage(DEBUG_STREAM_STATE, "bad timestamp, bailing\n");
+        inc_tcp_discards();
+        return;
     }
 
-    delete tel;
-}
-
-void TcpSession::reset(void)
-{
-    if (tcp_init)
-        clear_session(2);
-}
-
-bool TcpSession::setup(Packet*)
-{
-    // FIXIT-L this it should not be necessary to reset here
-    reset();
-
-    client->init_tracker( );
-    server->init_tracker( );
-    lws_init = tcp_init = false;
-    no_3whs = false;
-    pkt_action_mask = ACTION_NOTHING;
-    ecn = 0;
-    ingress_index = egress_index = 0;
-    ingress_group = egress_group = 0;
-    daq_flags = address_space_id = 0;
-
-    SESSION_STATS_ADD(tcpStats);
-    return true;
-}
+    update_paws_timestamps(tsd);
 
-void TcpSession::cleanup(void)
-{
-    // this flushes data and then calls TcpSessionClear()
-    cleanup_session(1);
-}
-
-void TcpSession::clear(void)
-{
-    if ( tcp_init )
-        // this does NOT flush data
-        clear_session(true);
-}
-
-void TcpSession::restart(Packet* p)
-{
-    // sanity check since this is called externally
-    assert(p->ptrs.tcph);
-
-    TcpTracker* talker, * listener;
-
-    if (p->packet_flags & PKT_FROM_SERVER)
-    {
-        talker = server;
-        listener = client;
-    }
-    else
+    // check for repeat SYNs
+    if ( tcph->is_syn_only() )
     {
-        talker = client;
-        listener = server;
-    }
+        int action;
+        if (!SEQ_EQ(tsd.get_seg_seq(), talker->get_iss())
+            && listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
+            action = ACTION_BAD_PKT;
+        else if (talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED)
+            action = listener->normalizer->handle_repeated_syn(tsd);
+        else
+            action = ACTION_NOTHING;
 
-    // FIXIT-H on data / on ack must be based on flush policy
-    if (p->dsize > 0)
-        listener->reassembler->flush_on_data_policy(p);
+        if (action != ACTION_NOTHING)
+        {
+            /* got a bad SYN on the session, alert! */
+            tel.set_tcp_event(EVENT_SYN_ON_EST);
+            pkt_action_mask |= action;
+            return;
+        }
+    }
 
-    if (p->ptrs.tcph->is_ack())
-        talker->reassembler->flush_on_ack_policy(p);
-}
+    // Check that the window is within the limits
+    if ( config->policy != StreamPolicy::OS_PROXY )
+    {
+        if ( config->max_window && (tsd.get_seg_wnd() > config->max_window ) )
+        {
+            DebugMessage(DEBUG_STREAM_STATE,
+                "Got window that was beyond the allowed policy value, bailing\n");
+            /* 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);
+            pkt_action_mask |= ACTION_BAD_PKT;
+            return;
+        }
+        else if ((tsd.get_pkt()->packet_flags & PKT_FROM_CLIENT)
+            && (tsd.get_seg_wnd() <= SLAM_MAX)
+            && (tsd.get_seg_ack() == listener->get_iss() + 1)
+            && !( tcph->is_fin() | tcph->is_rst() )
+            && !(flow->get_session_flags() & SSNFLAG_MIDSTREAM))
+        {
+            DebugMessage(DEBUG_STREAM_STATE, "Window slammed shut!\n");
+            /* got a window slam alert! */
+            tel.set_tcp_event(EVENT_WINDOW_SLAM);
+            inc_tcp_discards();
 
-void TcpSession::print(void)
-{
-    char buf[64];
+            if (listener->normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
+            {
+                pkt_action_mask |= ACTION_BAD_PKT;
+                return;
+            }
+        }
+    }
 
-    LogMessage("TcpSession:\n");
-    sfip_ntop(&flow->server_ip, buf, sizeof(buf));
-    LogMessage("    server IP:          %s\n", buf);
-    sfip_ntop(&flow->client_ip, buf, sizeof(buf));
-    LogMessage("    client IP:          %s\n", buf);
-    LogMessage("    server port:        %d\n", flow->server_port);
-    LogMessage("    client port:        %d\n", flow->client_port);
-    LogMessage("    flags:              0x%X\n", flow->get_session_flags());
-    LogMessage("Client Tracker:\n");
-    client->print();
-    LogMessage("Server Tracker:\n");
-    server->print();
-}
+    if (talker->s_mgr.state_queue != TcpStreamTracker::TCP_STATE_NONE)
+    {
+        DebugFormat(DEBUG_STREAM_STATE,
+            "Found queued state transition on ack 0x%X, current 0x%X!\n",
+            talker->s_mgr.transition_seq, tsd.get_seg_ack());
 
-void TcpSession::set_splitter(bool to_server, StreamSplitter* ss)
-{
-    TcpTracker* trk = ( to_server ) ? server : client;
+        if (tsd.get_seg_ack() == talker->s_mgr.transition_seq)
+        {
+            DebugMessage(DEBUG_STREAM_STATE, "accepting transition!\n");
+            talker->set_tcp_state(talker->s_mgr.state_queue);
+            talker->s_mgr.state_queue = TcpStreamTracker::TCP_STATE_NONE;
+        }
+    }
 
-    trk->set_splitter(ss);
-}
+    // handle data in the segment
+    handle_data_segment(tsd);
 
-StreamSplitter* TcpSession::get_splitter(bool to_server)
-{
-    if ( to_server )
-        return server->splitter;
-    else
-        return client->splitter;
+    if ( handle_fin_recv(tsd) )
+        finalize_tcp_packet_processing(tsd);
 }
 
 void TcpSession::flush_server(Packet* p)
 {
-    server->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 )
@@ -1820,12 +1406,12 @@ void TcpSession::flush_server(Packet* p)
     if ( server->reassembler->flush_stream(p, PKT_FROM_SERVER) )
         server->reassembler->purge_flushed_ackd( );
 
-    server->flags &= ~TF_FORCE_FLUSH;
+    server->clear_tf_flags(TF_FORCE_FLUSH);
 }
 
 void TcpSession::flush_client(Packet* p)
 {
-    client->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 )
@@ -1837,7 +1423,7 @@ void TcpSession::flush_client(Packet* p)
     if ( client->reassembler->flush_stream(p, PKT_FROM_CLIENT) )
         client->reassembler->purge_flushed_ackd( );
 
-    client->flags &= ~TF_FORCE_FLUSH;
+    client->clear_tf_flags(TF_FORCE_FLUSH);
 }
 
 void TcpSession::flush_listener(Packet* p)
@@ -1864,11 +1450,11 @@ void TcpSession::flush_listener(Packet* p)
 
     if ( dir != 0 )
     {
-        listener->flags |= TF_FORCE_FLUSH;
+        listener->set_tf_flags(TF_FORCE_FLUSH);
         if ( listener->reassembler->flush_stream(p, dir) )
             listener->reassembler->purge_flushed_ackd( );
 
-        listener->flags &= ~TF_FORCE_FLUSH;
+        listener->clear_tf_flags(TF_FORCE_FLUSH);
     }
 }
 
@@ -1896,11 +1482,11 @@ void TcpSession::flush_talker(Packet* p)
 
     if (dir != 0)
     {
-        talker->flags |= TF_FORCE_FLUSH;
+        talker->set_tf_flags(TF_FORCE_FLUSH);
         if ( talker->reassembler->flush_stream(p, dir) )
             talker->reassembler->purge_flushed_ackd( );
 
-        talker->flags &= ~TF_FORCE_FLUSH;
+        talker->clear_tf_flags(TF_FORCE_FLUSH);
     }
 }
 
@@ -2033,13 +1619,13 @@ bool TcpSession::is_sequenced(uint8_t dir)
 {
     if (dir & SSN_DIR_FROM_CLIENT)
     {
-        if (server->flags & (TF_MISSING_PREV_PKT | TF_MISSING_PKT))
+        if ( server->get_tf_flags() & ( TF_MISSING_PREV_PKT | TF_MISSING_PKT ) )
             return false;
     }
 
-    if (dir & SSN_DIR_FROM_SERVER)
+    if ( dir & SSN_DIR_FROM_SERVER )
     {
-        if (client->flags & (TF_MISSING_PREV_PKT | TF_MISSING_PKT))
+        if ( client->get_tf_flags() & ( TF_MISSING_PREV_PKT | TF_MISSING_PKT ) )
             return false;
     }
 
@@ -2052,22 +1638,22 @@ uint8_t TcpSession::missing_in_reassembled(uint8_t dir)
 {
     if (dir & SSN_DIR_FROM_CLIENT)
     {
-        if ((server->flags & TF_MISSING_PKT)
-            && (server->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->flags & TF_MISSING_PREV_PKT)
+        else if (server->get_tf_flags() & TF_MISSING_PREV_PKT)
             return SSN_MISSING_BEFORE;
-        else if (server->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->flags & TF_MISSING_PKT)
-            && (client->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->flags & TF_MISSING_PREV_PKT)
+        else if (client->get_tf_flags() & TF_MISSING_PREV_PKT)
             return SSN_MISSING_BEFORE;
-        else if (client->flags & TF_MISSING_PKT)
+        else if (client->get_tf_flags() & TF_MISSING_PKT)
             return SSN_MISSING_AFTER;
     }
 
@@ -2078,13 +1664,13 @@ bool TcpSession::are_packets_missing(uint8_t dir)
 {
     if (dir & SSN_DIR_FROM_CLIENT)
     {
-        if (server->flags & TF_PKT_MISSED)
+        if (server->get_tf_flags() & TF_PKT_MISSED)
             return true;
     }
 
     if (dir & SSN_DIR_FROM_SERVER)
     {
-        if (client->flags & TF_PKT_MISSED)
+        if (client->get_tf_flags() & TF_PKT_MISSED)
             return true;
     }
 
@@ -2191,6 +1777,15 @@ void TcpSession::SwapPacketHeaderFoo(void)
     }
 }
 
+static inline void set_window_scale(TcpTracker& talker, TcpTracker& listener,
+    TcpSegmentDescriptor& tsd)
+{
+    // scale the window.  Only if BOTH client and server specified wscale option as part
+    // of 3-way handshake.  This is per RFC 1323.
+    if ( ( talker.get_tf_flags() & TF_WSCALE ) && ( listener.get_tf_flags() & TF_WSCALE ) )
+        tsd.scale_seg_wnd(talker.get_wscale() );
+}
+
 /*
  * Main entry point for TCP
  */
@@ -2204,7 +1799,7 @@ int TcpSession::process(Packet* p)
         DebugFormat((DEBUG_STREAM|DEBUG_STREAM_STATE),
         "Got TCP Packet 0x%X:%d ->  0x%X:%d %s\nseq: 0x%X   ack:0x%X  dsize: %u\n",
         p->ptrs.ip_api.get_src(), p->ptrs.sp, p->ptrs.ip_api.get_dst(), p->ptrs.dp, flagbuf,
-        ntohl(p->ptrs.tcph->th_seq), ntohl(p->ptrs.tcph->th_ack), p->dsize);
+        p->ptrs.tcph->seq(), p->ptrs.tcph->ack(), p->dsize);
         );
 
     // FIXIT-L can't get here without protocol being set to TCP, is this really needed??
@@ -2228,69 +1823,10 @@ int TcpSession::process(Packet* p)
     }
 
     TcpSegmentDescriptor tsd(flow, p, tel);
-    if (!lws_init)
-    {
-        // FIXIT - should only do ths once...
-        if (config == nullptr )
-        {
-            config = get_tcp_cfg(flow->ssn_server);
-            require_3whs = config->require_3whs();
-            client->set_require_3whs(require_3whs);
-            server->set_require_3whs(require_3whs);
-        }
-        set_os_policy( );
-
-        // FIXIT most of this now looks out of place or redundant
-        if ( require_3whs )
-        {
-            if (p->ptrs.tcph->is_syn_only())
-            {
-                /* SYN only */
-                flow->session_state = STREAM_STATE_SYN;
-            }
-            else
-            {
-                // If we're within the "startup" window, try to handle
-                // this packet as midstream pickup -- allows for
-                // connections that already existed before snort started.
-                if (config->midstream_allowed(p))
-                    goto midstream_pickup_allowed;
-
-                // Do nothing with this packet since we require a 3-way ;)
-                DEBUG_WRAP(
-                    DebugMessage(DEBUG_STREAM_STATE,
-                    "Stream: Requiring 3-way Handshake, but failed to retrieve session"
-                    " object for non SYN packet.\n");
-                    );
-                if ( !p->ptrs.tcph->is_syn_only() && !p->ptrs.tcph->is_rst() && !no_3whs )
-                {
-                    tel->EventNo3whs();
-                    no_3whs = true;
-                }
-#ifdef REG_TEST
-                S5TraceTCP(p, flow, &tsd, 1);
-#endif
-                return 0;
-            }
-        }
-        else
-        {
-midstream_pickup_allowed:
-            if ( !p->ptrs.tcph->is_syn_ack()
-                && !p->dsize
-                && !(tsd.has_wscale() & TF_WSCALE) )
-            {
-#ifdef REG_TEST
-                S5TraceTCP(p, flow, &tsd, 1);
-#endif
-                return 0;
-            }
+    if (config == nullptr )
+        config = get_tcp_cfg(flow->ssn_server);
 
-            if (p->ptrs.tcph->is_syn())
-                flow->session_state |= STREAM_STATE_SYN;
-        }
-        lws_init = true;
-    }
+    set_os_policy( );
 
     // Check if the session is expired. Should be done before we do something with
     // the packet...Insert a packet, or handle state change SYN, FIN, RST, etc.
@@ -2314,19 +1850,50 @@ midstream_pickup_allowed:
     }
 
     // FIXIT - need to do something here to handle check for need to swap trackers
-    new_ssn = false;
-    if ( tsm.eval(tsd, *server) )
-        tsm.eval(tsd, *client);
-
     // FIXIT - this should change once tcp sm fully implemented
     pkt_action_mask = ACTION_NOTHING;
-    tel->clear_tcp_events();
+    tel.clear_tcp_events();
+
+    // process thru state machine...talker first
+    if ( p->packet_flags & PKT_FROM_CLIENT )
+    {
+        update_session_on_client_packet(tsd);
+        DEBUG_WRAP(t = "Server"; l = "Client");
+    }
+    else
+    {
+        update_session_on_server_packet(tsd);
+        DEBUG_WRAP(t = "Server"; l = "Client");
+    }
+
+    DebugFormat(DEBUG_STREAM_STATE, "   %s [talker] state: %s\n", t,
+        tcp_state_names[talker->get_tcp_state()]);
+    DebugFormat(DEBUG_STREAM_STATE, "   %s state: %s(%d)\n", l,
+        tcp_state_names[listener->get_tcp_state()], listener->get_tcp_state());
+
+    update_ignored_session(tsd);
+    // FIXIT - temp hack...move this to state handlers...
+    if ( listener->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED )
+        pkt_action_mask |= listener->normalizer->handle_paws(tsd);
+    set_window_scale(*talker, *listener, tsd);
+
+    if ( ( flow->get_session_flags() & SSNFLAG_RESET )
+        && !handle_syn_on_reset_session(tsd) )
+        return false;
+
+    if ( tsm.eval(tsd, *talker) )
+        tsm.eval(tsd, *listener);
+    else
+    {
+        S5TraceTCP(p, flow, &tsd, 1);
+        return 0;
+    }
 
-    if ( tcp_init || tsd.get_pkt()->dsize)
+    if ( tcp_init || tsd.get_seg_len())
         process_tcp_packet(tsd);
     // FIXIT - end
 
-    tel->log_tcp_events();
+    tel.log_tcp_events();
 
     DebugMessage(DEBUG_STREAM_STATE,
         "Finished Stream TCP cleanly!\n---------------------------------------------------\n");
index d96f5cc2022baa7d501b5d7e498b14d8a7eb09d8..9574a773fef045506f165a90cffb1a6fcfc7f25a 100644 (file)
@@ -57,9 +57,6 @@ public:
 
     void set_splitter(bool, StreamSplitter*) override;
     StreamSplitter* get_splitter(bool) override;
-    void init_new_tcp_session(TcpSegmentDescriptor& tsd);
-    void update_session_state(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd);
-
     void update_direction(char dir, const sfip_t*, uint16_t port) override;
 
     bool add_alert(Packet*, uint32_t gid, uint32_t sid) override;
@@ -104,40 +101,62 @@ public:
     static void set_memcap(class Memcap&);
     static void sinit(void);
     static void sterm(void);
-    void update_session_on_server_packet(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd);
-    void update_session_on_client_packet(TcpSegmentDescriptor& tsd);
-    bool handle_syn_on_reset_session(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd);
-    void update_ignored_session(TcpSegmentDescriptor& tsd);
 
-    TcpEventLogger* tel;
-    TcpStreamConfig* config;
-    TcpTracker* client;
-    TcpTracker* server;
-    uint8_t ecn;
-    bool lws_init;
-    bool tcp_init;
+    void init_new_tcp_session(TcpSegmentDescriptor&);
+    void update_timestamp_tracking(TcpSegmentDescriptor&);
+    void update_session_on_syn_ack(void);
+    void update_session_on_ack(void);
+    void update_session_on_server_packet(TcpSegmentDescriptor&);
+    void update_session_on_client_packet(TcpSegmentDescriptor&);
+    void update_session_on_rst(TcpSegmentDescriptor&, bool);
+    bool handle_syn_on_reset_session(TcpSegmentDescriptor&);
+    void handle_data_on_syn(TcpSegmentDescriptor&);
+    void handle_fin_recv_in_fw1(TcpSegmentDescriptor&);
+    bool handle_fin_recv(TcpSegmentDescriptor&);
+    void finalize_tcp_packet_processing(TcpSegmentDescriptor&);
+
+    void update_ignored_session(TcpSegmentDescriptor&);
+
+    void generate_no_3whs_event(void)
+    {
+        if ( !no_3whs )
+        {
+            tel.EventNo3whs();
+            no_3whs = true;
+        }
+    }
 
-    int32_t ingress_index; /* Index of the inbound interface. */
-    int32_t ingress_group; /* Index of the inbound group. */
-    int32_t egress_index; /* Index of the outbound interface. */
-    int32_t egress_group; /* Index of the outbound group. */
-    uint32_t daq_flags; /* Flags for the packet (DAQ_PKT_FLAG_*) */
-    uint16_t address_space_id;
+    void set_pkt_action_flag(uint32_t flag)
+    {
+        pkt_action_mask |= flag;
+    }
 
-    uint32_t pkt_action_mask;
-    bool require_3whs;
-    bool no_3whs;
+    void update_paws_timestamps(TcpSegmentDescriptor&);
+    void check_for_session_hijack(TcpSegmentDescriptor&);
+    void handle_data_segment(TcpSegmentDescriptor&);
 
-    // FIXIT - deprecate this once tcp state machine is fully implemented
-    bool new_ssn;
+    TcpTracker* client;
+    TcpTracker* server;
+    TcpEventLogger tel;
+    TcpStreamConfig* config = nullptr;
+    bool lws_init = false;
+    bool tcp_init = false;
+    uint8_t ecn = 0;
+    int32_t ingress_index = 0;
+    int32_t ingress_group = 0;
+    int32_t egress_index = 0;
+    int32_t egress_group = 0;
+    uint32_t daq_flags = 0;
+    uint16_t address_space_id = 0;
+    uint32_t pkt_action_mask = ACTION_NOTHING;
 
 private:
     void EndOfFileHandle(Packet* p);
-    bool flow_exceeds_config_thresholds(TcpTracker* rcv, TcpSegmentDescriptor& tsd);
-    void process_tcp_stream(TcpTracker* rcv, TcpSegmentDescriptor& tsd);
-    int process_tcp_data(TcpTracker* listener, TcpSegmentDescriptor& tsd);
+    bool flow_exceeds_config_thresholds(TcpTracker*, TcpSegmentDescriptor&);
+    void process_tcp_stream(TcpTracker*, TcpSegmentDescriptor&);
+    int process_tcp_data(TcpTracker*, TcpSegmentDescriptor&);
     void process_tcp_packet(TcpSegmentDescriptor&);
-    void FinishServerInit(TcpSegmentDescriptor& tsd);
+    void FinishServerInit(TcpSegmentDescriptor&);
     void swap_trackers(void);
 
     void NewTcpSessionOnSyn(TcpSegmentDescriptor&);
@@ -148,10 +167,11 @@ private:
     void clear_session(int freeApplicationData);
 
     int process_dis(Packet*);
-    void handle_data_on_syn(const tcp::TCPHdr* tcph, TcpSegmentDescriptor& tsd);
+    void update_on_3whs_complete(TcpSegmentDescriptor&);
 
-    TcpTracker* talker;
-    TcpTracker* listener;
+    bool no_3whs = false;
+    TcpTracker* talker = nullptr;
+    TcpTracker* listener = nullptr;
     TcpStateMachine tsm;
 };
 
index 63e70b5a68475f7ab16df6ce438cc8628f8bfd9f..ffdb84d3d7875fef9f029fa6c1c613c32ab859aa 100644 (file)
@@ -32,8 +32,8 @@ using namespace std;
 #include "catch/catch.hpp"
 #endif
 
-TcpStateCloseWait::TcpStateCloseWait(TcpStateMachine& tsm, TcpSession& session) :
-    TcpStateHandler(TcpStreamTracker::TCP_CLOSE_WAIT, tsm), session(session)
+TcpStateCloseWait::TcpStateCloseWait(TcpStateMachine& tsm, TcpSession& ssn) :
+    TcpStateHandler(TcpStreamTracker::TCP_CLOSE_WAIT, tsm), session(ssn)
 {
 }
 
@@ -43,85 +43,117 @@ TcpStateCloseWait::~TcpStateCloseWait()
 
 bool TcpStateCloseWait::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+
+    if ( tsd.get_seg_len() )
+        session.handle_data_on_syn(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= ( SUB_SYN_SENT | SUB_ACK_SENT );
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_recv(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateCloseWait::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        session.update_session_on_rst(tsd, true);
+        session.update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        session.set_pkt_action_flag(ACTION_RST);
+    }
+    else
+    {
+        session.tel.set_tcp_event(EVENT_BAD_RST);
+    }
+
+    return default_state_action(tsd, trk);
 }
 
index f0050a16901506b796ccae4ed154f5574e544df8..5cc2696ede16a6a1a13b442afbbadc182ebbe3e2 100644 (file)
@@ -24,6 +24,7 @@
 #include "tcp_module.h"
 #include "tcp_tracker.h"
 #include "tcp_session.h"
+#include "tcp_normalizer.h"
 #include "tcp_state_closed.h"
 
 #ifdef UNIT_TEST
@@ -42,62 +43,118 @@ TcpStateClosed::~TcpStateClosed()
 
 bool TcpStateClosed::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+    Flow* flow = tsd.get_flow();
+
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    if ( tsd.get_seg_len() )
+        session.handle_data_on_syn(tsd);
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.s_mgr.sub_state |= ( SUB_SYN_SENT | SUB_ACK_SENT );
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    return default_state_action(tsd, tracker);
 }
 
 bool TcpStateClosed::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    return default_state_action(tsd, tracker, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        session.update_session_on_rst(tsd, false);
+        session.update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        session.set_pkt_action_flag(ACTION_RST);
+    }
+    else
+    {
+        session.tel.set_tcp_event(EVENT_BAD_RST);
+    }
+
+    return default_state_action(tsd, tracker);
 }
 
 #ifdef FOO  // FIXIT - UNIT_TEST need work!!
index b6db44be329a3fa57d9e56a5d34f09b98f0386e8..5304b70683ff73b04fb2924ba9b74cf3e4e2801a 100644 (file)
@@ -32,8 +32,8 @@ using namespace std;
 #include "catch/catch.hpp"
 #endif
 
-TcpStateClosing::TcpStateClosing(TcpStateMachine& tsm, TcpSession& session) :
-    TcpStateHandler(TcpStreamTracker::TCP_CLOSING, tsm), session(session)
+TcpStateClosing::TcpStateClosing(TcpStateMachine& tsm, TcpSession& ssn) :
+    TcpStateHandler(TcpStreamTracker::TCP_CLOSING, tsm), session(ssn)
 {
 }
 
@@ -43,85 +43,122 @@ TcpStateClosing::~TcpStateClosing()
 
 bool TcpStateClosing::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    if ( tsd.get_seg_len() )
+        session.handle_data_on_syn(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.s_mgr.sub_state |= ( SUB_SYN_SENT | SUB_ACK_SENT );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
+    if ( SEQ_GEQ(tsd.get_end_seq(), trk.r_nxt_ack) )
+        trk.set_tcp_state(TcpStreamTracker::TCP_TIME_WAIT);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
+    if ( SEQ_GEQ(tsd.get_end_seq(), trk.r_nxt_ack) )
+        trk.set_tcp_state(TcpStreamTracker::TCP_TIME_WAIT);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_recv(tsd);
+    if ( SEQ_GEQ(tsd.get_end_seq(), trk.r_nxt_ack) )
+        trk.set_tcp_state(TcpStreamTracker::TCP_TIME_WAIT);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateClosing::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        session.update_session_on_rst(tsd, true);
+        session.update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        session.set_pkt_action_flag(ACTION_RST);
+    }
+    else
+    {
+        session.tel.set_tcp_event(EVENT_BAD_RST);
+    }
+
+    return default_state_action(tsd, trk);
 }
 
index 9f8de639610b6c6b1254667cd33136c8bb98195d..06ff3004dd5489ae234dc673718be71032aa678e 100644 (file)
@@ -25,8 +25,8 @@
 #include "tcp_normalizer.h"
 #include "tcp_state_established.h"
 
-TcpStateEstablished::TcpStateEstablished(TcpStateMachine& tsm, TcpSession& session) :
-    TcpStateHandler(TcpStreamTracker::TCP_ESTABLISHED, tsm), session(session)
+TcpStateEstablished::TcpStateEstablished(TcpStateMachine& tsm, TcpSession& ssn) :
+    TcpStateHandler(TcpStreamTracker::TCP_ESTABLISHED, tsm), session(ssn)
 {
 }
 
@@ -36,85 +36,119 @@ TcpStateEstablished::~TcpStateEstablished()
 
 bool TcpStateEstablished::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt()) )
+    {
+        session.update_session_on_syn_ack( );
+    }
+
+    if ( trk.is_server_tracker() )
+        trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_recv(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateEstablished::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        session.update_session_on_rst(tsd, false);
+        session.update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        session.set_pkt_action_flag(ACTION_RST);
+    }
+    else
+    {
+        session.tel.set_tcp_event(EVENT_BAD_RST);
+    }
+
+    return default_state_action(tsd, trk);
 }
 
index a55421734430754af01c430e63096a0c2fdb3b15..6b51eaf3fa6ed27384712fee29b61155f6d743e4 100644 (file)
@@ -43,85 +43,154 @@ TcpStateFinWait1::~TcpStateFinWait1()
 
 bool TcpStateFinWait1::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    if ( tsd.get_seg_len() )
+        session.handle_data_on_syn(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.s_mgr.sub_state |= ( SUB_SYN_SENT | SUB_ACK_SENT );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
+    check_for_window_slam(tsd, trk);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_recv(tsd);
+    check_for_window_slam(tsd, trk);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    if ( check_for_window_slam(tsd, trk) )
+        session.handle_fin_recv_in_fw1(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait1::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        session.update_session_on_rst(tsd, true);
+        session.update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        session.set_pkt_action_flag(ACTION_RST);
+    }
+    else
+    {
+        session.tel.set_tcp_event(EVENT_BAD_RST);
+    }
+
+    return default_state_action(tsd, trk);
+}
 
-    return default_state_action(tsd, trk, __func__);
+bool TcpStateFinWait1::check_for_window_slam(TcpSegmentDescriptor& tsd, TcpTracker& trk)
+{
+    DebugFormat(DEBUG_STREAM_STATE, "tsd.ack %X >= listener->snd_nxt %X\n",
+        tsd.get_seg_ack(), trk.get_snd_nxt());
+
+    if ( SEQ_EQ(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+    {
+        if ( (trk.normalizer->get_os_policy() == StreamPolicy::OS_WINDOWS)
+            && (tsd.get_seg_wnd() == 0))
+        {
+            session.tel.set_tcp_event(EVENT_WINDOW_SLAM);
+            inc_tcp_discards();
+
+            if (trk.normalizer->packet_dropper(tsd, NORM_TCP_BLOCK))
+            {
+                session.set_pkt_action_flag(ACTION_BAD_PKT);
+                return false;
+            }
+        }
+
+        trk.set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT2);
+
+        if ( trk.s_mgr.state_queue == TcpStreamTracker::TCP_CLOSING )
+        {
+            trk.s_mgr.state_queue = TcpStreamTracker::TCP_TIME_WAIT;
+            trk.s_mgr.transition_seq = tsd.get_end_seq();
+            trk.s_mgr.expected_flags = TH_ACK;
+        }
+    }
+
+    return true;
 }
 
index c55af9e5520811caa81379f15105e1e78ab344b5..e362231a906c214a3293d851f21e115c13897fbb 100644 (file)
@@ -46,6 +46,8 @@ public:
     bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) override;
 
 private:
+    bool check_for_window_slam(TcpSegmentDescriptor& tsd, TcpTracker& trk);
+
     TcpSession& session;
 };
 
index e39b11db7030ea6003d4f7505285d5a500296209..4fd6e0f0fa848a00dd8ee93372e1357cd9c50e45 100644 (file)
@@ -32,8 +32,8 @@ using namespace std;
 #include "catch/catch.hpp"
 #endif
 
-TcpStateFinWait2::TcpStateFinWait2(TcpStateMachine& tsm, TcpSession& session) :
-    TcpStateHandler(TcpStreamTracker::TCP_FIN_WAIT2, tsm), session(session)
+TcpStateFinWait2::TcpStateFinWait2(TcpStateMachine& tsm, TcpSession& ssn) :
+    TcpStateHandler(TcpStreamTracker::TCP_FIN_WAIT2, tsm), session(ssn)
 {
 }
 
@@ -43,85 +43,117 @@ TcpStateFinWait2::~TcpStateFinWait2()
 
 bool TcpStateFinWait2::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    if ( tsd.get_seg_len() )
+        session.handle_data_on_syn(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= ( SUB_SYN_SENT | SUB_ACK_SENT );
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( SEQ_GT(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+    {
+        trk.normalizer->packet_dropper(tsd, NORM_TCP_BLOCK);
+        session.tel.set_tcp_event(EVENT_BAD_ACK);
+        session.set_pkt_action_flag(ACTION_BAD_PKT);
+    }
+    else
+        trk.update_tracker_ack_recv(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateFinWait2::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        session.update_session_on_rst(tsd, true);
+        session.update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        session.set_pkt_action_flag(ACTION_RST);
+    }
+    else
+    {
+        session.tel.set_tcp_event(EVENT_BAD_RST);
+    }
+
+    return default_state_action(tsd, trk);
 }
 
index 57ab5ac639cfce7e7dd46271c58ca2bf2f666881..6d2f796a74ab4bfbb5c72fe1701c600837f8a181 100644 (file)
@@ -32,8 +32,8 @@ using namespace std;
 #include "catch/catch.hpp"
 #endif
 
-TcpStateLastAck::TcpStateLastAck(TcpStateMachine& tsm, TcpSession& session) :
-    TcpStateHandler(TcpStreamTracker::TCP_LAST_ACK, tsm), session(session)
+TcpStateLastAck::TcpStateLastAck(TcpStateMachine& tsm, TcpSession& ssn) :
+    TcpStateHandler(TcpStreamTracker::TCP_LAST_ACK, tsm), session(ssn)
 {
 }
 
@@ -43,85 +43,122 @@ TcpStateLastAck::~TcpStateLastAck()
 
 bool TcpStateLastAck::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    if ( tsd.get_seg_len() )
+        session.handle_data_on_syn(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.s_mgr.sub_state |= ( SUB_SYN_SENT | SUB_ACK_SENT );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
+    if ( SEQ_EQ(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+        trk.set_tcp_state(TcpStreamTracker::TCP_CLOSED);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_sent(tsd);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_recv(tsd);
+    if ( SEQ_EQ(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+        trk.set_tcp_state(TcpStreamTracker::TCP_CLOSED);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.update_tracker_ack_sent(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.update_tracker_ack_recv(tsd);
+    if ( SEQ_EQ(tsd.get_seg_ack(), trk.get_snd_nxt() ) )
+        trk.set_tcp_state(TcpStreamTracker::TCP_CLOSED);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateLastAck::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        session.update_session_on_rst(tsd, false);
+        session.update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        session.set_pkt_action_flag(ACTION_RST);
+    }
+    else
+    {
+        session.tel.set_tcp_event(EVENT_BAD_RST);
+    }
+
+    return default_state_action(tsd, trk);
 }
 
index 630741d346041f135ccbe6d859050744342cce21..a70a1e94eb4850899c98fac502c3bb8284e006c7 100644 (file)
@@ -36,85 +36,228 @@ TcpStateListen::~TcpStateListen()
 
 bool TcpStateListen::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    if ( session.config->require_3whs() || tsd.has_wscale() || ( tsd.get_seg_len() > 0 ) )
+    {
+        // FIXIT - do we need this check? only server goes into Listen state...
+        if ( tsd.get_pkt()->packet_flags & PKT_FROM_SERVER )
+            session.tel.set_tcp_event(EVENT_4WHS);
+    }
+
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( true || session.config->require_3whs() || tsd.has_wscale() || ( tsd.get_seg_len() > 0 ) )
+    {
+        trk.init_on_syn_recv(tsd);
+        trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+        if ( tsd.get_seg_len() )
+            session.handle_data_on_syn(tsd);
+    }
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    Flow* flow = tsd.get_flow();
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    flow->session_state |= ( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+        trk.init_on_synack_sent(tsd);
+        trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+        session.init_new_tcp_session(tsd);
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( !session.config->require_3whs() || session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+        trk.init_on_synack_recv(tsd);
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) && ( tsd.has_wscale() ||
+        ( tsd.get_seg_len() > 0 ) ) )
+    {
+        Flow* flow = tsd.get_flow();
+
+        /* FIXIT: do we need to verify the ACK field is >= the seq of the SYN-ACK?
+                   3-way Handshake complete, create TCP session */
+        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_SYN_ACK |
+            STREAM_STATE_ESTABLISHED );
+        trk.init_on_3whs_ack_sent(tsd);
+        session.init_new_tcp_session(tsd);
+        session.update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
+        tcpStats.sessions_on_3way++;
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) && ( tsd.has_wscale() ||
+        ( tsd.get_seg_len() > 0 ) ) )
+    {
+        Flow* flow = tsd.get_flow();
 
-    return default_state_action(tsd, trk, __func__);
+        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(), session.config->require_3whs() );
+        }
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+        Flow* flow = tsd.get_flow();
 
-    return default_state_action(tsd, trk, __func__);
+        flow->session_state |= STREAM_STATE_MIDSTREAM;
+        flow->set_session_flags(SSNFLAG_MIDSTREAM);
+
+        trk.init_on_data_seg_sent(tsd);
+        session.init_new_tcp_session(tsd);
+
+        if ( flow->session_state & STREAM_STATE_ESTABLISHED )
+            session.update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
+
+        tcpStats.sessions_on_data++;
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+        Flow* flow = tsd.get_flow();
 
-    return default_state_action(tsd, trk, __func__);
+        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(), session.config->require_3whs() );
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+        // FIXIT - handle this
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+    }
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateListen::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+        // FIXIT - handle this
+    }
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
index 5eae1573ee400905f15d1efd4e48b09222daab77..660eee303e31deccc09e946cb680d2f445d6c04d 100644 (file)
@@ -32,8 +32,8 @@
 #include "stream/libtcp/stream_tcp_unit_test.h"
 #endif
 
-TcpStateNone::TcpStateNone(TcpStateMachine& tsm, TcpSession& session) :
-    TcpStateHandler(TcpStreamTracker::TCP_STATE_NONE, tsm), session(session)
+TcpStateNone::TcpStateNone(TcpStateMachine& tsm, TcpSession& ssn) :
+    TcpStateHandler(TcpStreamTracker::TCP_STATE_NONE, tsm), session(ssn)
 {
 }
 
@@ -44,132 +44,126 @@ TcpStateNone::~TcpStateNone()
 bool TcpStateNone::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
     Flow* flow = tsd.get_flow();
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
     flow->ssn_state.direction = FROM_CLIENT;
-    flow->session_state |= STREAM_STATE_SYN;
 
-    if ( trk.is_3whs_required() || ( tsd.has_wscale() & TF_WSCALE ) ||
-         ( tsd.get_pkt()->dsize > 0 ) )
-    {
-        trk.init_on_syn_sent(tsd);
-        session.init_new_tcp_session(tsd);
-        tcpStats.sessions_on_syn++;
-    }
+    flow->session_state |= STREAM_STATE_SYN;
+    trk.init_on_syn_sent(tsd);
+    session.init_new_tcp_session(tsd);
 
-    return true;
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    if ( trk.is_3whs_required() || ( tsd.has_wscale() & TF_WSCALE ) ||
-         ( tsd.get_pkt()->dsize > 0 ) )
-    {
-        trk.init_on_syn_recv(tsd);
-        trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.is_3whs_required() );
-    }
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return true;
+    // FIXIT - syn received on undefined client, figure this out and do the right thing
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
     Flow* flow = tsd.get_flow();
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    /* SYN-ACK from server */
-    if ( ( flow->session_state == STREAM_STATE_NONE)
-        || ( flow->get_session_flags() & SSNFLAG_RESET ) )
-    {
-        DebugMessage(DEBUG_STREAM_STATE,
-            "Stream SYN|ACK PACKET, set session directioon to FROM_SERVER.\n");
-        flow->ssn_state.direction = FROM_SERVER;
-    }
-
-    flow->session_state |= STREAM_STATE_SYN_ACK;
-
-    if ( !trk.is_3whs_required() || session.config->midstream_allowed(tsd.get_pkt()) )
+    if ( !session.config->require_3whs() || session.config->midstream_allowed(tsd.get_pkt() ) )
     {
+        flow->session_state |= ( STREAM_STATE_SYN | STREAM_STATE_SYN_ACK );
         trk.init_on_synack_sent(tsd);
         session.init_new_tcp_session(tsd);
-        tcpStats.sessions_on_syn_ack++;
+        trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
     }
 
-    return true;
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    if ( !trk.is_3whs_required() || session.config->midstream_allowed(tsd.get_pkt()) )
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
     {
         trk.init_on_synack_recv(tsd);
+        trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
     }
 
-    trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.is_3whs_required() );
-
-    return true;
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    Flow* flow = tsd.get_flow();
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    if ( !tsd.get_tcph()->is_rst() && ( flow->session_state & STREAM_STATE_SYN_ACK ) )
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) && ( tsd.has_wscale() ||
+        ( tsd.get_seg_len() > 0 ) ) )
     {
+        Flow* flow = tsd.get_flow();
+
         /* FIXIT: do we need to verify the ACK field is >= the seq of the SYN-ACK?
                    3-way Handshake complete, create TCP session */
-        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_SYN_ACK |
+            STREAM_STATE_ESTABLISHED );
         trk.init_on_3whs_ack_sent(tsd);
         session.init_new_tcp_session(tsd);
         session.update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
         tcpStats.sessions_on_3way++;
     }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
 
-    return true;
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    Flow* flow = tsd.get_flow();
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) && ( tsd.has_wscale() ||
+        ( tsd.get_seg_len() > 0 ) ) )
+    {
+        Flow* flow = tsd.get_flow();
 
-    if ( !tsd.get_tcph()->is_rst() && ( flow->session_state & STREAM_STATE_SYN_ACK ) )
+        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(), session.config->require_3whs() );
+        }
+    }
+    else if ( session.config->require_3whs() )
     {
-        trk.init_on_3whs_ack_recv(tsd);
-        trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.is_3whs_required() );
+        session.generate_no_3whs_event();
+        return false;
     }
 
-    return true;
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    // FIXIT - are these necessary (see checks in TcpSession::process, but should get rid of those
-    if ( !trk.is_3whs_required() || session.config->midstream_allowed(tsd.get_pkt()) )
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
     {
         Flow* flow = tsd.get_flow();
 
         flow->session_state |= STREAM_STATE_MIDSTREAM;
         flow->set_session_flags(SSNFLAG_MIDSTREAM);
 
-        if (tsd.get_pkt()->ptrs.sp > tsd.get_pkt()->ptrs.dp)
-        {
-            flow->ssn_state.direction = FROM_CLIENT;
-            flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
-        }
-        else
-        {
-            flow->ssn_state.direction = FROM_SERVER;
-            flow->set_session_flags(SSNFLAG_SEEN_SERVER);
-        }
-
         trk.init_on_data_seg_sent(tsd);
         session.init_new_tcp_session(tsd);
 
@@ -178,65 +172,94 @@ bool TcpStateNone::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tr
 
         tcpStats.sessions_on_data++;
     }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
 
-    return true;
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    if ( !trk.is_3whs_required() || session.config->midstream_allowed(tsd.get_pkt()) )
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
     {
         Flow* flow = tsd.get_flow();
 
         flow->session_state |= STREAM_STATE_MIDSTREAM;
         flow->set_session_flags(SSNFLAG_MIDSTREAM);
 
-        if (tsd.get_pkt()->ptrs.sp > tsd.get_pkt()->ptrs.dp)
-        {
-            flow->ssn_state.direction = FROM_CLIENT;
-            flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
-        }
-        else
-        {
-            flow->ssn_state.direction = FROM_SERVER;
-            flow->set_session_flags(SSNFLAG_SEEN_SERVER);
-        }
-
         trk.init_on_data_seg_recv(tsd);
-        trk.normalizer->ecn_tracker(tsd.get_tcph(), trk.is_3whs_required() );
+        trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
     }
 
-    return true;
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+        // FIXIT - handle this
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+        // FIXIT - handle this
+    }
+    else if ( session.config->require_3whs() )
+    {
+        session.generate_no_3whs_event();
+        return false;
+    }
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+        // FIXIT - handle this
+    }
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateNone::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( session.config->midstream_allowed(tsd.get_pkt() ) )
+    {
+        // FIXIT - handle this
+    }
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 #ifdef FOO  // FIXIT - UNIT_TEST need work!!
index a3a6e647a9ffbc63e45beecfc02cbcad805e1dc1..5447a35c05f2865cccf6606bccb737bc50909fd5 100644 (file)
@@ -28,8 +28,8 @@ using namespace std;
 #include "tcp_normalizer.h"
 #include "tcp_state_syn_recv.h"
 
-TcpStateSynRecv::TcpStateSynRecv(TcpStateMachine& tsm, TcpSession& session) :
-    TcpStateHandler(TcpStreamTracker::TCP_SYN_RECV, tsm), session(session)
+TcpStateSynRecv::TcpStateSynRecv(TcpStateMachine& tsm, TcpSession& ssn) :
+    TcpStateHandler(TcpStreamTracker::TCP_SYN_RECV, tsm), session(ssn)
 {
 }
 
@@ -39,85 +39,168 @@ TcpStateSynRecv::~TcpStateSynRecv()
 
 bool TcpStateSynRecv::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    Flow* flow = tsd.get_flow();
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.finish_server_init(tsd);
+    trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    session.update_timestamp_tracking(tsd);
+    if ( tsd.get_tcph()->are_flags_set(TH_ECE) &&
+        ( flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY ) )
+        flow->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
+
+    if ( tsd.get_pkt()->packet_flags & PKT_FROM_SERVER )
+    {
+        flow->set_session_flags(SSNFLAG_SEEN_SERVER);
+        session.tel.set_tcp_event(EVENT_4WHS);
+    }
+
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( tsd.get_seg_len() )
+        session.handle_data_on_syn(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    Flow* flow = tsd.get_flow();
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    // FIXIT - verify ack being sent is valid...
+    trk.finish_server_init(tsd);
+    trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    flow->session_state |= STREAM_STATE_SYN_ACK;
+
+    trk.s_mgr.sub_state |= ( SUB_SYN_SENT | SUB_ACK_SENT );
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.is_ack_valid(tsd.get_seg_ack() ) )
+    {
+        Flow* flow = tsd.get_flow();
+
+        trk.update_tracker_ack_recv(tsd);
+        trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+        flow->set_session_flags(SSNFLAG_ESTABLISHED);
+        flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+        session.update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
+        trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    }
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    if ( session.config->midstream_allowed(tsd.get_pkt()) )
+    {
+        session.update_session_on_ack( );
+    }
+    trk.s_mgr.sub_state |= SUB_ACK_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.is_ack_valid(tsd.get_seg_ack() ) )
+    {
+        trk.update_tracker_ack_recv(tsd);
+        tsd.get_pkt()->packet_flags |= PKT_STREAM_TWH;
+        session.update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
+        trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    }
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= SUB_ACK_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.is_ack_valid(tsd.get_seg_ack() ) )
+    {
+        trk.update_tracker_ack_recv(tsd);
+        tsd.get_pkt()->packet_flags |= PKT_STREAM_TWH;
+        session.update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
+        trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+    }
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= SUB_ACK_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+    if ( tsd.get_tcph()->is_ack() )
+    {
+        Flow* flow = tsd.get_flow();
+        flow->session_state |= STREAM_STATE_ACK;
+        trk.update_tracker_ack_recv(tsd);
+        trk.set_tcp_state(TcpStreamTracker::TCP_CLOSE_WAIT);
+    }
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynRecv::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        session.update_session_on_rst(tsd, false);
+        session.update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        session.set_pkt_action_flag(ACTION_RST);
+    }
+    else
+    {
+        session.tel.set_tcp_event(EVENT_BAD_RST);
+    }
+
+    return default_state_action(tsd, trk);
 }
 
index 66c428761de0bd98b0e27d852e4cf57af01651ae..65d25817e55ee6b91b16f652c0f936c825b83c06 100644 (file)
@@ -32,8 +32,8 @@ using namespace std;
 #include "catch/catch.hpp"
 #endif
 
-TcpStateSynSent::TcpStateSynSent(TcpStateMachine& tsm, TcpSession& session) :
-    TcpStateHandler(TcpStreamTracker::TCP_SYN_SENT, tsm), session(session)
+TcpStateSynSent::TcpStateSynSent(TcpStateMachine& tsm, TcpSession& ssn) :
+    TcpStateHandler(TcpStreamTracker::TCP_SYN_SENT, tsm), session(ssn)
 {
 }
 
@@ -43,85 +43,132 @@ TcpStateSynSent::~TcpStateSynSent()
 
 bool TcpStateSynSent::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.finish_client_init(tsd);
+    if ( tsd.get_seg_len() )
+        session.handle_data_on_syn(tsd);
+    trk.set_tcp_state(TcpStreamTracker::TCP_SYN_RECV);
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= ( SUB_SYN_SENT | SUB_ACK_SENT );
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_3whs_ack(tsd) )
+    {
+        session.update_timestamp_tracking(tsd);
+        if ( tsd.get_seg_len() )
+            session.handle_data_on_syn(tsd);
+    }
+    else
+        session.set_pkt_action_flag(ACTION_BAD_PKT);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    Flow* flow = tsd.get_flow();
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    // FIXIT - verify ack being sent is valid...
+    trk.update_tracker_ack_sent(tsd);
+    flow->set_session_flags(SSNFLAG_ESTABLISHED);
+    flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+    session.update_timestamp_tracking(tsd);
+    session.update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
+    trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    Flow* flow = tsd.get_flow();
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    // FIXIT - verify ack being sent is valid...
+    trk.update_tracker_ack_sent(tsd);
+    flow->set_session_flags(SSNFLAG_ESTABLISHED);
+    flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
+    session.update_timestamp_tracking(tsd);
+    session.update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
+    trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateSynSent::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        session.update_session_on_rst(tsd, false);
+        session.update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        session.set_pkt_action_flag(ACTION_RST);
+    }
+    else
+    {
+        session.tel.set_tcp_event(EVENT_BAD_RST);
+    }
+
+    return default_state_action(tsd, trk);
 }
 
index e7abaef8f39e680eb3f0fcd8868391d7318f11b6..9bb8b7400e670c820680968a0f11770cdeaf3960 100644 (file)
@@ -32,8 +32,8 @@ using namespace std;
 #include "catch/catch.hpp"
 #endif
 
-TcpStateTimeWait::TcpStateTimeWait(TcpStateMachine& tsm, TcpSession& session) :
-    TcpStateHandler(TcpStreamTracker::TCP_TIME_WAIT, tsm), session(session)
+TcpStateTimeWait::TcpStateTimeWait(TcpStateMachine& tsm, TcpSession& ssn) :
+    TcpStateHandler(TcpStreamTracker::TCP_TIME_WAIT, tsm), session(ssn)
 {
 }
 
@@ -43,85 +43,104 @@ TcpStateTimeWait::~TcpStateTimeWait()
 
 bool TcpStateTimeWait::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= SUB_SYN_SENT;
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateTimeWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    trk.normalizer->ecn_tracker(tsd.get_tcph(), session.config->require_3whs() );
+    if ( tsd.get_seg_len() )
+        session.handle_data_on_syn(tsd);
 
-    return default_state_action(tsd, trk, __func__);
+    return true;
 }
 
 bool TcpStateTimeWait::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    trk.s_mgr.sub_state |= ( SUB_SYN_SENT | SUB_ACK_SENT );
+
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateTimeWait::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateTimeWait::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateTimeWait::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateTimeWait::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateTimeWait::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateTimeWait::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateTimeWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateTimeWait::rst_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
+    auto& trk = static_cast< TcpTracker& >( tracker );
 
-    return default_state_action(tsd, trk, __func__);
+    return default_state_action(tsd, trk);
 }
 
 bool TcpStateTimeWait::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
-    TcpTracker& trk = static_cast< TcpTracker& >( tracker );
-
-    return default_state_action(tsd, trk, __func__);
+    auto& trk = static_cast< TcpTracker& >( tracker );
+
+    if ( trk.update_on_rst_recv(tsd) )
+    {
+        session.update_session_on_rst(tsd, false);
+        session.update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
+        session.set_pkt_action_flag(ACTION_RST);
+    }
+    else
+    {
+        session.tel.set_tcp_event(EVENT_BAD_RST);
+    }
+
+    return default_state_action(tsd, trk);
 }
 
index 181335b4f02d852da93d99b21b1b5bb2361335d8..710943dfb4bcdffaa879e20001474d0a229e09f4 100644 (file)
 // Created on: Oct 22, 2015
 
 #include "main/snort_config.h"
-#include "time/packet_time.h"
-#include "stream/stream.h"
 #include "tcp_stream_config.h"
 
-static const char* const reassembly_policy_names[] = { "no policy", "first",
-                                                       "last", "linux", "old_linux", "bsd",
-                                                       "macos", "solaris", "irix",
-                                                       "hpux11", "hpux10", "windows", "win_2003",
-                                                       "vista", "proxy" };
+static const char* const reassembly_policy_names[] =
+{ "no policy", "first", "last", "linux", "old_linux", "bsd", "macos", "solaris", "irix",
+  "hpux11", "hpux10", "windows", "win_2003", "vista", "proxy" };
 
 TcpStreamConfig::TcpStreamConfig(void)
 {
-    policy = StreamPolicy::OS_DEFAULT;
-    reassembly_policy = ReassemblyPolicy::OS_DEFAULT;
-
-    flags = 0;
-    flush_factor = 0;
-
-    session_timeout = STREAM_DEFAULT_SSN_TIMEOUT;
-    max_window = 0;
-    overlap_limit = 0;
-
-    max_queued_bytes = STREAM_DEFAULT_MAX_QUEUED_BYTES;
-    max_queued_segs = STREAM_DEFAULT_MAX_QUEUED_SEGS;
-
-    max_consec_small_segs = STREAM_DEFAULT_CONSEC_SMALL_SEGS;
-    max_consec_small_seg_size = STREAM_DEFAULT_MAX_SMALL_SEG_SIZE;
-
-    hs_timeout = -1;
-    footprint = 0;
-    paf_max = 16384;
-}
-
-bool TcpStreamConfig::require_3whs(void)
-{
-    return hs_timeout >= 0;
-}
-
-bool TcpStreamConfig::midstream_allowed(Packet* p)
-{
-    if ( ( hs_timeout < 0 ) || ( p->pkth->ts.tv_sec - packet_first_time() < hs_timeout ) )
-        return true;
-
-    return false;
 }
 
 void TcpStreamConfig::show_config(void)
index 584c3cfc3a3ade312b9d57faa4172624fc327100..4dd590f0b28df765c59e2acb952bb693d65762b4 100644 (file)
@@ -22,6 +22,9 @@
 #ifndef TCP_STREAM_CONFIG_H
 #define TCP_STREAM_CONFIG_H
 
+#include "time/packet_time.h"
+#include "stream/stream.h"
+
 #include "tcp_defs.h"
 
 class TcpStreamConfig
@@ -29,31 +32,42 @@ class TcpStreamConfig
 public:
     TcpStreamConfig(void);
 
-    bool require_3whs(void);
-    bool midstream_allowed(Packet*);
+    bool require_3whs(void)
+    {
+        return hs_timeout >= 0;
+    }
+
+    bool midstream_allowed(Packet* p)
+    {
+        if ( ( hs_timeout < 0 ) || ( p->pkth->ts.tv_sec - packet_first_time() < hs_timeout ) )
+            return true;
+
+        return false;
+    }
+
     int verify_config(SnortConfig*);
     void show_config(void);
     static void show_config(TcpStreamConfig*);
 
-    StreamPolicy policy;
-    ReassemblyPolicy reassembly_policy;
+    StreamPolicy policy = StreamPolicy::OS_DEFAULT;
+    ReassemblyPolicy reassembly_policy = ReassemblyPolicy::OS_DEFAULT;
 
-    uint16_t flags;
-    uint16_t flush_factor;
+    uint16_t flags = 0;
+    uint16_t flush_factor = 0;
 
-    uint32_t session_timeout;
-    uint32_t max_window;
-    uint32_t overlap_limit;
+    uint32_t session_timeout = STREAM_DEFAULT_SSN_TIMEOUT;
+    uint32_t max_window = 0;
+    uint32_t overlap_limit = 0;
 
-    uint32_t max_queued_bytes;
-    uint32_t max_queued_segs;
+    uint32_t max_queued_bytes = STREAM_DEFAULT_MAX_QUEUED_BYTES;
+    uint32_t max_queued_segs = STREAM_DEFAULT_MAX_QUEUED_SEGS;
 
-    uint32_t max_consec_small_segs;
-    uint32_t max_consec_small_seg_size;
+    uint32_t max_consec_small_segs = STREAM_DEFAULT_CONSEC_SMALL_SEGS;
+    uint32_t max_consec_small_seg_size = STREAM_DEFAULT_MAX_SMALL_SEG_SIZE;
 
-    int hs_timeout;
-    int footprint;
-    unsigned paf_max;
+    int hs_timeout = -1;
+    int footprint = 0;
+    uint32_t paf_max = 16384;
 };
 
 #endif
index 326bb3c5a33956a20d1b70cc46e1612172947cca..470d99d52ace6d91687920555c2df4e8af51cccc 100644 (file)
 #include "tcp_tracker.h"
 
 TcpTracker::TcpTracker(bool client) :
-    TcpStreamTracker(client), splitter(nullptr), normalizer(nullptr), reassembler(nullptr)
+    TcpStreamTracker(client)
 {
-    tcp_event = TCP_MAX_EVENTS;
-    init_tracker( );
 }
 
 TcpTracker::~TcpTracker(void)
@@ -41,19 +39,19 @@ TcpTracker::~TcpTracker(void)
 
 void TcpTracker::init_tracker(void)
 {
-    memset(&s_mgr, 0, sizeof( StateMgr ) );
+    memset(&s_mgr, 0, sizeof(s_mgr));
     s_mgr.state_queue = TcpStreamTracker::TCP_STATE_NONE;
-
-    tcp_state = TcpStreamTracker::TCP_STATE_NONE;
+    tcp_state = ( client_tracker ) ?
+        TcpStreamTracker::TCP_STATE_NONE : TcpStreamTracker::TCP_LISTEN;
     flush_policy = STREAM_FLPOLICY_IGNORE;
-    memset(&paf_state, 0, sizeof( PAF_State ) );
+    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;
-    memset(mac_addr, 0, 6);
-    flags = 0;
+    tf_flags = 0;
     alert_count = 0;
-    memset(alerts, 0, sizeof( alerts ) );
+    memset(&alerts, 0, sizeof(alerts));
+    memset(&mac_addr, 0, sizeof(mac_addr));
 
     delete splitter;
     splitter = nullptr;
@@ -111,27 +109,25 @@ void TcpTracker::init_on_syn_sent(TcpSegmentDescriptor& tsd)
     if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
         tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
 
-    iss = tsd.get_seq();
-    snd_una = tsd.get_seq() + 1;
-    if ( tsd.get_seq() == tsd.get_end_seq() )
-        snd_nxt = snd_una;
-    else
-        snd_nxt = snd_una + ( tsd.get_end_seq() - tsd.get_seq() - 1 );
+    iss = tsd.get_seg_seq();
+    snd_una = iss;
+    snd_nxt = tsd.get_end_seq();
+    snd_wnd =  tsd.get_seg_wnd();
 
-    snd_wnd =  tsd.get_win();
     ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
-
-    flags |= normalizer->get_tcp_timestamp(tsd, false);
+    tf_flags |= normalizer->get_tcp_timestamp(tsd, false);
     ts_last = tsd.get_ts();
     if (ts_last == 0)
-        flags |= TF_TSTAMP_ZERO;
-    flags |= tsd.init_mss(&mss);
-    flags |= tsd.init_wscale(&wscale);
+        tf_flags |= TF_TSTAMP_ZERO;
+    tf_flags |= tsd.init_mss(&mss);
+    tf_flags |= tsd.init_wscale(&wscale);
+    s_mgr.sub_state |= SUB_SYN_SENT;
 
     cache_mac_address(tsd, FROM_CLIENT);
     set_splitter(tsd.get_flow() );
     init_flush_policy( );
 
+    tcpStats.sessions_on_syn++;
     tcp_state = TcpStreamTracker::TCP_SYN_SENT;
 }
 
@@ -139,15 +135,17 @@ void TcpTracker::init_on_syn_recv(TcpSegmentDescriptor& tsd)
 {
     Profile profile(s5TcpNewSessPerfStats);
 
-    reassembler->set_seglist_base_seq(tsd.get_seq() + 1);
-    r_nxt_ack = tsd.get_seq() + 1;
-    r_win_base = tsd.get_seq() + 1;
+    irs = tsd.get_seg_seq();
+    // FIXIT - 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);
     set_splitter(tsd.get_flow() );
     init_flush_policy( );
 
-    tcp_state = TcpStreamTracker::TCP_LISTEN;
+    tcp_state = TcpStreamTracker::TCP_SYN_RECV;
 }
 
 void TcpTracker::init_on_synack_sent(TcpSegmentDescriptor& tsd)
@@ -160,27 +158,30 @@ void TcpTracker::init_on_synack_sent(TcpSegmentDescriptor& tsd)
     if (tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE))
         tsd.get_flow()->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
 
-    iss =tsd.get_seq();
-    snd_una = tsd.get_seq() + 1;
-    snd_nxt = snd_una;
-    snd_wnd = tsd.get_win();
+    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();
 
-    reassembler->set_seglist_base_seq(tsd.get_ack() );
-    r_win_base = tsd.get_ack();
-    r_nxt_ack = tsd.get_ack();
-    ts_last_packet = tsd.get_pkt()->pkth->ts.tv_sec;
+    r_win_base = tsd.get_seg_ack();
+    r_nxt_ack = tsd.get_seg_ack();
+    reassembler->set_seglist_base_seq(tsd.get_seg_ack() );
 
-    flags |= normalizer->get_tcp_timestamp(tsd, false);
+    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 )
-        flags |= TF_TSTAMP_ZERO;
-    flags |= tsd.init_mss(&mss);
-    flags |= tsd.init_wscale(&wscale);
+        tf_flags |= TF_TSTAMP_ZERO;
+    tf_flags |= tsd.init_mss(&mss);
+    tf_flags |= tsd.init_wscale(&wscale);
+    s_mgr.sub_state |= ( SUB_SYN_SENT | SUB_ACK_SENT );
 
     cache_mac_address(tsd, FROM_SERVER);
     set_splitter(tsd.get_flow() );
     init_flush_policy();
 
+    tcpStats.sessions_on_syn_ack++;
     tcp_state = TcpStreamTracker::TCP_SYN_RECV;
 }
 
@@ -188,11 +189,14 @@ void TcpTracker::init_on_synack_recv(TcpSegmentDescriptor& tsd)
 {
     Profile profile(s5TcpNewSessPerfStats);
 
-    reassembler->set_seglist_base_seq(tsd.get_seq() + 1);
-    iss = tsd.get_ack() - 1;
-    r_nxt_ack = tsd.get_seq() + 1;
-    r_win_base = tsd.get_seq() + 1;
-    snd_nxt = tsd.get_ack();
+    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);
     set_splitter(tsd.get_flow() );
@@ -210,17 +214,22 @@ void TcpTracker::init_on_3whs_ack_sent(TcpSegmentDescriptor& tsd)
     if ( tsd.get_tcph()->are_flags_set(TH_CWR | TH_ECE) )
         tsd.get_flow()->set_session_flags(SSNFLAG_ECN_CLIENT_QUERY);
 
-    iss = tsd.get_seq();
-    snd_una = tsd.get_seq() + 1;
-    snd_nxt = tsd.get_seq() + 1;
-    snd_wnd = tsd.get_win();
+    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;
-    flags |= normalizer->get_tcp_timestamp(tsd, false);
+    tf_flags |= normalizer->get_tcp_timestamp(tsd, false);
     ts_last = tsd.get_ts();
     if (ts_last == 0)
-        flags |= TF_TSTAMP_ZERO;
-    flags |= tsd.init_mss(&mss);
-    flags |= tsd.init_wscale(&wscale);
+        tf_flags |= TF_TSTAMP_ZERO;
+    tf_flags |= tsd.init_mss(&mss);
+    tf_flags |= tsd.init_wscale(&wscale);
+    s_mgr.sub_state |= SUB_ACK_SENT;
 
     cache_mac_address(tsd, FROM_CLIENT);
     set_splitter(tsd.get_flow() );
@@ -232,9 +241,14 @@ void TcpTracker::init_on_3whs_ack_recv(TcpSegmentDescriptor& tsd)
 {
     Profile profile(s5TcpNewSessPerfStats);
 
-    reassembler->set_seglist_base_seq(tsd.get_seq() + 1);
-    r_nxt_ack = tsd.get_seq() + 1;
-    r_win_base = tsd.get_seq() + 1;
+    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);
     set_splitter(tsd.get_flow() );
@@ -246,29 +260,31 @@ void TcpTracker::init_on_data_seg_sent(TcpSegmentDescriptor& tsd)
 {
     Profile profile(s5TcpNewSessPerfStats);
 
-    iss = tsd.get_seq();
-    snd_una = tsd.get_seq();
-    snd_nxt = tsd.get_seq();
-    snd_wnd = tsd.get_win();
-    if ( tsd.get_direction() == FROM_SERVER )
-    {
-        r_win_base = tsd.get_ack();
-        r_nxt_ack = tsd.get_ack();
-        reassembler->set_seglist_base_seq(tsd.get_ack() );
-    }
+    Flow* flow = tsd.get_flow();
+
+    if ( flow->ssn_state.direction == FROM_CLIENT )
+        flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
     else
-    {
-        r_win_base = 0;
-        r_nxt_ack = 0;
-    }
+        flow->set_session_flags(SSNFLAG_SEEN_SERVER);
+
+    // FIXIT - 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;
-    flags |= normalizer->get_tcp_timestamp(tsd, 0);
+    tf_flags |= normalizer->get_tcp_timestamp(tsd, 0);
     ts_last = tsd.get_ts();
     if (ts_last == 0)
-        flags |= TF_TSTAMP_ZERO;
-    flags |= tsd.init_mss(&mss);
-    flags |= tsd.init_wscale(&wscale);
+        tf_flags |= TF_TSTAMP_ZERO;
+    tf_flags |= ( tsd.init_mss(&mss) | tsd.init_wscale(&wscale) );
+    s_mgr.sub_state |= SUB_ACK_SENT;
 
     cache_mac_address(tsd, tsd.get_direction() );
     set_splitter(tsd.get_flow() );
@@ -280,15 +296,16 @@ void TcpTracker::init_on_data_seg_recv(TcpSegmentDescriptor& tsd)
 {
     Profile profile(s5TcpNewSessPerfStats);
 
-    if ( tsd.get_direction() == FROM_SERVER )
-        iss = tsd.get_ack() - 1;
-    else
-        snd_una = tsd.get_ack() - 1;
-
-    r_nxt_ack = tsd.get_seq();
-    r_win_base = tsd.get_seq();
+    // FIXIT - should we init these?
+    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 */
-    reassembler->set_seglist_base_seq(tsd.get_seq() );
+
+    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() );
     set_splitter(tsd.get_flow() );
@@ -296,6 +313,245 @@ void TcpTracker::init_on_data_seg_recv(TcpSegmentDescriptor& tsd)
     tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
 }
 
+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 - 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 + 1;
+    }
+}
+
+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 - 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();
+
+    snd_wnd = tsd.get_seg_wnd();
+
+    s_mgr.sub_state |= SUB_ACK_SENT;
+
+    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 );
+
+        /* Indicate this packet completes 3-way handshake */
+        tsd.get_pkt()->packet_flags |= PKT_STREAM_TWH;
+        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(void)
+{
+    tcp_state = TcpStreamTracker::TCP_CLOSED;
+    s_mgr.sub_state |= SUB_RST_SENT;
+}
+
+#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;
+
+    /* check for valid seqeuence/retrans */
+    if ( tcp_state >= TcpStreamTracker::TCP_ESTABLISHED )
+    {
+        //and
+        //and !ValidSeq(listener, tsd))
+        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(void)
 {
     LogMessage(" + TcpTracker +\n");
index 7813e5b7f23f659023eec605a765d63b883c5920..b44227c3630093669855ffefed318e11dfb0cacd 100644 (file)
@@ -29,7 +29,7 @@
 struct StateMgr
 {
     uint8_t sub_state;
-    enum TcpStreamTracker::TcpStates state_queue;
+    enum TcpStreamTracker::TcpState state_queue;
     uint8_t expected_flags;
     uint32_t transition_seq;
     uint32_t stq_get_seq;
@@ -79,6 +79,7 @@ class TcpTracker : public TcpStreamTracker
 public:
     TcpTracker(bool);
     virtual ~TcpTracker(void);
+
     void init_tracker(void);
     void print(void);
     void init_flush_policy(void);
@@ -93,26 +94,29 @@ public:
     void init_on_3whs_ack_recv(TcpSegmentDescriptor& tsd);
     void init_on_data_seg_sent(TcpSegmentDescriptor& tsd);
     void init_on_data_seg_recv(TcpSegmentDescriptor& tsd);
-
+    void finish_server_init(TcpSegmentDescriptor& tsd);
+    void finish_client_init(TcpSegmentDescriptor& tsd);
+
+    void update_tracker_ack_recv(TcpSegmentDescriptor& tsd);
+    void update_tracker_ack_sent(TcpSegmentDescriptor& tsd);
+    bool update_on_3whs_ack(TcpSegmentDescriptor& tsd);
+    bool update_on_rst_recv(TcpSegmentDescriptor& tsd);
+    void update_on_rst_sent(void);
+
+    bool is_segment_seq_valid(TcpSegmentDescriptor& tsd);
+
+    StreamSplitter* splitter = nullptr;
+    TcpNormalizer* normalizer = nullptr;
+    TcpReassembler* reassembler = nullptr;
+    uint32_t small_seg_count = 0;
+    uint8_t alert_count = 0;
+    StreamAlertInfo alerts[MAX_SESSION_ALERTS];
     StateMgr s_mgr; /* state tracking goodies */
-
+    FlushPolicy flush_policy = STREAM_FLPOLICY_IGNORE;
     // this is intended to be private to paf but is included
     // directly to avoid the need for allocation; do not directly
     // manipulate within this module.
     PAF_State paf_state;    // for tracking protocol aware flushing
-    FlushPolicy flush_policy;
-    StreamSplitter* splitter;
-    TcpNormalizer* normalizer;
-    TcpReassembler* reassembler;
-
-    uint32_t r_nxt_ack; /* next expected ack from remote side */
-    uint32_t r_win_base; /* remote side window base sequence number
-     * (i.e. the last ack we got) */
-
-    uint32_t small_seg_count;
-
-    uint8_t alert_count; /* number alerts stored (up to MAX_SESSION_ALERTS) */
-    StreamAlertInfo alerts[MAX_SESSION_ALERTS]; /* history of alerts */
 };
 
 #endif