]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #34 in SNORT/snort3 from stream_dev to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 2 Oct 2015 17:11:43 +0000 (13:11 -0400)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 2 Oct 2015 17:11:43 +0000 (13:11 -0400)
Squashed commit of the following:

commit 0029a412c7434f5a32c8ebf06e688695241057e2
Merge: 1d6c94b e662907
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Wed Sep 23 17:05:47 2015 +0000

    Merge branch 'stream_dev' of https://stash-eng-rtp1.cisco.com/stash/scm/snort/snort3 into stream_dev

commit 1d6c94baecd2f800144c46d90aa54662502ba1ce
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Wed Sep 23 12:55:01 2015 -0400

    code cleanup from review comments, add c/s trackers, session to tcp norm class, use tcp flags helper functions

commit b2b73179b98333fd22d9cd9f2dfdc5da718b8d71
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Tue Sep 22 09:22:30 2015 -0400

    fix merge issue after rebase with master

commit 6a18d85328ea868fddccab5e9a2804a35808e4dc
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Tue Sep 15 12:50:24 2015 -0400

    merge of latest tcp normalization refactoring

commit e662907c2639d9d2459158624538da7fc03565e6
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Wed Sep 23 12:55:01 2015 -0400

    code cleanup from review comments, add c/s trackers, session to tcp norm class, use tcp flags helper functions

commit 2c349a9753993ce2d60cb119ac0d8e29a6d10d8e
Merge: b97bed9 3a88b13
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Tue Sep 22 10:14:51 2015 -0400

    fix merge issue pulling latest from origin

commit b97bed97696dc55b79961c3b154594bfb78fe029
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Tue Sep 22 09:22:30 2015 -0400

    fix merge issue after rebase with master

commit 797672c0dd77a424b4fa0480ce30767726a6cac0
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Tue Sep 15 12:50:24 2015 -0400

    merge of latest tcp normalization refactoring

commit 3a88b134a557fc33cd30095588dd82d6c1d58fa1
Author: davis mcpherson <davis.mcpherson@gmail.com>
Date:   Tue Sep 15 12:50:24 2015 -0400

    merge of latest tcp normalization refactoring

29 files changed:
src/flow/flow.h
src/main/snort.cc
src/network_inspectors/normalize/norm_module.cc
src/network_inspectors/port_scan/ps_detect.cc
src/protocols/tcp.h
src/service_inspectors/dns/dns.cc
src/service_inspectors/ftp_telnet/ftp_data.cc
src/service_inspectors/imap/imap.cc
src/service_inspectors/pop/pop.cc
src/service_inspectors/sip/sip.cc
src/service_inspectors/sip/sip_dialog.cc
src/service_inspectors/smtp/smtp.cc
src/service_inspectors/ssh/ssh.cc
src/service_inspectors/ssl/ssl_inspector.cc
src/stream/stream_api.cc
src/stream/stream_api.h
src/stream/tcp/CMakeLists.txt
src/stream/tcp/Makefile.am
src/stream/tcp/tcp_defs.h
src/stream/tcp/tcp_normalization.cc [deleted file]
src/stream/tcp/tcp_normalization.h [deleted file]
src/stream/tcp/tcp_normalizer.cc [new file with mode: 0644]
src/stream/tcp/tcp_normalizer.h [new file with mode: 0644]
src/stream/tcp/tcp_normalizers.cc [new file with mode: 0644]
src/stream/tcp/tcp_normalizers.h [new file with mode: 0644]
src/stream/tcp/tcp_reassembly.cc
src/stream/tcp/tcp_reassembly.h
src/stream/tcp/tcp_session.cc
src/stream/tcp/tcp_session.h

index f23140bda9881e5f1766917834d065d9bdcac1e7..9ef6b1d1c0404d8f8974f9da756d1cef634c8a86 100644 (file)
@@ -156,6 +156,7 @@ public:
     void call_handlers(Packet* p, bool eof = false);
 
     void markup_packet_flags(Packet*);
+
     void set_direction(Packet*);
 
     void set_expire(const Packet*, uint32_t timeout);
@@ -164,6 +165,39 @@ public:
 
     void set_ttl(Packet*, bool client);
 
+    uint32_t update_session_flags( uint32_t flags )
+    {
+        return ssn_state.session_flags = flags;
+    }
+
+    uint32_t set_session_flags(uint32_t flags)
+    {
+        return ssn_state.session_flags |= flags;
+    }
+
+    uint32_t clear_session_flags(uint32_t flags)
+    {
+        return ssn_state.session_flags &= ~flags;
+    }
+
+    uint32_t get_session_flags(void)
+    {
+        return ssn_state.session_flags;
+    }
+
+    int get_ignore_direction(void)
+    {
+        return ssn_state.ignore_direction;
+    }
+
+    int set_ignore_direction(char ignore_direction)
+    {
+        if (ssn_state.ignore_direction != ignore_direction)
+            ssn_state.ignore_direction = ignore_direction;
+
+        return ssn_state.ignore_direction;
+    }
+
     bool two_way_traffic()
     { return (ssn_state.session_flags & SSNFLAG_SEEN_BOTH) == SSNFLAG_SEEN_BOTH; }
 
@@ -260,7 +294,6 @@ public:  // FIXIT-M privatize if possible
     unsigned policy_id;
 
     FlowState flow_state;
-    LwState ssn_state;
 
     // FIXIT-L can client and server ip and port be removed from flow?
     sfip_t client_ip; // FIXIT-L family and bits should be changed to uint16_t
@@ -281,6 +314,10 @@ public:  // FIXIT-M privatize if possible
     uint8_t  outer_client_ttl, outer_server_ttl;
 
     uint8_t  response_count;
+
+public:
+    LwState ssn_state;
+
 };
 
 #endif
index 801ea723673eb6a4dfac75a2e54cd7f095d43f05..23320d53ffcb488b93f359fe69d53f532cea1c42 100644 (file)
@@ -100,6 +100,7 @@ using namespace std;
 #include "control/idle_processing.h"
 #include "file_api/file_service.h"
 #include "flow/flow_control.h"
+#include "flow/flow.h"
 #include "stream/stream.h"
 #include "target_based/sftarget_reader.h"
 
@@ -784,7 +785,7 @@ static DAQ_Verdict update_verdict(DAQ_Verdict verdict, int& inject)
         }
     }
     else if ( (s_packet->packet_flags & PKT_IGNORE) ||
-        (stream.get_ignore_direction(s_packet->flow) == SSN_DIR_BOTH) )
+        (s_packet->flow && s_packet->flow->get_ignore_direction( ) == SSN_DIR_BOTH) )
     {
         if ( !Active::get_tunnel_bypass() )
         {
@@ -798,7 +799,8 @@ static DAQ_Verdict update_verdict(DAQ_Verdict verdict, int& inject)
     }
     else if ( s_packet->ptrs.decode_flags & DECODE_PKT_TRUST )
     {
-        stream.set_ignore_direction(s_packet->flow, SSN_DIR_BOTH);
+        if(s_packet->flow)
+            s_packet->flow->set_ignore_direction(SSN_DIR_BOTH);
         verdict = DAQ_VERDICT_WHITELIST;
     }
     else
index b01cd2e5af070d60e9ec8915e3d7dfa5676ac229..372b504884ed69a3fa9da86a78585f0621d91439 100644 (file)
@@ -25,6 +25,7 @@
 #include <vector>
 
 #include "stream/stream.h"
+#include "stream/tcp/tcp_normalizer.h"
 
 using namespace std;
 
@@ -394,7 +395,7 @@ const PegInfo* NormalizeModule::get_pegs() const
         p++;
     }
 
-    p = Stream_GetNormPegs();
+    p = TcpNormalizer::get_normalization_pegs();
     assert(p);
 
     while ( p->name )
@@ -422,7 +423,7 @@ PegCount* NormalizeModule::get_counts() const
         counts.push_back(p[i][NORM_MODE_TEST]);
     }
 
-    p = Stream_GetNormCounts(c);
+    p = TcpNormalizer::get_normalization_counts(c);
 
     for ( unsigned i = 0; i < c; ++i )
     {
index f2a4b49bc1dceef14b740d17691d76eb3e999956..5ceb1f8c5bcaeedb5d9d153d1d257b0a5e95f9ab 100644 (file)
@@ -784,7 +784,7 @@ int PortScan::ps_tracker_update_tcp(PS_PKT* ps_pkt, PS_TRACKER* scanner,
     **  Otherwise, only consider streams not picked up midstream.
     */
     if ( p->flow )
-        session_flags = stream.get_session_flags(p->flow);
+        session_flags = p->flow->get_session_flags();
 
     if ( session_flags & (SSNFLAG_SEEN_CLIENT|SSNFLAG_SEEN_SERVER) )
     {
index 59ff84ca6458fd8bc06448add784edd498db5e49..61e751ee5b92bb2cda2ca07f39df5851f9efd305 100644 (file)
@@ -71,14 +71,14 @@ struct TCPHdr
     uint16_t th_sport;     /* source port */
     uint16_t th_dport;     /* destination port */
     uint32_t th_seq;       /* sequence number */
-    uint32_t th_ack;       /* acknowledgement number */
+    uint32_t th_ack;       /* acknowledgment number */
     uint8_t th_offx2;      /* offset and reserved */
     uint8_t th_flags;
     uint16_t th_win;       /* window */
     uint16_t th_sum;       /* checksum */
     uint16_t th_urp;       /* urgent pointer */
 
-    /* Fomatted data access and booleans */
+    /* Formatted data access and booleans */
     inline uint8_t hlen() const
     { return (th_offx2 & 0xf0) >> 2; }
 
@@ -119,10 +119,10 @@ struct TCPHdr
     { return (th_flags & TH_SYN); }
 
     inline bool is_syn_only() const
-    { return (th_flags & (TH_SYN|TH_ACK)) == TH_SYN; }
+    { return (th_flags & (TH_SYN | TH_ACK | TH_RST | TH_FIN)) == TH_SYN; }
 
     inline bool is_syn_ack() const
-    { return are_flags_set(TH_SYN|TH_ACK); }
+    { return are_flags_set(TH_SYN | TH_ACK); }
 
     inline bool is_ack() const
     { return (th_flags & TH_ACK); }
index 07bef715ff3f13240e872944d67a5b6c8ff2d052..0edc3dc1d043c49446f5b57496f668dcf6dcfc48 100644 (file)
@@ -1005,7 +1005,7 @@ static void snort_dns(Packet* p)
         /* If session picked up mid-stream, do not process further.
          * Would be almost impossible to tell where we are in the
          * data stream. */
-        if ( stream.get_session_flags(p->flow) & SSNFLAG_MIDSTREAM )
+        if ( p->flow->get_session_flags() & SSNFLAG_MIDSTREAM )
         {
             return;
         }
@@ -1085,6 +1085,7 @@ void Dns::eval(Packet* p)
 {
     // precondition - what we registered for
     assert((p->is_udp() and p->dsize and p->data) or p->has_tcp_data());
+    assert(p->flow);
 
     ++dnsstats.total_packets;
     snort_dns(p);
index f1cf5e47b083b3b421c0130faf697d5e0ae00ff2..82ca6eb3fb0a279397dc1d01e369d47b1b0c0f36 100644 (file)
@@ -91,7 +91,7 @@ static void FTPDataProcess(
      * and preprocessor was configured to ignore ftp-data sessions. */
     if (!status && data_ssn->data_chan)
     {
-        stream.set_ignore_direction(p->flow, SSN_DIR_BOTH);
+        p->flow->set_ignore_direction(SSN_DIR_BOTH);
     }
 }
 
@@ -130,7 +130,8 @@ static int SnortFTPData(Packet* p)
                 "FTP-DATA Invalid FTP_SESSION retrieved durring lookup\n");
 
             if (data_ssn->data_chan)
-                stream.set_ignore_direction(p->flow, SSN_DIR_BOTH);
+                p->flow->set_ignore_direction(SSN_DIR_BOTH);
+
 
             return -2;
         }
@@ -144,7 +145,7 @@ static int SnortFTPData(Packet* p)
         case FTPP_FILE_IGNORE:
             /* This wasn't a file transfer; ignore it */
             if (data_ssn->data_chan)
-                stream.set_ignore_direction(p->flow, SSN_DIR_BOTH);
+                p->flow->set_ignore_direction(SSN_DIR_BOTH);
             return 0;
 
         default:
index 971ed6e25d0bdf910ba3b4c419c379080eaad7bb..7c27b07a18442a4db9ed36fe0c3408e7a3843f00 100644 (file)
@@ -634,7 +634,7 @@ static void snort_imap(IMAP_PROTO_CONF* config, Packet* p)
             {
                 imap_ssn->state = STATE_TLS_DATA;
             }
-            else if (!(stream.get_session_flags(p->flow) & SSNFLAG_MIDSTREAM)
+            else if (!(p->flow->get_session_flags() & SSNFLAG_MIDSTREAM)
                 && !stream.missed_packets(p->flow, SSN_DIR_BOTH))
             {
                 /* revert back to command state - assume server didn't accept STARTTLS */
@@ -764,6 +764,7 @@ void Imap::eval(Packet* p)
     PROFILE_VARS;
     // precondition - what we registered for
     assert(p->has_tcp_data());
+    assert(p->flow);
 
     ++imapstats.total_packets;
 
index 3de4a41306298d0ffb0abdc46667deec79241b42..88f97b5557296f27a058416e7b2354647ade8354 100644 (file)
@@ -569,7 +569,7 @@ static void snort_pop(POP_PROTO_CONF* config, Packet* p)
             {
                 pop_ssn->state = STATE_TLS_DATA;
             }
-            else if (!(stream.get_session_flags(p->flow) & SSNFLAG_MIDSTREAM)
+            else if (!(p->flow->get_session_flags() & SSNFLAG_MIDSTREAM)
                 && !stream.missed_packets(p->flow, SSN_DIR_BOTH))
             {
                 /* revert back to command state - assume server didn't accept STARTTLS */
@@ -699,6 +699,7 @@ void Pop::eval(Packet* p)
     PROFILE_VARS;
     // precondition - what we registered for
     assert(p->has_tcp_data());
+    assert(p->flow);
 
     ++popstats.total_packets;
 
index 25732168f73b8b34ea681a4dc00b0649b5f8af42..7884852b72867c8c6d4aa009e5d53df6a9d8c460 100644 (file)
@@ -335,6 +335,7 @@ void Sip::eval(Packet* p)
 {
     // precondition - what we registered for
     assert((p->is_udp() and p->dsize and p->data) or p->has_tcp_data());
+    assert(p->flow);
 
     ++sipstats.total_packets;
     snort_sip(config, p);
index 624c9e56f165758efaf275fb8664ee42a10b49ba..fdb2338c0ff6339466d9fa257c9dc00895f090d3 100644 (file)
@@ -425,7 +425,7 @@ static int SIP_ignoreChannels(SIP_DialogData* dialog, Packet* p, SIP_PROTO_CONF*
 #endif
         if ( fd )
         {
-            stream.set_ignore_direction(p->flow, SSN_DIR_BOTH);
+            p->flow->set_ignore_direction(SSN_DIR_BOTH);
         }
         else
         {
index b175f5d78558e8eb0ffd093f043512845dc626e9..1afe973080220584c868abe8bb688d652f97c4f0 100644 (file)
@@ -1076,7 +1076,7 @@ static void SMTP_ProcessServerPacket(SMTP_PROTO_CONF* config, Packet* p, SMTPDat
         {
             smtp_ssn->state = STATE_TLS_DATA;
         }
-        else if (!(stream.get_session_flags(p->flow) & SSNFLAG_MIDSTREAM)
+        else if (!(p->flow->get_session_flags() & SSNFLAG_MIDSTREAM)
             && !stream.missed_packets(p->flow, SSN_DIR_BOTH))
         {
             /* Check to see if the raw packet is in order */
@@ -1527,6 +1527,7 @@ void Smtp::eval(Packet* p)
     PROFILE_VARS;
     // precondition - what we registered for
     assert(p->has_tcp_data());
+    assert(p->flow);
 
     ++smtpstats.total_packets;
 
index 2990eb7ee429e19bb2fcbc5f2db76fbc47a9e204..cf1df7573b9247882b2f588909c34cc2ea4df5e5 100644 (file)
@@ -186,7 +186,7 @@ static void snort_ssh(SSH_PROTO_CONF* config, Packet* p)
     /* If we picked up mid-stream or missed any packets (midstream pick up
      *      * means we've already missed packets) set missed packets flag and make
      *           * sure we don't do any more reassembly on this session */
-    if ((stream.get_session_flags(p->flow) & SSNFLAG_MIDSTREAM)
+    if ((p->flow->get_session_flags() & SSNFLAG_MIDSTREAM)
         || stream.missed_packets(p->flow, SSN_DIR_BOTH))
     {
         /* Order only matters if the packets are not encrypted */
@@ -809,6 +809,7 @@ void Ssh::eval(Packet* p)
 {
     // precondition - what we registered for
     assert(p->has_tcp_data());
+    assert(p->flow);
 
     ++sshstats.total_packets;
     snort_ssh(config, p);
index d4a3572953af1862c6ed516b4462f17b7eacb4ba..bafc090f06849d3b204ec1afe29433c71c51c044 100644 (file)
@@ -144,7 +144,7 @@ static inline bool SSLPP_is_encrypted(SSL_PROTO_CONF* config, uint32_t ssl_flags
         }
         /* Check if we're either midstream or if packets were missed after the
          *          * connection was established */
-        else if ((stream.get_session_flags (packet->flow) & SSNFLAG_MIDSTREAM) ||
+        else if ((packet->flow->get_session_flags() & SSNFLAG_MIDSTREAM) ||
             (stream.missed_packets(packet->flow, SSN_DIR_BOTH)))
         {
             if ((ssl_flags & (SSL_CAPP_FLAG | SSL_SAPP_FLAG)) == (SSL_CAPP_FLAG | SSL_SAPP_FLAG))
@@ -444,6 +444,7 @@ void Ssl::eval(Packet* p)
 {
     // precondition - what we registered for
     assert(p->has_tcp_data());
+    assert(p->flow);
 
     ++sslstats.total_packets;
     snort_ssl(config, p);
index e614ac7818a11ee506267ec303ec89127b791f0b..247f983bd5843edee7e001d419fd44a9f60c9f7c 100644 (file)
@@ -331,47 +331,6 @@ void Stream::drop_session(const Packet* p)
         drop_traffic(flow, SSN_DIR_BOTH);
 }
 
-uint32_t Stream::set_session_flags(Flow* flow, uint32_t flags)
-{
-    if ( !flow )
-        return 0;
-
-    if ((flow->ssn_state.session_flags & flags) != flags)
-    {
-        flow->ssn_state.session_flags |= flags;
-    }
-    return flow->ssn_state.session_flags;
-}
-
-uint32_t Stream::get_session_flags(Flow* flow)
-{
-    if ( !flow )
-        return 0;
-
-    return flow->ssn_state.session_flags;
-}
-
-int Stream::get_ignore_direction(Flow* flow)
-{
-    if ( !flow )
-        return 0;
-
-    return flow->ssn_state.ignore_direction;
-}
-
-int Stream::set_ignore_direction(Flow* flow, int ignore_direction)
-{
-    if ( !flow )
-        return 0;
-
-    if (flow->ssn_state.ignore_direction != ignore_direction)
-    {
-        flow->ssn_state.ignore_direction = ignore_direction;
-    }
-
-    return flow->ssn_state.ignore_direction;
-}
-
 //-------------------------------------------------------------------------
 // misc support
 //-------------------------------------------------------------------------
@@ -853,24 +812,24 @@ TEST_CASE("Stream API", "[stream_api][stream]")
 
     SECTION("set/get ignore direction")
     {
-        int dir = Stream::set_ignore_direction( flow, SSN_DIR_NONE);
+        int dir = flow->set_ignore_direction( SSN_DIR_NONE);
         CHECK( ( dir == SSN_DIR_NONE ) );
-        dir = Stream::get_ignore_direction( flow );
+        dir = flow->get_ignore_direction( );
         CHECK( ( dir == SSN_DIR_NONE ) );
 
-        dir = Stream::set_ignore_direction( flow, SSN_DIR_FROM_CLIENT);
+        dir = flow->set_ignore_direction( SSN_DIR_FROM_CLIENT);
         CHECK( ( dir == SSN_DIR_FROM_CLIENT ) );
-        dir = Stream::get_ignore_direction( flow );
+        dir = flow->get_ignore_direction( );
         CHECK( ( dir == SSN_DIR_FROM_CLIENT ) );
 
-        dir = Stream::set_ignore_direction( flow, SSN_DIR_FROM_SERVER);
+        dir = flow->set_ignore_direction( SSN_DIR_FROM_SERVER);
         CHECK( ( dir == SSN_DIR_FROM_SERVER ) );
-        dir = Stream::get_ignore_direction( flow );
+        dir = flow->get_ignore_direction( );
         CHECK( ( dir == SSN_DIR_FROM_SERVER ) );
 
-        dir = Stream::set_ignore_direction( flow, SSN_DIR_BOTH);
+        dir = flow->set_ignore_direction( SSN_DIR_BOTH);
         CHECK( ( dir == SSN_DIR_BOTH ) );
-        dir = Stream::get_ignore_direction( flow );
+        dir = flow->get_ignore_direction( );
         CHECK( ( dir == SSN_DIR_BOTH ) );
     }
 
@@ -881,12 +840,12 @@ TEST_CASE("Stream API", "[stream_api][stream]")
         int dir;
 
         Stream::stop_inspection( flow, pkt, SSN_DIR_FROM_CLIENT, 0, 0 );
-        dir = Stream::get_ignore_direction( flow );
+        dir = flow->get_ignore_direction( );
         CHECK( ( dir == SSN_DIR_FROM_CLIENT ) );
         CHECK( ( flow->flow_state == Flow::ALLOW ) );
 
         Stream::stop_inspection( flow, pkt, SSN_DIR_FROM_SERVER, 0, 0 );
-        dir = Stream::get_ignore_direction( flow );
+        dir = flow->get_ignore_direction( );
         CHECK( ( dir == SSN_DIR_FROM_SERVER ) );
         CHECK( ( flow->flow_state == Flow::ALLOW ) );
 
index 750b9a5b40d732cabd26170ab73fc98a04db108c..ddf78a5fc9a8a3041c53021ee146edee71b233f7 100644 (file)
@@ -241,15 +241,9 @@ public:
     static void set_application_protocol_id_from_host_entry(
         Flow*, const struct HostAttributeEntry*, int direction);
 
-    static uint32_t set_session_flags(Flow*, uint32_t flags);
-    static uint32_t get_session_flags(Flow*);
-
     static bool is_midstream(Flow* flow)
     { return flow->ssn_state.session_flags & SSNFLAG_MIDSTREAM; }
 
-    static int get_ignore_direction(Flow*);
-    static int set_ignore_direction(Flow*, int ignore_direction);
-
     // Get the TTL value used at session setup
     // Set outer=false to get inner ip ttl for ip in ip; else outer=true
     static uint8_t get_session_ttl(Flow*, char dir, bool outer);
index fd91a6aae56fe96ea4c372b8914f2361cec80e8a..aa9146e327a2a2c37aed3cac48cc582249264d17 100644 (file)
@@ -6,8 +6,10 @@ add_library( stream_tcp STATIC
     tcp_module.h
     tcp_defs.h
     tcp_events.h
-    tcp_normalization.h
-    tcp_normalization.cc
+    tcp_normalizer.h
+    tcp_normalizer.cc
+    tcp_normalizers.h
+    tcp_normalizers.cc
     tcp_reassembly.h
     tcp_reassembly.cc
     tcp_session.cc
index 18f2121ade9f21e66cc2421fa004b11dbe6b07e4..5845df44156864c254feabdfcf6119c35ab3a7ae 100644 (file)
@@ -9,8 +9,10 @@ tcp_module.h \
 tcp_debug_trace.h \
 tcp_defs.h \
 tcp_events.h \
-tcp_normalization.h \
-tcp_normalization.cc \
+tcp_normalizer.h \
+tcp_normalizer.cc \
+tcp_normalizers.h \
+tcp_normalizers.cc \
 tcp_reassembly.h \
 tcp_reassembly.cc \
 tcp_session.cc \
index 49d3f765008a7d83d9fab68a578a34d11d259c0a..23270e02aec5b2f47ce79c8a32dbd5935b3f7f9e 100644 (file)
@@ -23,6 +23,7 @@
 #define TCP_DEFS_H
 
 #include "main/snort_debug.h"
+#include "protocols/packet.h"
 
 /* TCP states */
 #define TCP_STATE_NONE         0
 #define REASSEMBLY_POLICY_VISTA      13
 #define REASSEMBLY_POLICY_DEFAULT    REASSEMBLY_POLICY_BSD
 
+/* target-based policy types */
+// changes to this enum require changes to stream_api.h::TCP_POLICIES
+#define STREAM_POLICY_FIRST       1
+#define STREAM_POLICY_LAST        2
+#define STREAM_POLICY_LINUX       3
+#define STREAM_POLICY_OLD_LINUX   4
+#define STREAM_POLICY_BSD         5
+#define STREAM_POLICY_MACOS       6
+#define STREAM_POLICY_SOLARIS     7
+#define STREAM_POLICY_IRIX        8
+#define STREAM_POLICY_HPUX11      9
+#define STREAM_POLICY_HPUX10     10
+#define STREAM_POLICY_WINDOWS    11
+#define STREAM_POLICY_WINDOWS2K3 12
+#define STREAM_POLICY_VISTA      13
+#define STREAM_POLICY_PROXY      14
+#define STREAM_POLICY_DEFAULT    STREAM_POLICY_BSD
+
 struct TcpDataBlock
 {
+    Packet* pkt;
     uint32_t seq;
     uint32_t ack;
     uint32_t win;
diff --git a/src/stream/tcp/tcp_normalization.cc b/src/stream/tcp/tcp_normalization.cc
deleted file mode 100644 (file)
index 33649e3..0000000
+++ /dev/null
@@ -1,407 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// tcp_normalization.cc author davis mcpherson <davmcphe@@cisco.com>
-// Created on: Jul 31, 2015
-
-#include "tcp_normalization.h"
-#include "tcp_events.h"
-
-THREAD_LOCAL PegCount normStats[PC_MAX][NORM_MODE_MAX];
-
-static const PegInfo pegName[] =
-{ { "tcp trim syn", "tcp segments trimmed on SYN" },
-  { "tcp trim rst", "RST packets with data trimmed" },
-  { "tcp trim win", "data trimed to window" },
-  { "tcp trim mss", "data trimmed to MSS" },
-  { "tcp ecn session", "ECN bits cleared" },
-  { "tcp ts nop", "timestamp options cleared" },
-  { "tcp ips data", "normalized segments" },
-  { "tcp block", "blocked segments" },
-  { nullptr, nullptr }
-};
-
-const PegInfo* Stream_GetNormPegs()
-{
-    return pegName;
-}
-
-NormPegs Stream_GetNormCounts(unsigned& c)
-{
-    c = PC_MAX;
-    return normStats;
-}
-
-static inline int SetupOK(const TcpTracker* st)
-{
-    return ((st->s_mgr.sub_state & SUB_SETUP_OK) == SUB_SETUP_OK);
-}
-
-uint32_t StreamGetWindow(Flow* flow, TcpTracker* st, TcpDataBlock* tdb)
-{
-    int32_t window;
-
-    if (st->l_window)
-    {
-        // don't use the window if we may have missed scaling
-        if (!(flow->session_state & STREAM_STATE_MIDSTREAM))
-            return st->l_window;
-    }
-    // one way zero window is unitialized
-    // two way zero window is actually closed (regardless of scaling)
-    else if (flow->two_way_traffic())
-        return st->l_window;
-
-    // ensure the data is in the window
-    window = tdb->end_seq - st->r_win_base;
-
-    if (window < 0)
-        window = 0;
-
-    return (uint32_t) window;
-}
-
-uint32_t StreamGetTcpTimestamp(Packet* p, uint32_t* ts, int strip)
-{
-    DebugMessage(DEBUG_STREAM_STATE, "Getting timestamp...\n");
-
-    const NormMode mode = Normalize_GetMode(NORM_TCP_OPT);
-    tcp::TcpOptIterator iter(p->ptrs.tcph, p);
-
-    // using const because non-const is not supported
-    for (const tcp::TcpOption& opt : iter)
-    {
-        if (opt.code == tcp::TcpOptCode::TIMESTAMP)
-        {
-            if (strip)
-            {
-                NormalStripTimeStamp(p, &opt, mode);
-            } else if (!strip || !NormalStripTimeStamp(p, &opt, mode))
-            {
-                *ts = EXTRACT_32BITS(opt.data);
-                DebugFormat(DEBUG_STREAM_STATE, "Found timestamp %lu\n", *ts);
-
-                return TF_TSTAMP;
-            }
-        }
-    }
-    *ts = 0;
-
-    DebugMessage(DEBUG_STREAM_STATE, "No timestamp...\n");
-
-    return TF_NONE;
-}
-
-// per rfc 793 a rst is valid if the seq number is in window
-// for all states but syn-sent (handled above).  however, we
-// validate here based on how various implementations actually
-// handle a rst.
-int ValidRst(Flow* flow, TcpTracker *st, TcpDataBlock *tdb)
-{
-    DebugFormat(DEBUG_STREAM_STATE, "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
-            tdb->end_seq, st->r_win_base, tdb->seq, st->r_nxt_ack+StreamGetWindow(flow, st, tdb));
-
-    switch (st->os_policy) {
-        case STREAM_POLICY_HPUX11:
-            if (SEQ_GEQ(tdb->seq, st->r_nxt_ack))
-            {
-                DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (>= next seq)!\n");
-                return 1;
-            }
-            DebugMessage(DEBUG_STREAM_STATE, "rst is not valid seq (>= next seq)!\n");
-            return 0;
-            break;
-        case STREAM_POLICY_FIRST:
-        case STREAM_POLICY_LAST:
-        case STREAM_POLICY_MACOS:
-        case STREAM_POLICY_WINDOWS:
-        case STREAM_POLICY_VISTA:
-        case STREAM_POLICY_WINDOWS2K3:
-        case STREAM_POLICY_HPUX10:
-        case STREAM_POLICY_IRIX:
-            if (SEQ_EQ(tdb->seq, st->r_nxt_ack))
-            {
-                DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (next seq)!\n");
-                return 1;
-            }
-            DebugMessage(DEBUG_STREAM_STATE, "rst is not valid seq (next seq)!\n");
-            return 0;
-            break;
-        case STREAM_POLICY_BSD:
-        case STREAM_POLICY_LINUX:
-        case STREAM_POLICY_OLD_LINUX:
-        case STREAM_POLICY_SOLARIS:
-            if (SEQ_GEQ(tdb->end_seq, st->r_win_base))
-            {
-                // reset must be admitted when window closed
-                if (SEQ_LEQ(tdb->seq,
-                            st->r_win_base + StreamGetWindow(flow, st, tdb)))
-                {
-                    DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (within window)!\n");
-                    return 1;
-                }
-            }
-
-            DebugMessage(DEBUG_STREAM_STATE, "rst is not valid seq (within window)!\n");
-            return 0;
-            break;
-    }
-
-    DebugMessage(DEBUG_STREAM_STATE, "rst is not valid!\n");
-    return 0;
-}
-
-int ValidTimestamp(TcpTracker *talker, TcpTracker *listener, TcpDataBlock *tdb, Packet *p,
-        int *eventcode, int *got_ts)
-{
-    if ( ( p->ptrs.tcph->th_flags & TH_RST )
-            or listener->config->policy == STREAM_POLICY_PROXY)
-        return ACTION_NOTHING;
-
-#if 0
-    if ( p->ptrs.tcph->th_flags & TH_ACK &&
-            Normalize_IsEnabled(NORM_TCP_OPT) )
-    {
-        // FIXIT-L validate tsecr here (check that it was previously sent)
-        // checking for the most recent ts is easy enough must check if
-        // ts are up to date in retransmitted packets
-    }
-#endif
-    /*
-     * check PAWS
-     */
-    if ((talker->flags & TF_TSTAMP) && (listener->flags & TF_TSTAMP))
-    {
-        char validate_timestamp = 1;
-        DebugMessage(DEBUG_STREAM_STATE, "Checking timestamps for PAWS\n");
-
-        *got_ts = StreamGetTcpTimestamp(p, &tdb->ts, 0);
-
-        if (*got_ts)
-        {
-            if (listener->config->policy == STREAM_POLICY_HPUX11)
-            {
-                /* HPUX 11 ignores timestamps for out of order segments */
-                if ((listener->flags & TF_MISSING_PKT)
-                        || !SEQ_EQ(listener->r_nxt_ack, tdb->seq))
-                {
-                    validate_timestamp = 0;
-                }
-            }
-
-            if (talker->flags & TF_TSTAMP_ZERO)
-            {
-                /* Handle the case where the 3whs used a 0 timestamp.  Next packet
-                 * from that endpoint should have a valid timestamp... */
-                if ((listener->config->policy == STREAM_POLICY_LINUX)
-                        || (listener->config->policy == STREAM_POLICY_WINDOWS2K3))
-                {
-                    /* Linux, Win2k3 et al.  do not support timestamps if
-                     * the 3whs used a 0 timestamp. */
-                    talker->flags &= ~TF_TSTAMP;
-                    listener->flags &= ~TF_TSTAMP;
-                    validate_timestamp = 0;
-                } else if ((listener->config->policy == STREAM_POLICY_OLD_LINUX)
-                        || (listener->config->policy == STREAM_POLICY_WINDOWS)
-                        || (listener->config->policy == STREAM_POLICY_VISTA))
-                {
-                    /* Older Linux (2.2 kernel & earlier), Win32 (non 2K3)
-                     * allow the 3whs to use a 0 timestamp. */
-                    talker->flags &= ~TF_TSTAMP_ZERO;
-                    if (SEQ_EQ(listener->r_nxt_ack, tdb->seq))
-                    {
-                        talker->ts_last = tdb->ts;
-                        validate_timestamp = 0; /* Ignore the timestamp for this
-                                                 * first packet, next one will
-                                                 * checked. */
-                    }
-                }
-            }
-
-            if (validate_timestamp)
-            {
-                int result = 0;
-                if (listener->config->policy == STREAM_POLICY_LINUX)
-                {
-                    /* Linux 2.6 accepts timestamp values that are off
-                     * by one. */
-                    result = (int) ((tdb->ts - talker->ts_last) + 1);
-                } else
-                {
-                    result = (int) (tdb->ts - talker->ts_last);
-                }
-
-                if (result < 0)
-                {
-                    DebugMessage(DEBUG_STREAM_STATE, "Packet outside PAWS window, dropping\n");
-                    /* bail, we've got a packet outside the PAWS window! */
-                    //inc_tcp_discards();
-                    *eventcode |= EVENT_BAD_TIMESTAMP;
-                    NormalDropPacketIf(p, NORM_TCP_OPT);
-                    return ACTION_BAD_PKT;
-                } else if ((talker->ts_last != 0)
-                        && ((uint32_t) p->pkth->ts.tv_sec
-                            > talker->ts_last_pkt + PAWS_24DAYS))
-                {
-                    /* this packet is from way too far into the future */
-                    DebugFormat(DEBUG_STREAM_STATE, "packet PAWS timestamp way too far ahead of last packet %d %d...\n",
-                            p->pkth->ts.tv_sec, talker->ts_last_pkt);
-                    //inc_tcp_discards();
-                    *eventcode |= EVENT_BAD_TIMESTAMP;
-                    NormalDropPacketIf(p, NORM_TCP_OPT);
-                    return ACTION_BAD_PKT;
-                } else
-                {
-                    DebugMessage(DEBUG_STREAM_STATE, "packet PAWS ok...\n");
-                }
-            }
-        }
-        else
-        {
-            /* we've got a packet with no timestamp, but 3whs indicated talker
-             * was doing timestamps.  This breaks protocol, however, some servers
-             * still ack the packet with the missing timestamp.  Log an alert,
-             * but continue to process the packet
-             */
-            *eventcode |= EVENT_NO_TIMESTAMP;
-            DebugMessage(DEBUG_STREAM_STATE, "packet no timestamp, had one earlier from this side...ok for now...\n");
-
-            if (listener->config->policy == STREAM_POLICY_SOLARIS)
-            {
-                /* Solaris stops using timestamps if it receives a packet
-                 * without a timestamp and there were timestamps in use.
-                 */
-                listener->flags &= ~TF_TSTAMP;
-            }
-            NormalDropPacketIf(p, NORM_TCP_OPT);
-        }
-    }
-    else if (p->ptrs.tcph->is_syn_only())
-    {
-        *got_ts = StreamGetTcpTimestamp(p, &tdb->ts, 0);
-        if (*got_ts)
-            talker->flags |= TF_TSTAMP;
-    }
-    else
-    {
-        // 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 where
-        // we disable timestamp handling.
-        int strip = (SetupOK(talker) && SetupOK(listener));
-        DebugMessage(DEBUG_STREAM_STATE, "listener not doing timestamps...\n");
-        *got_ts = StreamGetTcpTimestamp(p, &tdb->ts, strip);
-
-        if (*got_ts)
-        {
-            if (!(talker->flags & TF_TSTAMP))
-            {
-                /* Since we skipped the SYN, may have missed the talker's
-                 * timestamp there, so set it now.
-                 */
-                talker->flags |= TF_TSTAMP;
-                if (tdb->ts == 0)
-                {
-                    talker->flags |= TF_TSTAMP_ZERO;
-                }
-            }
-
-            /* Only valid to test this if listener is using timestamps.
-             * Otherwise, timestamp in this packet is not used, regardless
-             * of its value. */
-            if ((tdb->ts == 0) && (listener->flags & TF_TSTAMP))
-            {
-                switch (listener->os_policy) {
-                    case STREAM_POLICY_WINDOWS:
-                    case STREAM_POLICY_VISTA:
-                    case STREAM_POLICY_WINDOWS2K3:
-                    case STREAM_POLICY_OLD_LINUX:
-                    case STREAM_POLICY_SOLARIS:
-                        /* Old Linux & Windows allows a 0 timestamp value. */
-                        break;
-                    default:
-                        DebugMessage(DEBUG_STREAM_STATE, "Packet with 0 timestamp, dropping\n");
-                        //inc_tcp_discards();
-                        /* bail */
-                        *eventcode |= EVENT_BAD_TIMESTAMP;
-                        return ACTION_BAD_PKT;
-                }
-            }
-        }
-    }
-    return ACTION_NOTHING;
-}
-
-int RepeatedSyn(TcpTracker *listener, TcpTracker *talker, TcpDataBlock *tdb, TcpSession *tcpssn)
-{
-    switch (listener->os_policy)
-    {
-        case STREAM_POLICY_WINDOWS:
-        case STREAM_POLICY_WINDOWS2K3:
-        case STREAM_POLICY_VISTA:
-            /* 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(tdb->seq, listener->r_nxt_ack))
-            {
-                DebugMessage(DEBUG_STREAM_STATE, "Got syn on established windows ssn, which causes Reset, bailing\n");
-                tcpssn->flow->ssn_state.session_flags |= SSNFLAG_RESET;
-                talker->s_mgr.state = TCP_STATE_CLOSED;
-                return ACTION_RST;
-            } else
-            {
-                DebugMessage(DEBUG_STREAM_STATE, "Got syn on established windows ssn, not causing Reset, bailing\n");
-                inc_tcp_discards();
-                return ACTION_NOTHING;
-            }
-            break;
-
-        case STREAM_POLICY_MACOS:
-            /* MACOS ignores a 2nd SYN, regardless of the sequence number. */
-            DebugMessage(DEBUG_STREAM_STATE, "Got syn on established macos ssn, not causing Reset, bailing\n");
-            inc_tcp_discards();
-            return ACTION_NOTHING;
-            break;
-
-        case STREAM_POLICY_FIRST:
-        case STREAM_POLICY_LAST:
-        case STREAM_POLICY_LINUX:
-        case STREAM_POLICY_OLD_LINUX:
-        case STREAM_POLICY_BSD:
-        case STREAM_POLICY_SOLARIS:
-        case STREAM_POLICY_HPUX11:
-        case STREAM_POLICY_HPUX10:
-        case STREAM_POLICY_IRIX:
-            /* If its not a retransmission of the actual SYN... RESET */
-            if (!SEQ_EQ(tdb->seq, talker->isn))
-            {
-                DebugMessage(DEBUG_STREAM_STATE, "Got syn on established ssn, which causes Reset, bailing\n");
-                tcpssn->flow->ssn_state.session_flags |= SSNFLAG_RESET;
-                talker->s_mgr.state = TCP_STATE_CLOSED;
-                return ACTION_RST;
-            } else
-            {
-                DebugMessage(DEBUG_STREAM_STATE, "Got syn on established ssn, not causing Reset, bailing\n");
-                inc_tcp_discards();
-                return ACTION_NOTHING;
-            }
-            break;
-    }
-    return ACTION_NOTHING;
-}
diff --git a/src/stream/tcp/tcp_normalization.h b/src/stream/tcp/tcp_normalization.h
deleted file mode 100644 (file)
index 07b408a..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-// tcp_normalization.h author davis mcpherson <davmcphe@@cisco.com>
-// Created on: Jul 31, 2015
-
-#ifndef TCP_NORMALIZATION_H
-#define TCP_NORMALIZATION_H
-
-#include "main/snort_types.h"
-#include "framework/counts.h"
-#include "perf_monitor/perf.h"
-#include "protocols/tcp_options.h"
-#include "protocols/tcp.h"
-#include "normalize/normalize.h"
-#include "packet_io/active.h"
-#include "tcp_session.h"
-#include "tcp_defs.h"
-
-enum PegCounts
-{
-    PC_TCP_TRIM_SYN,
-    PC_TCP_TRIM_RST,
-    PC_TCP_TRIM_WIN,
-    PC_TCP_TRIM_MSS,
-    PC_TCP_ECN_SSN,
-    PC_TCP_TS_NOP,
-    PC_TCP_IPS_DATA,
-    PC_TCP_BLOCK,
-    PC_MAX
-};
-
-extern THREAD_LOCAL PegCount normStats[PC_MAX][NORM_MODE_MAX];
-
-/* target-based policy types */
-// changes to this enum require changes to stream_api.h::TCP_POLICIES
-#define STREAM_POLICY_FIRST       1
-#define STREAM_POLICY_LAST        2
-#define STREAM_POLICY_LINUX       3
-#define STREAM_POLICY_OLD_LINUX   4
-#define STREAM_POLICY_BSD         5
-#define STREAM_POLICY_MACOS       6
-#define STREAM_POLICY_SOLARIS     7
-#define STREAM_POLICY_IRIX        8
-#define STREAM_POLICY_HPUX11      9
-#define STREAM_POLICY_HPUX10     10
-#define STREAM_POLICY_WINDOWS    11
-#define STREAM_POLICY_WINDOWS2K3 12
-#define STREAM_POLICY_VISTA      13
-#define STREAM_POLICY_PROXY      14
-#define STREAM_POLICY_DEFAULT    STREAM_POLICY_BSD
-
-//-----------------------------------------------------------------------
-// instead of centralizing all these normalizations so that
-// Normalize_IsEnabled() is called only once, the checks and
-// normalizations are localized.  this should lead to many
-// fewer total checks.  however, it is best to minimize
-// configuration checks on a per packet basis so there is
-// still room for improvement.
-static inline bool NormalDropPacketIf(Packet* p, NormFlags f)
-{
-    const NormMode mode = Normalize_GetMode(f);
-
-    normStats[PC_TCP_BLOCK][mode]++;
-    sfBase.iPegs[PERF_COUNT_TCP_BLOCK][mode]++;
-
-    if (mode == NORM_MODE_ON)
-    {
-        Active::drop_packet(p);
-        return true;
-    }
-    return false;
-}
-
-static inline bool NormalStripTimeStamp(Packet* p, const tcp::TcpOption* opt, NormMode mode)
-{
-    normStats[PC_TCP_TS_NOP][mode]++;
-    sfBase.iPegs[PERF_COUNT_TCP_TS_NOP][mode]++;
-
-    if (mode == NORM_MODE_ON)
-    {
-        // set raw option bytes to nops
-        memset( ( void * ) opt, ( uint32_t ) tcp::TcpOptCode::NOP, tcp::TCPOLEN_TIMESTAMP);
-        p->packet_flags |= PKT_MODIFIED;
-        return true;
-    }
-    return false;
-}
-
-static inline void NormalTrimPayload(Packet* p, uint16_t max, TcpDataBlock* tdb)
-{
-    uint16_t fat = p->dsize - max;
-    p->dsize = max;
-    p->packet_flags |= (PKT_MODIFIED | PKT_RESIZED);
-    tdb->end_seq -= fat;
-}
-
-static inline void NormalTrimPayloadIf(Packet* p, uint32_t max, TcpDataBlock* tdb, NormFlags flag,
-        PegCounts peg, PerfCounts perf)
-{
-    const NormMode mode = Normalize_GetMode(flag);
-
-    if (mode == NORM_MODE_ON)
-        NormalTrimPayload(p, max, tdb);
-
-    normStats[peg][mode]++;
-    sfBase.iPegs[perf][mode]++;
-}
-
-static inline void NormalTrimPayloadIfSyn(Packet* p, uint32_t max, TcpDataBlock* tdb)
-{
-    if (p->dsize > max)
-        NormalTrimPayloadIf(p, max, tdb, NORM_TCP_TRIM_SYN,
-                PC_TCP_TRIM_SYN, PERF_COUNT_TCP_TRIM_SYN);
-}
-
-static inline void NormalTrimPayloadIfRst(Packet* p, uint32_t max, TcpDataBlock* tdb)
-{
-    if (p->dsize > max)
-        NormalTrimPayloadIf(p, max, tdb, NORM_TCP_TRIM_RST, PC_TCP_TRIM_RST,
-                PERF_COUNT_TCP_TRIM_RST);
-}
-
-static inline void NormalTrimPayloadIfWin(Packet* p, uint32_t max, TcpDataBlock* tdb)
-{
-    if (p->dsize > max)
-        NormalTrimPayloadIf(p, max, tdb, NORM_TCP_TRIM_WIN, PC_TCP_TRIM_WIN,
-                PERF_COUNT_TCP_TRIM_WIN);
-}
-
-static inline void NormalTrimPayloadIfMss(Packet* p, uint32_t max, TcpDataBlock* tdb)
-{
-    if (p->dsize > max)
-        NormalTrimPayloadIf(p, max, tdb, NORM_TCP_TRIM_MSS, PC_TCP_TRIM_MSS,
-                PERF_COUNT_TCP_TRIM_MSS);
-}
-
-static inline void NormalTrackECN(TcpSession* s, tcp::TCPHdr* tcph, int req3way)
-{
-    if (!s)
-        return;
-
-    if (tcph->is_syn_ack())
-    {
-        if (!req3way || s->ecn)
-            s->ecn = ((tcph->th_flags & (TH_ECE | TH_CWR)) == TH_ECE);
-    } else if (tcph->is_syn())
-        s->ecn = tcph->are_flags_set(TH_ECE | TH_CWR);
-}
-
-static inline void NormalCheckECN(TcpSession* s, Packet* p)
-{
-    if (!s->ecn && (p->ptrs.tcph->th_flags & (TH_ECE | TH_CWR)))
-    {
-        const NormMode mode = Normalize_GetMode(NORM_TCP_ECN_STR);
-
-        if (mode == NORM_MODE_ON)
-        {
-            ((tcp::TCPHdr*) p->ptrs.tcph)->th_flags &= ~(TH_ECE | TH_CWR);
-            p->packet_flags |= PKT_MODIFIED;
-        }
-        normStats[PC_TCP_ECN_SSN][mode]++;
-        sfBase.iPegs[PERF_COUNT_TCP_ECN_SSN][mode]++;
-    }
-}
-
-const PegInfo* Stream_GetNormPegs();
-NormPegs Stream_GetNormCounts(unsigned& c);
-
-uint32_t StreamGetWindow(Flow* flow, TcpTracker* st, TcpDataBlock* tdb);
-uint32_t StreamGetTcpTimestamp(Packet* p, uint32_t* ts, int strip);
-int ValidTimestamp(TcpTracker *talker, TcpTracker *listener, TcpDataBlock *tdb, Packet *p,
-        int *eventcode, int *got_ts);
-int ValidRst(Flow* flow, TcpTracker *st, TcpDataBlock *tdb);
-int RepeatedSyn(TcpTracker *listener, TcpTracker *talker, TcpDataBlock *tdb, TcpSession *tcpssn);
-
-#endif
diff --git a/src/stream/tcp/tcp_normalizer.cc b/src/stream/tcp/tcp_normalizer.cc
new file mode 100644 (file)
index 0000000..53c49f7
--- /dev/null
@@ -0,0 +1,407 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_normalization.cc author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Jul 31, 2015
+
+#include "tcp_normalizer.h"
+#include "tcp_events.h"
+
+THREAD_LOCAL PegCount normStats[PC_MAX][NORM_MODE_MAX];
+
+static const PegInfo pegName[] =
+{
+    { "tcp trim syn", "tcp segments trimmed on SYN" },
+    { "tcp trim rst", "RST packets with data trimmed" },
+    { "tcp trim win", "data trimed to window" },
+    { "tcp trim mss", "data trimmed to MSS" },
+    { "tcp ecn session", "ECN bits cleared" },
+    { "tcp ts nop", "timestamp options cleared" },
+    { "tcp ips data", "normalized segments" },
+    { "tcp block", "blocked segments" },
+    { nullptr, nullptr }
+};
+
+static inline int SetupOK(const TcpTracker* st)
+{
+    return ((st->s_mgr.sub_state & SUB_SETUP_OK) == SUB_SETUP_OK);
+}
+
+TcpNormalizer::TcpNormalizer( uint16_t os_policy, TcpSession* session, TcpTracker* tracker ) :
+              os_policy( os_policy ), session( session ), tracker( tracker ),
+              peer_tracker( nullptr )
+{
+    trim_syn = Normalize_GetMode( NORM_TCP_TRIM_SYN );
+    trim_rst = Normalize_GetMode( NORM_TCP_TRIM_RST );
+    trim_win = Normalize_GetMode( NORM_TCP_TRIM_WIN );
+    trim_mss = Normalize_GetMode( NORM_TCP_TRIM_MSS );
+    strip_ecn = Normalize_GetMode( NORM_TCP_ECN_STR );
+    tcp_block = Normalize_GetMode( NORM_TCP_BLOCK );
+    opt_block = Normalize_GetMode( NORM_TCP_OPT );
+
+    paws_ts_fudge = 0;
+    paws_drop_zero_ts = true;
+}
+
+const PegInfo* TcpNormalizer::get_normalization_pegs()
+{
+    return pegName;
+}
+
+NormPegs TcpNormalizer::get_normalization_counts(unsigned& c)
+{
+    c = PC_MAX;
+    return normStats;
+}
+
+void TcpNormalizer::trim_payload(TcpDataBlock* tdb, uint32_t max, NormMode mode, PegCounts peg, PerfCounts perf)
+{
+    if (mode == NORM_MODE_ON)
+    {
+         uint16_t fat = tdb->pkt->dsize - max;
+         tdb->pkt->dsize = max;
+         tdb->pkt->packet_flags |= (PKT_MODIFIED | PKT_RESIZED);
+         tdb->end_seq -= fat;
+    }
+
+    normStats[peg][mode]++;
+    sfBase.iPegs[perf][mode]++;
+}
+
+bool TcpNormalizer::strip_tcp_timestamp(TcpDataBlock* tdb, const tcp::TcpOption* opt, NormMode mode)
+{
+     normStats[PC_TCP_TS_NOP][mode]++;
+     sfBase.iPegs[PERF_COUNT_TCP_TS_NOP][mode]++;
+
+     if (mode == NORM_MODE_ON)
+     {
+         // set raw option bytes to nops
+         memset((void *) opt, (uint32_t) tcp::TcpOptCode::NOP, tcp::TCPOLEN_TIMESTAMP);
+         tdb->pkt->packet_flags |= PKT_MODIFIED;
+         return true;
+     }
+
+     return false;
+ }
+bool TcpNormalizer::packet_dropper(TcpDataBlock* tdb, NormFlags f)
+{
+    const NormMode mode = (f == NORM_TCP_BLOCK) ? tcp_block : opt_block;
+
+    normStats[PC_TCP_BLOCK][mode]++;
+    sfBase.iPegs[PERF_COUNT_TCP_BLOCK][mode]++;
+
+    if (mode == NORM_MODE_ON)
+    {
+        Active::drop_packet(tdb->pkt);
+        return true;
+    }
+
+    return false;
+}
+
+void TcpNormalizer::trim_syn_payload(TcpDataBlock* tdb, uint32_t max)
+{
+    if (tdb->pkt->dsize > max)
+        trim_payload(tdb, max, trim_syn, PC_TCP_TRIM_SYN, PERF_COUNT_TCP_TRIM_SYN);
+}
+
+void TcpNormalizer::trim_rst_payload(TcpDataBlock* tdb, uint32_t max)
+{
+    if (tdb->pkt->dsize > max)
+        trim_payload(tdb, max, trim_rst, PC_TCP_TRIM_RST, PERF_COUNT_TCP_TRIM_RST);
+}
+
+void TcpNormalizer::trim_win_payload(TcpDataBlock* tdb, uint32_t max)
+{
+    if (tdb->pkt->dsize > max)
+        trim_payload(tdb, max, trim_win, PC_TCP_TRIM_WIN, PERF_COUNT_TCP_TRIM_WIN);
+}
+
+void TcpNormalizer::trim_mss_payload(TcpDataBlock* tdb, uint32_t max)
+{
+    if (tdb->pkt->dsize > max)
+        trim_payload(tdb, max, trim_mss, PC_TCP_TRIM_MSS, PERF_COUNT_TCP_TRIM_MSS);
+}
+
+void TcpNormalizer::ecn_tracker( tcp::TCPHdr* tcph, bool req3way )
+{
+    if( tcph->is_syn_ack() )
+    {
+        if( !req3way || session->ecn )
+            session->ecn = ((tcph->th_flags & (TH_ECE | TH_CWR)) == TH_ECE);
+    }
+    else if( tcph->is_syn() )
+        session->ecn = tcph->are_flags_set(TH_ECE | TH_CWR);
+}
+
+void TcpNormalizer::ecn_stripper( Packet* p )
+{
+    if (!session->ecn && (p->ptrs.tcph->th_flags & (TH_ECE | TH_CWR)))
+    {
+        if (strip_ecn == NORM_MODE_ON)
+        {
+            ((tcp::TCPHdr*) p->ptrs.tcph)->th_flags &= ~(TH_ECE | TH_CWR);
+            p->packet_flags |= PKT_MODIFIED;
+        }
+
+        normStats[PC_TCP_ECN_SSN][strip_ecn]++;
+        sfBase.iPegs[PERF_COUNT_TCP_ECN_SSN][strip_ecn]++;
+    }
+}
+
+// don't use the window if we may have missed scaling
+// one way zero window is unitialized
+// two way zero window is actually closed (regardless of scaling)
+uint32_t TcpNormalizer::get_stream_window( TcpDataBlock* tdb )
+{
+    int32_t window;
+
+    if( tracker->l_window )
+    {
+        if( !(session->flow->session_state & STREAM_STATE_MIDSTREAM ) )
+            return tracker->l_window;
+    }
+    else if( session->flow->two_way_traffic() )
+        return tracker->l_window;
+
+    // ensure the data is in the window
+    window = tdb->end_seq - tracker->r_win_base;
+    if (window < 0)
+        window = 0;
+
+    return (uint32_t) window;
+}
+
+uint32_t TcpNormalizer::get_tcp_timestamp(TcpDataBlock* tdb, bool strip)
+{
+    DebugMessage(DEBUG_STREAM_STATE, "Getting timestamp...\n");
+
+    tcp::TcpOptIterator iter(tdb->pkt->ptrs.tcph, tdb->pkt);
+
+    // using const because non-const is not supported
+    for (const tcp::TcpOption& opt : iter)
+    {
+        if (opt.code == tcp::TcpOptCode::TIMESTAMP)
+        {
+            bool stripped = false;
+
+            if (strip)
+                stripped = strip_tcp_timestamp(tdb, &opt, opt_block);
+
+            if(!stripped)
+            {
+                tdb->ts = EXTRACT_32BITS(opt.data);
+                DebugFormat(DEBUG_STREAM_STATE, "Found timestamp %lu\n", *ts);
+
+                return TF_TSTAMP;
+            }
+        }
+    }
+    tdb->ts = 0;
+
+    DebugMessage(DEBUG_STREAM_STATE, "No timestamp...\n");
+
+    return TF_NONE;
+}
+
+bool TcpNormalizer::validate_rst_seq_geq( TcpDataBlock* tdb )
+{
+    DebugFormat(DEBUG_STREAM_STATE, "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
+            tdb->end_seq, tracker->r_win_base, tdb->seq, tracker->r_nxt_ack + get_stream_window( tdb ));
+
+    if (SEQ_GEQ(tdb->seq, tracker->r_nxt_ack))
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (>= next seq)!\n");
+        return true;
+    }
+
+    DebugMessage(DEBUG_STREAM_STATE, "rst is not valid seq (>= next seq)!\n");
+    return false;
+}
+
+bool TcpNormalizer::validate_rst_end_seq_geq( TcpDataBlock* tdb )
+{
+    DebugFormat(DEBUG_STREAM_STATE, "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
+            tdb->end_seq, tracker->r_win_base, tdb->seq, tracker->r_nxt_ack + get_stream_window( tdb ));
+
+    if (SEQ_GEQ(tdb->end_seq, tracker->r_win_base))
+     {
+         // reset must be admitted when window closed
+         if (SEQ_LEQ(tdb->seq, tracker->r_win_base + get_stream_window( tdb )))
+         {
+             DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (within window)!\n");
+             return true;
+         }
+     }
+
+     DebugMessage(DEBUG_STREAM_STATE, "rst is not valid seq (within window)!\n");
+     return false;
+}
+
+bool TcpNormalizer::validate_rst_seq_eq( TcpDataBlock* tdb )
+{
+    DebugFormat(DEBUG_STREAM_STATE, "Checking end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
+            tdb->end_seq, tracker->r_win_base, tdb->seq, tracker->r_nxt_ack + get_stream_window( tdb ));
+
+    if (SEQ_EQ(tdb->seq, tracker->r_nxt_ack))
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "rst is valid seq (next seq)!\n");
+        return true;
+    }
+
+    DebugMessage(DEBUG_STREAM_STATE, "rst is not valid seq (next seq)!\n");
+    return false;
+}
+
+// per rfc 793 a rst is valid if the seq number is in window
+// for all states but syn-sent (handled above).  however, we
+// validate here based on how various implementations actually
+// handle a rst.
+bool TcpNormalizer::validate_rst( TcpDataBlock* tdb )
+{
+    return validate_rst_seq_eq( tdb );
+}
+
+int TcpNormalizer::validate_paws_timestamp( TcpDataBlock* tdb, int* eventcode )
+{
+    if( ( (int) ( ( tdb->ts - peer_tracker->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();
+        *eventcode |= EVENT_BAD_TIMESTAMP;
+        packet_dropper(tdb, NORM_TCP_OPT);
+        return ACTION_BAD_PKT;
+    }
+    else if( ( peer_tracker->ts_last != 0 )
+            && ( ( uint32_t ) tdb->pkt->pkth->ts.tv_sec > peer_tracker->ts_last_pkt + PAWS_24DAYS ) )
+    {
+        /* this packet is from way too far into the future */
+        DebugFormat(DEBUG_STREAM_STATE, "packet PAWS timestamp way too far ahead of last packet %d %d...\n",
+                p->pkth->ts.tv_sec, peer_tracker->ts_last_pkt);
+        //inc_tcp_discards();
+        *eventcode |= EVENT_BAD_TIMESTAMP;
+        packet_dropper(tdb, NORM_TCP_OPT);
+        return ACTION_BAD_PKT;
+    }
+    else
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "packet PAWS ok...\n");
+        return ACTION_NOTHING;
+    }
+}
+
+bool TcpNormalizer::is_paws_ts_checked_required( TcpDataBlock* )
+{
+    return true;
+}
+
+int TcpNormalizer::validate_paws( TcpDataBlock* tdb, int* eventcode, int* got_ts )
+{
+    *got_ts = get_tcp_timestamp(tdb, false);
+    if (*got_ts)
+    {
+        bool check_ts = is_paws_ts_checked_required( tdb );
+
+        if (check_ts)
+            return validate_paws_timestamp( tdb, eventcode );
+        else
+            return ACTION_NOTHING;
+    }
+    else
+    {
+        // we've got a packet with no timestamp, but 3whs indicated talker was doing
+        //  timestamps.  This breaks protocol, however, some servers still ack the packet
+        //   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");
+        *eventcode |= EVENT_NO_TIMESTAMP;
+
+        /* Ignore the timestamp for this first packet, next one will checked. */
+        if (tracker->config->policy == STREAM_POLICY_SOLARIS)
+            tracker->flags &= ~TF_TSTAMP;
+
+        packet_dropper(tdb, NORM_TCP_OPT);
+        return ACTION_NOTHING;
+    }
+}
+
+int TcpNormalizer::handle_paws_no_timestamps(TcpDataBlock* tdb, int* eventcode, int* got_ts)
+{
+    // 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
+    // where we disable timestamp handling.
+    int strip = ( SetupOK( peer_tracker ) && SetupOK( tracker ) );
+    DebugMessage(DEBUG_STREAM_STATE, "listener not doing timestamps...\n");
+
+    *got_ts = get_tcp_timestamp(tdb, strip);
+    if (*got_ts)
+    {
+        if (!(peer_tracker->flags & TF_TSTAMP))
+        {
+            // SYN skipped, may have missed talker's timestamp , so set it now.
+            peer_tracker->flags |= TF_TSTAMP;
+            if (tdb->ts == 0)
+                peer_tracker->flags |= TF_TSTAMP_ZERO;
+        }
+
+        // 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 && ( tdb->ts == 0 ) ) && ( tracker->flags & TF_TSTAMP ) )
+        {
+            DebugMessage(DEBUG_STREAM_STATE, "Packet with 0 timestamp, dropping\n");
+            *eventcode |= EVENT_BAD_TIMESTAMP;
+            return ACTION_BAD_PKT;
+        }
+    }
+
+    return ACTION_NOTHING;
+}
+
+int TcpNormalizer::handle_paws(TcpDataBlock* tdb, int* eventcode, int* got_ts)
+{
+    if ( tdb->pkt->ptrs.tcph->is_rst() )
+        return ACTION_NOTHING;
+
+#if 0
+    if ( tdb->pkt->ptrs.tcph->is_ack() && Normalize_IsEnabled(NORM_TCP_OPT) )
+    {
+        // FIXIT-L validate tsecr here (check that it was previously sent)
+        // checking for the most recent ts is easy enough must check if
+        // ts are up to date in retransmitted packets
+    }
+#endif
+
+    if ((peer_tracker->flags & TF_TSTAMP) && (tracker->flags & TF_TSTAMP))
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "Checking timestamps for PAWS\n");
+        return validate_paws( tdb, eventcode, got_ts );
+    }
+    else if (tdb->pkt->ptrs.tcph->is_syn_only())
+    {
+        *got_ts = get_tcp_timestamp(tdb, 0);
+        if (*got_ts)
+            peer_tracker->flags |= TF_TSTAMP;
+
+        return ACTION_NOTHING;
+    }
+    else
+    {
+        return handle_paws_no_timestamps( tdb, eventcode, got_ts );
+    }
+}
+
diff --git a/src/stream/tcp/tcp_normalizer.h b/src/stream/tcp/tcp_normalizer.h
new file mode 100644 (file)
index 0000000..c09a5c0
--- /dev/null
@@ -0,0 +1,148 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_normalizer.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Jul 31, 2015
+
+#ifndef TCP_NORMALIZER_H
+#define TCP_NORMALIZER_H
+
+#include "main/snort_types.h"
+#include "framework/counts.h"
+#include "perf_monitor/perf.h"
+#include "protocols/tcp_options.h"
+#include "protocols/tcp.h"
+#include "normalize/normalize.h"
+#include "packet_io/active.h"
+#include "tcp_session.h"
+#include "tcp_defs.h"
+
+enum PegCounts
+{
+    PC_TCP_TRIM_SYN,
+    PC_TCP_TRIM_RST,
+    PC_TCP_TRIM_WIN,
+    PC_TCP_TRIM_MSS,
+    PC_TCP_ECN_SSN,
+    PC_TCP_TS_NOP,
+    PC_TCP_IPS_DATA,
+    PC_TCP_BLOCK,
+    PC_MAX
+};
+
+extern THREAD_LOCAL PegCount normStats[PC_MAX][NORM_MODE_MAX];
+
+class TcpNormalizer
+{
+public:
+
+    virtual ~TcpNormalizer( ) { }
+
+    virtual bool packet_dropper (TcpDataBlock*, NormFlags );
+    virtual void trim_syn_payload( TcpDataBlock*, uint32_t max = 0 );
+    virtual void trim_rst_payload( TcpDataBlock*, uint32_t max = 0 );
+    virtual void trim_win_payload( TcpDataBlock*, uint32_t max = 0 );
+    virtual void trim_mss_payload( TcpDataBlock*, uint32_t max = 0 );
+    virtual void ecn_tracker( tcp::TCPHdr*, bool req3way );
+    virtual void ecn_stripper( Packet* );
+
+    virtual uint32_t get_stream_window( TcpDataBlock* );
+    virtual uint32_t get_tcp_timestamp( TcpDataBlock *, bool strip );
+    virtual int handle_paws( TcpDataBlock*, int*, int* );
+    virtual bool validate_rst( TcpDataBlock* );
+    virtual int handle_repeated_syn( TcpDataBlock* ) = 0;
+
+    static const PegInfo* get_normalization_pegs( void );
+    static NormPegs get_normalization_counts( unsigned&  );
+
+    void set_peer_tracker( TcpTracker* peer_tracker )
+    {
+        this->peer_tracker = peer_tracker;
+    }
+
+    uint16_t get_os_policy() const
+    {
+        return os_policy;
+    }
+
+    bool is_paws_drop_zero_ts() const
+    {
+        return paws_drop_zero_ts;
+    }
+
+    int32_t get_paws_ts_fudge() const
+    {
+        return paws_ts_fudge;
+    }
+
+    NormMode get_opt_block() const
+    {
+        return opt_block;
+    }
+
+    NormMode get_strip_ecn() const
+    {
+        return strip_ecn;
+    }
+
+    NormMode get_tcp_block() const
+    {
+        return tcp_block;
+    }
+
+    NormMode get_trim_mss() const
+    {
+        return trim_mss;
+    }
+
+    NormMode get_trim_win() const
+    {
+        return trim_win;
+    }
+
+protected:
+    TcpNormalizer( uint16_t, TcpSession*, TcpTracker* );
+    virtual void trim_payload( TcpDataBlock*, uint32_t, NormMode, PegCounts, PerfCounts );
+    virtual bool strip_tcp_timestamp( TcpDataBlock*, const tcp::TcpOption*, NormMode );
+    virtual bool validate_rst_seq_geq( TcpDataBlock* );
+    virtual bool validate_rst_end_seq_geq(  TcpDataBlock* );
+    virtual bool validate_rst_seq_eq( TcpDataBlock* );
+
+    int validate_paws_timestamp( TcpDataBlock*, int* );
+    virtual bool is_paws_ts_checked_required( TcpDataBlock* );
+    int validate_paws( TcpDataBlock*, int*, int* );
+    int handle_paws_no_timestamps( TcpDataBlock*, int* , int* );
+
+    uint16_t os_policy;
+    TcpSession* session;
+    TcpTracker* tracker;
+    TcpTracker* peer_tracker;
+
+    NormMode trim_syn;
+    NormMode trim_rst;
+    NormMode trim_win;
+    NormMode trim_mss;
+    NormMode strip_ecn;
+    NormMode tcp_block;
+    NormMode opt_block;
+
+    int32_t paws_ts_fudge;
+    bool paws_drop_zero_ts;
+};
+
+#endif
diff --git a/src/stream/tcp/tcp_normalizers.cc b/src/stream/tcp/tcp_normalizers.cc
new file mode 100644 (file)
index 0000000..21b1bab
--- /dev/null
@@ -0,0 +1,321 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_normalizers.cc author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Sep 22, 2015
+
+#include "tcp_module.h"
+#include "tcp_normalizers.h"
+
+TcpNormalizer* TcpNormalizerFactory::allocate_normalizer( uint16_t os_policy,
+        TcpSession* session, TcpTracker* tracker, TcpTracker* peer )
+{
+    TcpNormalizer* normalizer;
+
+    switch (os_policy)
+    {
+    case STREAM_POLICY_FIRST:
+        normalizer = new TcpNormalizerFirst( session, tracker );
+        break;
+
+    case STREAM_POLICY_LAST:
+        normalizer = new TcpNormalizerLast( session, tracker );
+        break;
+
+    case STREAM_POLICY_LINUX:
+        normalizer = new TcpNormalizerLinux( session, tracker );
+        break;
+
+    case STREAM_POLICY_OLD_LINUX:
+        normalizer = new TcpNormalizerOldLinux( session, tracker );
+        break;
+
+    case STREAM_POLICY_BSD:
+        normalizer = new TcpNormalizerBSD( session, tracker );
+        break;
+
+    case STREAM_POLICY_MACOS:
+        normalizer = new TcpNormalizerMacOS( session, tracker );
+        break;
+
+    case STREAM_POLICY_SOLARIS:
+        normalizer = new TcpNormalizerSolaris( session, tracker );
+        break;
+
+    case STREAM_POLICY_IRIX:
+        normalizer = new TcpNormalizerIrix( session, tracker );
+        break;
+
+    case STREAM_POLICY_HPUX11:
+        normalizer = new TcpNormalizerHpux11( session, tracker );
+        break;
+
+    case STREAM_POLICY_HPUX10:
+        normalizer = new TcpNormalizerHpux10( session, tracker );
+        break;
+
+    case STREAM_POLICY_WINDOWS:
+        normalizer = new TcpNormalizerWindows( session, tracker );
+        break;
+
+    case STREAM_POLICY_WINDOWS2K3:
+        normalizer = new TcpNormalizerWindows2K3( session, tracker );
+        break;
+
+    case STREAM_POLICY_VISTA:
+        normalizer = new TcpNormalizerVista( session, tracker );
+        break;
+
+    case STREAM_POLICY_PROXY:
+        normalizer = new TcpNormalizerProxy( session, tracker );
+        break;
+
+    default:
+        normalizer = new TcpNormalizerBSD( session, tracker );
+        break;
+    }
+
+    normalizer->set_peer_tracker( peer );
+    return normalizer;
+}
+
+static inline int handle_repeated_syn_mswin( TcpTracker* talker, TcpTracker* listener,
+        TcpDataBlock* tdb, TcpSession* session )
+{
+    /* 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(tdb->seq, listener->r_nxt_ack))
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "Got syn on established windows ssn, which causes Reset, bailing\n");
+        session->flow->set_session_flags( SSNFLAG_RESET );
+        talker->s_mgr.state = TCP_STATE_CLOSED;
+        return ACTION_RST;
+    }
+    else
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "Got syn on established windows ssn, not causing Reset, bailing\n");
+        inc_tcp_discards();
+        return ACTION_NOTHING;
+    }
+}
+
+static inline int handle_repeated_syn_bsd( TcpTracker* talker, TcpDataBlock* tdb, TcpSession* session )
+{
+    /* If its not a retransmission of the actual SYN... RESET */
+     if (!SEQ_EQ(tdb->seq, talker->isn))
+     {
+         DebugMessage(DEBUG_STREAM_STATE, "Got syn on established ssn, which causes Reset, bailing\n");
+         session->flow->set_session_flags( SSNFLAG_RESET );
+         talker->s_mgr.state = TCP_STATE_CLOSED;
+         return ACTION_RST;
+     }
+     else
+     {
+         DebugMessage(DEBUG_STREAM_STATE, "Got syn on established ssn, not causing Reset, bailing\n");
+         inc_tcp_discards();
+         return ACTION_NOTHING;
+     }
+}
+
+// Linux, Win2k3 et al.  do not support timestamps if the 3whs used a 0 timestamp.
+static inline bool paws_3whs_zero_ts_not_supported(TcpTracker* talker, TcpTracker* listener )
+{
+    bool check_ts = true;
+
+    if (talker->flags & TF_TSTAMP_ZERO)
+    {
+        talker->flags &= ~TF_TSTAMP;
+        listener->flags &= ~TF_TSTAMP;
+        check_ts = false;
+    }
+
+    return check_ts;
+}
+
+// Older Linux ( <= 2.2 kernel ), Win32 (non 2K3) allow the 3whs to use a 0 timestamp.
+static inline bool paws_3whs_zero_ts_supported(TcpTracker* talker, TcpTracker* listener, TcpDataBlock* tdb)
+{
+    bool check_ts = true;
+
+    if( talker->flags & TF_TSTAMP_ZERO )
+    {
+        talker->flags &= ~TF_TSTAMP_ZERO;
+        if( SEQ_EQ( listener->r_nxt_ack, tdb->seq ) )
+        {
+            // Ignore timestamp for this first packet, save to check on next
+            talker->ts_last = tdb->ts;
+            check_ts = false;
+        }
+    }
+
+    return check_ts;
+}
+
+int TcpNormalizerFirst::handle_repeated_syn( TcpDataBlock* tdb )
+{
+    return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+}
+
+int TcpNormalizerLast::handle_repeated_syn( TcpDataBlock* tdb )
+{
+    return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+}
+
+bool TcpNormalizerLinux::validate_rst( TcpDataBlock *tdb )
+{
+    return validate_rst_end_seq_geq( tdb );
+}
+
+bool TcpNormalizerLinux::is_paws_ts_checked_required( TcpDataBlock* )
+{
+    return paws_3whs_zero_ts_not_supported( peer_tracker, tracker );
+}
+
+int TcpNormalizerLinux::handle_repeated_syn( TcpDataBlock* tdb )
+{
+    return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+}
+
+bool TcpNormalizerOldLinux::validate_rst( TcpDataBlock *tdb )
+{
+    return validate_rst_end_seq_geq( tdb );
+}
+
+bool TcpNormalizerOldLinux::is_paws_ts_checked_required( TcpDataBlock* tdb)
+{
+    return paws_3whs_zero_ts_supported( peer_tracker, tracker, tdb );
+}
+
+int TcpNormalizerOldLinux::handle_repeated_syn( TcpDataBlock* tdb )
+{
+    return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+}
+
+bool TcpNormalizerBSD::validate_rst( TcpDataBlock *tdb )
+{
+    return validate_rst_end_seq_geq( tdb );
+}
+
+int TcpNormalizerBSD::handle_repeated_syn( TcpDataBlock* tdb )
+{
+    return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+}
+
+int TcpNormalizerMacOS::handle_repeated_syn( TcpDataBlock* )
+{
+    /* MACOS ignores a 2nd SYN, regardless of the sequence number. */
+    DebugMessage(DEBUG_STREAM_STATE, "Got syn on established macos ssn, not causing Reset, bailing\n");
+    inc_tcp_discards();
+    return ACTION_NOTHING;
+}
+
+bool TcpNormalizerSolaris::validate_rst( TcpDataBlock* tdb )
+{
+    return validate_rst_end_seq_geq( tdb );
+}
+
+int TcpNormalizerSolaris::handle_repeated_syn( TcpDataBlock* tdb )
+{
+    return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+}
+
+int TcpNormalizerIrix::handle_repeated_syn( TcpDataBlock* tdb )
+{
+    return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+}
+
+bool TcpNormalizerHpux11::validate_rst( TcpDataBlock *tdb )
+{
+    return validate_rst_seq_geq( tdb );
+}
+
+bool TcpNormalizerHpux11::is_paws_ts_checked_required( TcpDataBlock* tdb )
+{
+    /* HPUX 11 ignores timestamps for out of order segments */
+    if ((tracker->flags & TF_MISSING_PKT) || !SEQ_EQ(tracker->r_nxt_ack, tdb->seq))
+        return false;
+    else
+        return true;
+}
+
+int TcpNormalizerHpux11::handle_repeated_syn( TcpDataBlock* tdb )
+{
+    return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+}
+
+int TcpNormalizerHpux10::handle_repeated_syn( TcpDataBlock* tdb )
+{
+    return handle_repeated_syn_bsd( peer_tracker, tdb, session );
+}
+
+bool TcpNormalizerWindows::is_paws_ts_checked_required( TcpDataBlock* tdb)
+{
+    return paws_3whs_zero_ts_supported( peer_tracker, tracker, tdb );
+}
+
+int TcpNormalizerWindows::handle_repeated_syn( TcpDataBlock *tdb )
+{
+    return handle_repeated_syn_mswin( peer_tracker, tracker, tdb, session );
+}
+
+
+int TcpNormalizerWindows2K3::handle_repeated_syn( TcpDataBlock *tdb )
+{
+    return handle_repeated_syn_mswin( peer_tracker, tracker, tdb, session );
+}
+
+bool TcpNormalizerWindows2K3::is_paws_ts_checked_required( TcpDataBlock* )
+{
+    return paws_3whs_zero_ts_not_supported( peer_tracker, tracker );
+}
+
+bool TcpNormalizerVista::is_paws_ts_checked_required( TcpDataBlock* tdb)
+{
+    return paws_3whs_zero_ts_supported( peer_tracker, tracker, tdb );
+}
+
+int TcpNormalizerVista::handle_repeated_syn( TcpDataBlock *tdb )
+{
+    return handle_repeated_syn_mswin( peer_tracker, tracker, tdb, session );
+}
+
+bool TcpNormalizerProxy::validate_rst( TcpDataBlock *tdb )
+{
+    // FIXIT - will session->flow ever be null? i would think not, remove this check if possible
+    if( session->flow )
+    {
+        DebugFormat(DEBUG_STREAM_STATE, "Proxy Normalizer - Not Valid\n end_seq (%X) > r_win_base (%X) && seq (%X) < r_nxt_ack(%X)\n",
+                tdb->end_seq, tracker->r_win_base, tdb->seq, tracker->r_nxt_ack + get_stream_window( tdb ));
+    }
+
+    return false;
+}
+
+int TcpNormalizerProxy::handle_paws(TcpDataBlock*, Packet*, int*, int*)
+{
+    return ACTION_NOTHING;
+}
+
+int TcpNormalizerProxy::handle_repeated_syn( TcpDataBlock* )
+{
+    return ACTION_NOTHING;
+}
+
+
+
diff --git a/src/stream/tcp/tcp_normalizers.h b/src/stream/tcp/tcp_normalizers.h
new file mode 100644 (file)
index 0000000..577e641
--- /dev/null
@@ -0,0 +1,204 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// tcp_normalizers.h author davis mcpherson <davmcphe@@cisco.com>
+// Created on: Sep 22, 2015
+
+#ifndef TCP_NORMALIZERS_H
+#define TCP_NORMALIZERS_H
+
+#include "tcp_defs.h"
+#include "tcp_normalizer.h"
+
+
+class TcpNormalizerFirst : public TcpNormalizer
+{
+public:
+    TcpNormalizerFirst( TcpSession* session, TcpTracker* tracker ) :
+        TcpNormalizer( STREAM_POLICY_FIRST, session, tracker )
+    { }
+
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerLast : public TcpNormalizer
+{
+public:
+    TcpNormalizerLast( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_LAST, session, tracker )
+    { }
+
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerLinux : public TcpNormalizer
+{
+public:
+    TcpNormalizerLinux( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_LINUX, session, tracker )
+    {
+        // Linux 2.6 accepts timestamp values that are off by one. so set fudge factor */
+        paws_ts_fudge = 1;
+    }
+
+    bool validate_rst( TcpDataBlock* );
+    bool is_paws_ts_checked_required( TcpDataBlock* );
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerOldLinux : public TcpNormalizer
+{
+public:
+    TcpNormalizerOldLinux( TcpSession* session, TcpTracker* tracker ) :
+            TcpNormalizer( STREAM_POLICY_OLD_LINUX, session, tracker )
+    {
+        paws_drop_zero_ts = false;
+    }
+
+    bool validate_rst( TcpDataBlock* );
+    bool is_paws_ts_checked_required( TcpDataBlock* );
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerBSD : public TcpNormalizer
+{
+public:
+    TcpNormalizerBSD( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_BSD, session, tracker )
+    { }
+
+    bool validate_rst( TcpDataBlock* );
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerMacOS : public TcpNormalizer
+{
+public:
+    TcpNormalizerMacOS( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_MACOS, session, tracker )
+    { }
+
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerSolaris : public TcpNormalizer
+{
+public:
+    TcpNormalizerSolaris( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_SOLARIS, session, tracker )
+    {
+        paws_drop_zero_ts = false;
+    }
+
+    bool validate_rst( TcpDataBlock* );
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerIrix : public TcpNormalizer
+{
+public:
+    TcpNormalizerIrix( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_IRIX, session, tracker )
+    { }
+
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerHpux11 : public TcpNormalizer
+{
+public:
+    TcpNormalizerHpux11( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_HPUX11, session, tracker )
+    { }
+
+    bool validate_rst( TcpDataBlock* );
+    bool is_paws_ts_checked_required( TcpDataBlock* );
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerHpux10 : public TcpNormalizer
+{
+public:
+    TcpNormalizerHpux10( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_HPUX10, session, tracker )
+    { }
+
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerWindows : public TcpNormalizer
+{
+public:
+    TcpNormalizerWindows( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_WINDOWS, session, tracker )
+    {
+        paws_drop_zero_ts = false;
+    }
+
+    bool is_paws_ts_checked_required( TcpDataBlock* );
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerWindows2K3 : public TcpNormalizer
+{
+public:
+    TcpNormalizerWindows2K3( TcpSession* session, TcpTracker* tracker ) :
+            TcpNormalizer( STREAM_POLICY_WINDOWS2K3, session, tracker )
+    {
+        paws_drop_zero_ts = false;
+    }
+
+    bool is_paws_ts_checked_required(  TcpDataBlock* );
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerVista : public TcpNormalizer
+{
+public:
+    TcpNormalizerVista( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_VISTA, session, tracker )
+    {
+        paws_drop_zero_ts = false;
+    }
+
+    bool is_paws_ts_checked_required( TcpDataBlock*);
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerProxy : public TcpNormalizer
+{
+public:
+    TcpNormalizerProxy( TcpSession* session, TcpTracker* tracker  ) :
+            TcpNormalizer( STREAM_POLICY_PROXY, session, tracker )
+    { }
+
+    bool validate_rst(TcpDataBlock* );
+    int handle_paws( TcpDataBlock*, Packet*, int*, int* );
+    int handle_repeated_syn( TcpDataBlock* );
+};
+
+class TcpNormalizerFactory
+{
+public:
+    static TcpNormalizer* allocate_normalizer( uint16_t, TcpSession*, TcpTracker*, TcpTracker* );
+};
+
+
+
+
+#endif /* TCP_NORMALIZERS_H_ */
index 7b2a1cb7e931f0b54c7cd6db56c6d6a4c7fc0d11..7640b72f6c8e8bc2dd3d709e22ee9523911d9d31 100644 (file)
@@ -1,5 +1,5 @@
 //--------------------------------------------------------------------------
-// Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License Version 2 as published
@@ -31,7 +31,7 @@
 #include "tcp_module.h"
 #include "tcp_session.h"
 #include "tcp_events.h"
-#include "tcp_normalization.h"
+#include "tcp_normalizer.h"
 #include "tcp_reassembly.h"
 #include "tcp_defs.h"
 
@@ -365,7 +365,7 @@ static inline int SegmentFastTrack(TcpSegment *tail, TcpDataBlock *tdb)
     return 0;
 }
 
-int AddStreamNode(TcpTracker *st, Packet *p, TcpDataBlock* tdb, int16_t len, uint32_t slide,
+int AddStreamNode(TcpTracker *st, TcpDataBlock* tdb, int16_t len, uint32_t slide,
         uint32_t trunc, uint32_t seq, TcpSegment *left)
 {
     TcpSegment *ss = NULL;
@@ -379,7 +379,7 @@ int AddStreamNode(TcpTracker *st, Packet *p, TcpDataBlock* tdb, int16_t len, uin
          */
         DebugFormat(DEBUG_STREAM_STATE, "zero size TCP data after left & right trimming " "(len: %d slide: %d trunc: %d)\n", len, slide, trunc);
         inc_tcp_discards();
-        NormalTrimPayloadIfWin(p, 0, tdb);
+        st->normalizer->trim_win_payload( tdb );
 
 #ifdef DEBUG_STREAM_EX
         {
@@ -403,7 +403,7 @@ int AddStreamNode(TcpTracker *st, Packet *p, TcpDataBlock* tdb, int16_t len, uin
     }
 
     // FIXIT-L don't allocate overlapped part
-    ss = TcpSegment::init(p, p->pkth->ts, p->data, p->dsize);
+    ss = TcpSegment::init(tdb->pkt, tdb->pkt->pkth->ts, tdb->pkt->data, tdb->pkt->dsize);
 
     if (!ss)
         return STREAM_INSERT_FAILED;
@@ -414,9 +414,9 @@ int AddStreamNode(TcpTracker *st, Packet *p, TcpDataBlock* tdb, int16_t len, uin
     ss->ts = tdb->ts;
 
     /* handle the urg ptr */
-    if (p->ptrs.tcph->th_flags & TH_URG)
+    if (tdb->pkt->ptrs.tcph->th_flags & TH_URG)
     {
-        if (p->ptrs.tcph->urp() < p->dsize)
+        if (tdb->pkt->ptrs.tcph->urp() < tdb->pkt->dsize)
         {
             switch (st->os_policy)
             {
@@ -424,7 +424,7 @@ int AddStreamNode(TcpTracker *st, Packet *p, TcpDataBlock* tdb, int16_t len, uin
                 case STREAM_POLICY_OLD_LINUX:
                     /* Linux, Old linux discard data from urgent pointer
                        If urg pointer is 0, it's treated as a 1 */
-                    ss->urg_offset = p->ptrs.tcph->urp();
+                    ss->urg_offset = tdb->pkt->ptrs.tcph->urp();
                     if (ss->urg_offset == 0)
                     {
                         ss->urg_offset = 1;
@@ -444,8 +444,8 @@ int AddStreamNode(TcpTracker *st, Packet *p, TcpDataBlock* tdb, int16_t len, uin
                 case STREAM_POLICY_IRIX:
                     /* Others discard data from urgent pointer
                        If urg pointer is beyond this packet, it's treated as a 0 */
-                    ss->urg_offset = p->ptrs.tcph->urp();
-                    if (ss->urg_offset > p->dsize)
+                    ss->urg_offset = tdb->pkt->ptrs.tcph->urp();
+                    if (ss->urg_offset > tdb->pkt->dsize)
                     {
                         ss->urg_offset = 0;
                     }
@@ -458,7 +458,7 @@ int AddStreamNode(TcpTracker *st, Packet *p, TcpDataBlock* tdb, int16_t len, uin
     st->seg_bytes_logical += ss->size;
     st->total_bytes_queued += ss->size;
 
-    p->packet_flags |= PKT_STREAM_INSERT;
+    tdb->pkt->packet_flags |= PKT_STREAM_INSERT;
 
     DebugFormat(DEBUG_STREAM_STATE, "added %d bytes on segment list @ seq: 0x%X, total %lu, %d segments queued\n",
             ss->size, ss->seq, st->seg_bytes_logical, SegsToFlush(st, 0));
@@ -1460,14 +1460,14 @@ void purge_all(TcpTracker *st)
     st->seg_bytes_total = st->seg_bytes_logical = 0;
 }
 
-int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn)
+int StreamQueue(TcpTracker *st, TcpDataBlock *tdb, TcpSession *tcpssn)
 {
     TcpSegment *left = NULL;
     TcpSegment *right = NULL;
     TcpSegment *dump_me = NULL;
     uint32_t seq = tdb->seq;
     uint32_t seq_end = tdb->end_seq;
-    uint16_t len = p->dsize;
+    uint16_t len = tdb->pkt->dsize;
     int trunc = 0;
     int overlap = 0;
     int slide = 0;
@@ -1478,8 +1478,8 @@ int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn
     int32_t dist_tail;
     uint16_t reassembly_policy;
     // To check for retransmitted data
-    const uint8_t* rdata = p->data;
-    uint16_t rsize = p->dsize;
+    const uint8_t* rdata = tdb->pkt->data;
+    uint16_t rsize = tdb->pkt->dsize;
     uint32_t rseq = tdb->seq;
     PROFILE_VARS;
     DEBUG_WRAP(
@@ -1516,8 +1516,7 @@ int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn
                 st->seglist_tail->seq, st->seglist_tail->size);
 
         // BLOCK add to existing block and/or allocate new block
-        ret = AddStreamNode(st, p, tdb, len, slide /* 0 */, trunc /* 0 */, seq,
-                left /* tail */);
+        ret = AddStreamNode(st, tdb, len, slide /* 0 */, trunc /* 0 */, seq, left /* tail */);
 
         MODULE_PROFILE_END(s5TcpInsertPerfStats);
         return ret;
@@ -1641,13 +1640,13 @@ int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn
                 case REASSEMBLY_POLICY_OLD_LINUX:
                 case REASSEMBLY_POLICY_MACOS:
                     DebugMessage(DEBUG_STREAM_STATE, "left overlap, honoring old data\n");
-                    if (SEQ_LT(left->seq, tdb->seq) && SEQ_GT(left->seq + left->size, tdb->seq + p->dsize))
+                    if (SEQ_LT(left->seq, tdb->seq) && SEQ_GT(left->seq + left->size, tdb->seq + tdb->pkt->dsize))
                     {
                         if (ips_data == NORM_MODE_ON)
                         {
                             unsigned offset = tdb->seq - left->seq;
-                            memcpy((uint8_t*) p->data, left->payload + offset, p->dsize);
-                            p->packet_flags |= PKT_MODIFIED;
+                            memcpy((uint8_t*) tdb->pkt->data, left->payload + offset, tdb->pkt->dsize);
+                            tdb->pkt->packet_flags |= PKT_MODIFIED;
                         }
                         normStats[PC_TCP_IPS_DATA][ips_data]++;
                         sfBase.iPegs[PERF_COUNT_TCP_IPS_DATA][ips_data]++;
@@ -1658,8 +1657,8 @@ int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn
                         {
                             unsigned offset = tdb->seq - left->seq;
                             unsigned length = left->seq + left->size - tdb->seq;
-                            memcpy((uint8_t*) p->data, left->payload + offset, length);
-                            p->packet_flags |= PKT_MODIFIED;
+                            memcpy((uint8_t*) tdb->pkt->data, left->payload + offset, length);
+                            tdb->pkt->packet_flags |= PKT_MODIFIED;
                         }
                         normStats[PC_TCP_IPS_DATA][ips_data]++;
                         sfBase.iPegs[PERF_COUNT_TCP_IPS_DATA][ips_data]++;
@@ -1722,7 +1721,7 @@ int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn
                          * seq by + (seq + len) and
                          * size by - (seq + len - left->seq).
                          */
-                        ret = DupStreamNode(p, st, left, &right);
+                        ret = DupStreamNode(tdb->pkt, st, left, &right);
                         if (ret != STREAM_INSERT_OK)
                         {
                             /* No warning, its done in StreamSeglistAddNode */
@@ -1781,14 +1780,14 @@ int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn
         /* Treat sequence number overlap as a retransmission
          * Only check right side since left side happens rarely
          */
-        RetransmitHandle(p, tcpssn);
+        RetransmitHandle(tdb->pkt, tcpssn);
 
         if (overlap < right->size)
         {
             if (right->is_retransmit(rdata, rsize, rseq))
             {
                 // All data was retransmitted
-                RetransmitProcess(p, tcpssn);
+                RetransmitProcess(tdb->pkt, tcpssn);
                 addthis = 0;
                 break;
             }
@@ -1836,9 +1835,9 @@ int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn
                     if (ips_data == NORM_MODE_ON)
                     {
                         unsigned offset = right->seq - tdb->seq;
-                        unsigned length = tdb->seq + p->dsize - right->seq;
-                        memcpy((uint8_t*) p->data + offset, right->payload, length);
-                        p->packet_flags |= PKT_MODIFIED;
+                        unsigned length = tdb->seq + tdb->pkt->dsize - right->seq;
+                        memcpy((uint8_t*) tdb->pkt->data + offset, right->payload, length);
+                        tdb->pkt->packet_flags |= PKT_MODIFIED;
                     }
                     normStats[PC_TCP_IPS_DATA][ips_data]++;
                     sfBase.iPegs[PERF_COUNT_TCP_IPS_DATA][ips_data]++;
@@ -1867,7 +1866,7 @@ int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn
                 if (rsize == 0)
                 {
                     // All data was retransmitted
-                    RetransmitProcess(p, tcpssn);
+                    RetransmitProcess(tdb->pkt, tcpssn);
                     addthis = 0;
                 }
                 continue;
@@ -1927,8 +1926,8 @@ int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn
                     if (ips_data == NORM_MODE_ON)
                     {
                         unsigned offset = right->seq - tdb->seq;
-                        memcpy((uint8_t*) p->data + offset, right->payload, right->size);
-                        p->packet_flags |= PKT_MODIFIED;
+                        memcpy((uint8_t*) tdb->pkt->data + offset, right->payload, right->size);
+                        tdb->pkt->packet_flags |= PKT_MODIFIED;
                     }
                     normStats[PC_TCP_IPS_DATA][ips_data]++;
                     sfBase.iPegs[PERF_COUNT_TCP_IPS_DATA][ips_data]++;
@@ -1966,7 +1965,7 @@ int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn
                     /* insert this one, and see if we need to chunk it up
                        Adjust slide so that is correct relative to orig seq */
                     slide = seq - tdb->seq;
-                    ret = AddStreamNode(st, p, tdb, len, slide, trunc, seq, left);
+                    ret = AddStreamNode(st, tdb, len, slide, trunc, seq, left);
                     if (ret != STREAM_INSERT_OK)
                     {
                         /* no warning, already done above */
@@ -2025,7 +2024,7 @@ right_overlap_last:
     {
         /* Adjust slide so that is correct relative to orig seq */
         slide = seq - tdb->seq;
-        ret = AddStreamNode(st, p, tdb, len, slide, trunc, seq, left);
+        ret = AddStreamNode(st, tdb, len, slide, trunc, seq, left);
     }
     else
     {
index 464f531413a8a6a30a10125908137aea8d5cbf76..06974e8002f893af0dc8cec90a6b90d4389d8518 100644 (file)
@@ -1,5 +1,5 @@
 //--------------------------------------------------------------------------
-// Copyright (C) 2014-2015 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
 //
 // This program is free software; you can redistribute it and/or modify it
 // under the terms of the GNU General Public License Version 2 as published
@@ -37,9 +37,9 @@ struct TcpTracker;
 
 struct TcpSegment
 {
-    static TcpSegment* init(struct Packet*, const struct timeval&, const uint8_t*, unsigned);
-    static void term(TcpSegment*);
-    bool is_retransmit(const uint8_t*, uint16_t size, uint32_t);
+    static TcpSegment* init( struct Packet*, const struct timeval&, const uint8_t*, unsigned );
+    static void term( TcpSegment* );
+    bool is_retransmit( const uint8_t*, uint16_t size, uint32_t );
 
     uint8_t* payload;
 
@@ -77,8 +77,8 @@ void purge_all(TcpTracker *st);
 int flush_stream(TcpSession *tcpssn, TcpTracker *st, Packet *p, uint32_t dir);
 int purge_flushed_ackd(TcpSession *tcpssn, TcpTracker *st);
 void FlushQueuedSegs(Flow* flow, TcpSession* tcpssn, bool clear, Packet* p = nullptr);
-int StreamQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb, TcpSession *tcpssn);
-int AddStreamNode(TcpTracker *st, Packet *p, TcpDataBlock* tdb, int16_t len, uint32_t slide,
+int StreamQueue(TcpTracker *st, TcpDataBlock *tdb, TcpSession *tcpssn);
+int AddStreamNode(TcpTracker *st, TcpDataBlock* tdb, int16_t len, uint32_t slide,
         uint32_t trunc, uint32_t seq, TcpSegment *left);
 uint32_t SegsToFlush(const TcpTracker* st, unsigned max);
 int CheckFlushPolicyOnData(TcpSession *, TcpTracker *, TcpTracker *, Packet *);
index eaf22cd1d4ef1710f5910ef838e71f094b6a27b1..341092888dd12182f45c67f591b08c514d334746 100644 (file)
@@ -58,7 +58,6 @@
 // in specific files ... these functional groups will be further refactored as the stream tcp
 // rewrite continues...
 #include "tcp_events.h"
-#include "tcp_normalization.h"
 #include "tcp_reassembly.h"
 #include "tcp_debug_trace.h"
 
@@ -67,6 +66,7 @@
 #include "tcp_listen_state.h"
 #include "tcp_syn_sent_state.h"
 #include "tcp_syn_recv_state.h"
+#include "tcp_normalizers.h"
 // TBD-EDM
 
 #include "main/snort_types.h"
@@ -114,7 +114,7 @@ using namespace tcp;
 
 /*  P R O T O T Y P E S  ********************************************/
 
-static int ProcessTcp(Flow*, Packet*, TcpDataBlock*, StreamTcpConfig*);
+static int ProcessTcp(Flow*, TcpDataBlock*, StreamTcpConfig*);
 
 /*  G L O B A L S  **************************************************/
 
@@ -166,28 +166,29 @@ void StreamUpdatePerfBaseState(SFBASE *sf_base, Flow *flow, char newState)
     if (!flow)
         return;
 
+    uint32_t session_flags = flow->get_session_flags();
     switch (newState)
     {
         case TCP_STATE_SYN_SENT:
-            if (!(flow->ssn_state.session_flags & SSNFLAG_COUNTED_INITIALIZE))
+            if (!(session_flags & SSNFLAG_COUNTED_INITIALIZE))
             {
                 sf_base->iSessionsInitializing++;
-                flow->ssn_state.session_flags |= SSNFLAG_COUNTED_INITIALIZE;
+                session_flags |= SSNFLAG_COUNTED_INITIALIZE;
             }
             break;
 
         case TCP_STATE_ESTABLISHED:
-            if (!(flow->ssn_state.session_flags & SSNFLAG_COUNTED_ESTABLISH))
+            if (!(session_flags & SSNFLAG_COUNTED_ESTABLISH))
             {
                 sf_base->iSessionsEstablished++;
 
                 if (perfmon_config && (perfmon_config->perf_flags & SFPERF_FLOWIP))
                     UpdateFlowIPState(&sfFlow, &flow->client_ip, &flow->server_ip, SFS_STATE_TCP_ESTABLISHED);
 
-                flow->ssn_state.session_flags |= SSNFLAG_COUNTED_ESTABLISH;
+                session_flags |= SSNFLAG_COUNTED_ESTABLISH;
 
-                if ((flow->ssn_state.session_flags & SSNFLAG_COUNTED_INITIALIZE)
-                        && !(flow->ssn_state.session_flags & SSNFLAG_COUNTED_CLOSING))
+                if ((session_flags & SSNFLAG_COUNTED_INITIALIZE)
+                        && !(session_flags & SSNFLAG_COUNTED_CLOSING))
                 {
                     assert(sf_base->iSessionsInitializing);
                     sf_base->iSessionsInitializing--;
@@ -196,12 +197,12 @@ void StreamUpdatePerfBaseState(SFBASE *sf_base, Flow *flow, char newState)
             break;
 
         case TCP_STATE_CLOSING:
-            if (!(flow->ssn_state.session_flags & SSNFLAG_COUNTED_CLOSING))
+            if (!(session_flags & SSNFLAG_COUNTED_CLOSING))
             {
                 sf_base->iSessionsClosing++;
-                flow->ssn_state.session_flags |= SSNFLAG_COUNTED_CLOSING;
+                session_flags |= SSNFLAG_COUNTED_CLOSING;
 
-                if (flow->ssn_state.session_flags & SSNFLAG_COUNTED_ESTABLISH)
+                if (session_flags & SSNFLAG_COUNTED_ESTABLISH)
                 {
                     assert(sf_base->iSessionsEstablished);
                     sf_base->iSessionsEstablished--;
@@ -209,7 +210,7 @@ void StreamUpdatePerfBaseState(SFBASE *sf_base, Flow *flow, char newState)
                     if (perfmon_config  && (perfmon_config->perf_flags & SFPERF_FLOWIP))
                         UpdateFlowIPState(&sfFlow, &flow->client_ip, &flow->server_ip, SFS_STATE_TCP_CLOSED);
                 }
-                else if (flow->ssn_state.session_flags & SSNFLAG_COUNTED_INITIALIZE)
+                else if (session_flags & SSNFLAG_COUNTED_INITIALIZE)
                 {
                     assert(sf_base->iSessionsInitializing);
                     sf_base->iSessionsInitializing--;
@@ -218,12 +219,12 @@ void StreamUpdatePerfBaseState(SFBASE *sf_base, Flow *flow, char newState)
             break;
 
         case TCP_STATE_CLOSED:
-            if (flow->ssn_state.session_flags & SSNFLAG_COUNTED_CLOSING)
+            if ( session_flags & SSNFLAG_COUNTED_CLOSING )
             {
                 assert(sf_base->iSessionsClosing);
                 sf_base->iSessionsClosing--;
             }
-            else if (flow->ssn_state.session_flags & SSNFLAG_COUNTED_ESTABLISH)
+            else if (session_flags & SSNFLAG_COUNTED_ESTABLISH)
             {
                 assert(sf_base->iSessionsEstablished);
                 sf_base->iSessionsEstablished--;
@@ -231,7 +232,7 @@ void StreamUpdatePerfBaseState(SFBASE *sf_base, Flow *flow, char newState)
                 if (perfmon_config && (perfmon_config->perf_flags & SFPERF_FLOWIP))
                     UpdateFlowIPState(&sfFlow, &flow->client_ip, &flow->server_ip, SFS_STATE_TCP_CLOSED);
             }
-            else if (flow->ssn_state.session_flags & SSNFLAG_COUNTED_INITIALIZE)
+            else if (session_flags & SSNFLAG_COUNTED_INITIALIZE)
             {
                 assert(sf_base->iSessionsInitializing);
                 sf_base->iSessionsInitializing--;
@@ -242,6 +243,7 @@ void StreamUpdatePerfBaseState(SFBASE *sf_base, Flow *flow, char newState)
             break;
     }
 
+    flow->update_session_flags( session_flags );
     sf_base->stream_mem_in_use = tcp_memcap->used();
 }
 
@@ -431,7 +433,7 @@ static void PrintTcpSession(TcpSession* ts)
     LogMessage("    server port:        %d\n", ts->flow->server_port);
     LogMessage("    client port:        %d\n", ts->flow->client_port);
 
-    LogMessage("    flags:              0x%X\n", ts->flow->ssn_state.session_flags);
+    LogMessage("    flags:              0x%X\n", ts->flow->get_session_flags());
 
     LogMessage("Client Tracker:\n");
     PrintTcpTracker(&ts->client);
@@ -515,7 +517,7 @@ static inline int ValidRstSynSent(TcpTracker *st, TcpDataBlock *tdb)
 static inline int ValidSeq(
         const Packet* p, Flow* flow, TcpTracker *st, TcpDataBlock *tdb)
 {
-    uint32_t win = StreamGetWindow(flow, st, tdb);
+    uint32_t win = st->normalizer->get_stream_window(flow, st, tdb);
 
     if ( !p->dsize )
     {
@@ -538,27 +540,27 @@ static inline int ValidSeq(
 }
 
 #else
-static inline int ValidSeq(const Packet* p, Flow* flow, TcpTracker *st, TcpDataBlock *tdb)
+static inline int ValidSeq( Flow* flow, TcpTracker *st, TcpDataBlock *tdb)
 {
     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",
-            tdb->end_seq, st->r_win_base, tdb->seq, st->r_nxt_ack+StreamGetWindow(flow, st, tdb));
+            tdb->end_seq, st->r_win_base, tdb->seq, st->r_nxt_ack + st->normalizer->get_stream_window(flow, st, tdb));
 
     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 (p->dsize)
+    if (tdb->pkt->dsize)
         right_ok = SEQ_GT(tdb->end_seq, left_seq);
     else
         right_ok = SEQ_GEQ(tdb->end_seq, left_seq);
 
     if (right_ok)
     {
-        uint32_t win = StreamGetWindow(flow, st, tdb);
+        uint32_t win = st->normalizer->get_stream_window( tdb );
 
         if (SEQ_LEQ(tdb->seq, st->r_win_base + win))
         {
@@ -578,8 +580,7 @@ static inline int ValidSeq(const Packet* p, Flow* flow, TcpTracker *st, TcpDataB
 
 #endif
 
-static inline void UpdateSsn(Packet*, TcpTracker *rcv, TcpTracker *snd,
-        TcpDataBlock *tdb)
+static inline void UpdateSsn( TcpTracker *rcv, TcpTracker *snd, TcpDataBlock *tdb)
 {
 #if 0
     if (
@@ -609,7 +610,7 @@ static inline void UpdateSsn(Packet*, TcpTracker *rcv, TcpTracker *snd,
             {
                 // normalize here
                 tdb->ack = seq;
-                ((TCPHdr*)p->ptrs.tcph)->th_ack = htonl(seq);
+                tcph->th_ack = htonl(seq);
                 p->packet_flags |= PKT_MODIFIED;
                 break;
             }
@@ -645,16 +646,17 @@ static inline void UpdateSsn(Packet*, TcpTracker *rcv, TcpTracker *snd,
 
 static inline void SetupTcpDataBlock(TcpDataBlock* tdb, Packet* p)
 {
+    tdb->pkt = p;
     tdb->seq = ntohl(p->ptrs.tcph->th_seq);
     tdb->ack = ntohl(p->ptrs.tcph->th_ack);
     tdb->win = ntohs(p->ptrs.tcph->th_win);
     tdb->end_seq = tdb->seq + (uint32_t) p->dsize;
     tdb->ts = 0;
 
-    if (p->ptrs.tcph->th_flags & TH_SYN)
+    if( p->ptrs.tcph->is_syn() )
     {
         tdb->end_seq++;
-        if (!(p->ptrs.tcph->th_flags & TH_ACK))
+        if( !p->ptrs.tcph->is_ack() )
             EventInternal(INTERNAL_EVENT_SYN_RECEIVED);
     }
     // don't bump end_seq for fin here
@@ -666,8 +668,7 @@ static inline void SetupTcpDataBlock(TcpDataBlock* tdb, Packet* p)
 }
 
 
-static void TcpSessionClear(Flow* flow, TcpSession* tcpssn,
-        int freeApplicationData)
+static void TcpSessionClear(Flow* flow, TcpSession* tcpssn, int freeApplicationData)
 {
     DebugFormat(DEBUG_STREAM_STATE, "In TcpSessionClear, %lu bytes in use\n", tcp_memcap->used());
     DebugFormat(DEBUG_STREAM_STATE, "client has %d segs queued\n", tcpssn->client.seg_count);
@@ -684,16 +685,12 @@ static void TcpSessionClear(Flow* flow, TcpSession* tcpssn,
     StreamUpdatePerfBaseState(&sfBase, tcpssn->flow, TCP_STATE_CLOSED);
     RemoveStreamSession(&sfBase);
 
-    if (flow->ssn_state.session_flags & SSNFLAG_PRUNED)
-    {
+    if (flow->get_session_flags() & SSNFLAG_PRUNED)
         CloseStreamSession(&sfBase, SESSION_CLOSED_PRUNED);
-    } else if (flow->ssn_state.session_flags & SSNFLAG_TIMEDOUT)
-    {
+    else if (flow->get_session_flags() & SSNFLAG_TIMEDOUT)
         CloseStreamSession(&sfBase, SESSION_CLOSED_TIMEDOUT);
-    } else
-    {
+    else
         CloseStreamSession(&sfBase, SESSION_CLOSED_NORMALLY);
-    }
 
     tcpssn->set_splitter(true, nullptr);
     tcpssn->set_splitter(false, nullptr);
@@ -801,30 +798,32 @@ static inline int IsWellFormed(Packet *p, TcpTracker *ts)
 
 #endif
 
-static void FinishServerInit( Packet* p, TcpDataBlock* tdb, TcpSession* ssn )
+static void FinishServerInit( TcpDataBlock* tdb, TcpSession* ssn )
 {
-    TcpTracker *server;
-    TcpTracker *client;
+    TcpTracker* server;
+    TcpTracker* client;
+    const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
 
-    if ( !ssn )
+    // FIXIT - can tcp session be null at this point?
+    if( !ssn )
         return;
 
     server = &ssn->server;
     client = &ssn->client;
 
-    server->l_window = tdb->win; /* set initial server window */
+    server->l_window = tdb->win;
     server->l_unackd = tdb->seq + 1;
     server->l_nxt_seq = server->l_unackd;
     server->isn = tdb->seq;
 
     client->r_nxt_ack = tdb->end_seq;
 
-    if ( p->ptrs.tcph->th_flags & TH_FIN )
+    if( tcph->is_fin() )
         server->l_nxt_seq--;
 
     DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", client->seglist_base_seq);
 
-    if ( !( ssn->flow->session_state & STREAM_STATE_MIDSTREAM ) )
+    if( !( ssn->flow->session_state & STREAM_STATE_MIDSTREAM ) )
     {
         server->s_mgr.state = TCP_STATE_SYN_RCVD;
         client->seglist_base_seq = server->l_unackd;
@@ -836,14 +835,15 @@ static void FinishServerInit( Packet* p, TcpDataBlock* tdb, TcpSession* ssn )
         client->r_win_base = tdb->seq;
     }
 
-    server->flags |= StreamGetTcpTimestamp(p, &server->ts_last, 0);
+    server->flags |= server->normalizer->get_tcp_timestamp(tdb, false);
+    server->ts_last = tdb->ts;
     if (server->ts_last == 0)
         server->flags |= TF_TSTAMP_ZERO;
     else
-        server->ts_last_pkt = p->pkth->ts.tv_sec;
+        server->ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
 
-    server->flags |= StreamGetMss(p, &server->mss);
-    server->flags |= StreamGetWscale(p, &server->wscale);
+    server->flags |= StreamGetMss(tdb->pkt, &server->mss);
+    server->flags |= StreamGetWscale(tdb->pkt, &server->wscale);
 
 #ifdef DEBUG_STREAM_EX
     PrintTcpSession(ssn);
@@ -855,8 +855,10 @@ static inline void EndOfFileHandle(Packet* p, TcpSession* tcpssn)
     tcpssn->flow->call_handlers(p, true);
 }
 
-static void NewQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb)
+static void NewQueue(TcpTracker *st, TcpDataBlock *tdb)
 {
+    const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+
     PROFILE_VARS; MODULE_PROFILE_START(s5TcpInsertPerfStats);
 
     DebugMessage(DEBUG_STREAM_STATE, "In NewQueue\n");
@@ -864,7 +866,7 @@ static void NewQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb)
     uint32_t overlap = 0;
     uint32_t seq = tdb->seq;
 
-    if (p->ptrs.tcph->th_flags & TH_SYN)
+    if( tcph->is_syn() )
         seq++;
 
     /* new packet seq is below the last ack... */
@@ -873,7 +875,7 @@ static void NewQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb)
         DebugMessage(DEBUG_STREAM_STATE, "segment overlaps ack'd data...\n");
         overlap = st->r_win_base - tdb->seq;
 
-        if (overlap >= p->dsize)
+        if (overlap >= tdb->pkt->dsize)
         {
             DebugMessage(DEBUG_STREAM_STATE, "full overlap on ack'd data, dropping segment\n");
             MODULE_PROFILE_END(s5TcpInsertPerfStats);
@@ -882,7 +884,7 @@ static void NewQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb)
     }
 
     // BLOCK add new block to seglist containing data
-    AddStreamNode(st, p, tdb, p->dsize, overlap, 0, tdb->seq + overlap, NULL);
+    AddStreamNode(st, tdb, tdb->pkt->dsize, overlap, 0, tdb->seq + overlap, NULL);
 
     DebugFormat(DEBUG_STREAM_STATE, "Attached new queue to seglist, %d bytes queued, base_seq 0x%X\n",
             p->dsize-overlap, st->seglist_base_seq);
@@ -891,12 +893,12 @@ static void NewQueue(TcpTracker *st, Packet *p, TcpDataBlock *tdb)
 }
 
 
-static void ProcessTcpStream(TcpTracker *rcv, TcpSession *tcpssn, Packet *p,
-        TcpDataBlock *tdb, StreamTcpConfig* config)
+static void ProcessTcpStream(TcpTracker *rcv, TcpSession *tcpssn, TcpDataBlock *tdb,
+        StreamTcpConfig* config)
 {
     DebugFormat(DEBUG_STREAM_STATE, "In ProcessTcpStream(), %d bytes to queue\n", p->dsize);
 
-    if (p->packet_flags & PKT_IGNORE)
+    if (tdb->pkt->packet_flags & PKT_IGNORE)
         return;
 
 #ifdef HAVE_DAQ_ADDRESS_SPACE_ID
@@ -917,7 +919,7 @@ static void ProcessTcpStream(TcpTracker *rcv, TcpSession *tcpssn, Packet *p,
 
     if (config->max_consec_small_segs)
     {
-        if (p->dsize < config->max_consec_small_seg_size)
+        if (tdb->pkt->dsize < config->max_consec_small_seg_size)
         {
             rcv->small_seg_count++;
 
@@ -950,27 +952,27 @@ static void ProcessTcpStream(TcpTracker *rcv, TcpSession *tcpssn, Packet *p,
 
     if (!rcv->seg_count)
     {
-        NewQueue(rcv, p, tdb);
+        NewQueue(rcv, tdb);
         return;
     }
     if (SEQ_GT(rcv->r_win_base, tdb->seq))
     {
         uint32_t offset = rcv->r_win_base - tdb->seq;
 
-        if (offset < p->dsize)
+        if (offset < tdb->pkt->dsize)
         {
             tdb->seq += offset;
-            p->data += offset;
-            p->dsize -= (uint16_t) offset;
+            tdb->pkt->data += offset;
+            tdb->pkt->dsize -= (uint16_t) offset;
 
-            StreamQueue(rcv, p, tdb, tcpssn);
+            StreamQueue(rcv, tdb, tcpssn);
 
-            p->dsize += (uint16_t) offset;
-            p->data -= offset;
+            tdb->pkt->dsize += (uint16_t) offset;
+            tdb->pkt->data -= offset;
             tdb->seq -= offset;
         }
     } else
-        StreamQueue(rcv, p, tdb, tcpssn);
+        StreamQueue(rcv, tdb, tcpssn);
 
     if ((rcv->config->overlap_limit)
             && (rcv->overlap_count > rcv->config->overlap_limit))
@@ -981,14 +983,16 @@ static void ProcessTcpStream(TcpTracker *rcv, TcpSession *tcpssn, Packet *p,
     }
 }
 
-static int ProcessTcpData(Packet *p, TcpTracker *listener, TcpSession *tcpssn,
+static int ProcessTcpData(TcpTracker *listener, TcpSession *tcpssn,
         TcpDataBlock *tdb, StreamTcpConfig *config)
 {
+    const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+
     PROFILE_VARS; MODULE_PROFILE_START(s5TcpDataPerfStats);
 
     uint32_t seq = tdb->seq;
 
-    if (p->ptrs.tcph->th_flags & TH_SYN)
+    if( tcph->is_syn() )
     {
         if (listener->os_policy == STREAM_POLICY_MACOS)
             seq++;
@@ -996,7 +1000,7 @@ static int ProcessTcpData(Packet *p, TcpTracker *listener, TcpSession *tcpssn,
         else
         {
             DebugMessage(DEBUG_STREAM_STATE, "Bailing, data on SYN, not MAC Policy!\n");
-            NormalTrimPayloadIfSyn(p, 0, tdb);
+            listener->normalizer->trim_syn_payload( tdb );
             MODULE_PROFILE_END(s5TcpDataPerfStats);
             return STREAM_UNALIGNED;
         }
@@ -1007,10 +1011,10 @@ static int ProcessTcpData(Packet *p, TcpTracker *listener, TcpSession *tcpssn,
     {
         /* check if we're in the window */
         if (listener->config->policy != STREAM_POLICY_PROXY
-                and StreamGetWindow(tcpssn->flow, listener, tdb) == 0)
+                and listener->normalizer->get_stream_window( tdb ) == 0)
         {
             DebugMessage(DEBUG_STREAM_STATE, "Bailing, we're out of the window!\n");
-            NormalTrimPayloadIfWin(p, 0, tdb);
+            listener->normalizer->trim_win_payload( tdb );
             MODULE_PROFILE_END(s5TcpDataPerfStats);
             return STREAM_UNALIGNED;
         }
@@ -1020,12 +1024,12 @@ static int ProcessTcpData(Packet *p, TcpTracker *listener, TcpSession *tcpssn,
         if (listener->s_mgr.state_queue == TCP_STATE_NONE)
             listener->r_nxt_ack = tdb->end_seq;
 
-        if (p->dsize != 0)
+        if (tdb->pkt->dsize != 0)
         {
-            if (!(tcpssn->flow->ssn_state.session_flags & SSNFLAG_STREAM_ORDER_BAD))
-                p->packet_flags |= PKT_STREAM_ORDER_OK;
+            if (!(tcpssn->flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD))
+                tdb->pkt->packet_flags |= PKT_STREAM_ORDER_OK;
 
-            ProcessTcpStream(listener, tcpssn, p, tdb, config);
+            ProcessTcpStream(listener, tcpssn, tdb, config);
             /* set flags to session flags */
 
             MODULE_PROFILE_END(s5TcpDataPerfStats);
@@ -1051,10 +1055,10 @@ static int ProcessTcpData(Packet *p, TcpTracker *listener, TcpSession *tcpssn,
         {
             /* check if we're in the window */
             if (listener->config->policy != STREAM_POLICY_PROXY
-                    and StreamGetWindow(tcpssn->flow, listener, tdb) == 0)
+                    and listener->normalizer->get_stream_window( tdb ) == 0)
             {
                 DebugMessage(DEBUG_STREAM_STATE, "Bailing, we're out of the window!\n");
-                NormalTrimPayloadIfWin(p, 0, tdb);
+                listener->normalizer->trim_win_payload( tdb );
                 MODULE_PROFILE_END(s5TcpDataPerfStats);
                 return STREAM_UNALIGNED;
             }
@@ -1072,14 +1076,14 @@ static int ProcessTcpData(Packet *p, TcpTracker *listener, TcpSession *tcpssn,
             }
         }
 
-        if (p->dsize != 0)
+        if (tdb->pkt->dsize != 0)
         {
-            if (!(tcpssn->flow->ssn_state.session_flags & SSNFLAG_STREAM_ORDER_BAD))
+            if (!(tcpssn->flow->get_session_flags() & SSNFLAG_STREAM_ORDER_BAD))
             {
-                if (!SEQ_LEQ((tdb->seq + p->dsize), listener->r_nxt_ack))
-                    tcpssn->flow->ssn_state.session_flags |= SSNFLAG_STREAM_ORDER_BAD;
+                if (!SEQ_LEQ((tdb->seq + tdb->pkt->dsize), listener->r_nxt_ack))
+                    tcpssn->flow->set_session_flags( SSNFLAG_STREAM_ORDER_BAD );
             }
-            ProcessTcpStream(listener, tcpssn, p, tdb, config);
+            ProcessTcpStream(listener, tcpssn, tdb, config);
         }
     }
 
@@ -1097,12 +1101,16 @@ static void SetOSPolicy(Flow* flow, TcpSession* tcpssn)
     if (!tcpssn->client.os_policy)
     {
         tcpssn->client.os_policy = flow->ssn_policy ? flow->ssn_policy : tcpssn->client.config->policy;
+        tcpssn->client.normalizer = TcpNormalizerFactory::allocate_normalizer( tcpssn->client.os_policy,
+                tcpssn, &tcpssn->client, &tcpssn->server );
         SetTcpReassemblyPolicy(&tcpssn->client);
     }
 
     if (!tcpssn->server.os_policy)
     {
         tcpssn->server.os_policy = flow->ssn_policy ? flow->ssn_policy : tcpssn->server.config->policy;
+        tcpssn->server.normalizer = TcpNormalizerFactory::allocate_normalizer( tcpssn->client.os_policy,
+                tcpssn, &tcpssn->server, &tcpssn->client );
         SetTcpReassemblyPolicy(&tcpssn->server);
     }
 }
@@ -1190,7 +1198,7 @@ static inline void CopyMacAddr(Packet* p, TcpSession* tcpssn, int dir)
     }
 }
 
-static void NewTcpSession(Packet* p, Flow* flow, StreamTcpConfig* dstPolicy, TcpSession* tmp)
+static void NewTcpSession(Packet* p, Flow* flow, StreamTcpConfig* dstPolicy, TcpSession* tss)
 {
     Inspector* ins = flow->gadget;
 
@@ -1201,7 +1209,8 @@ static void NewTcpSession(Packet* p, Flow* flow, StreamTcpConfig* dstPolicy, Tcp
     {
         stream.set_splitter(flow, true, ins->get_splitter(true));
         stream.set_splitter(flow, false, ins->get_splitter(false));
-    } else
+    }
+    else
     {
         stream.set_splitter(flow, true, new AtomSplitter(true));
         stream.set_splitter(flow, false, new AtomSplitter(false));
@@ -1210,24 +1219,18 @@ static void NewTcpSession(Packet* p, Flow* flow, StreamTcpConfig* dstPolicy, Tcp
     {
         DebugMessage(DEBUG_STREAM_STATE, "adding TcpSession to lightweight session\n");
         flow->protocol = p->type();
-        tmp->flow = flow;
-
-        /* New session, previous was marked as reset.  Clear the
-         * reset flag. */
-        if (flow->ssn_state.session_flags & SSNFLAG_RESET)
-            flow->ssn_state.session_flags &= ~SSNFLAG_RESET;
+        tss->flow = flow;
 
-        SetOSPolicy(flow, tmp);
-
-        if ((flow->ssn_state.session_flags & SSNFLAG_CLIENT_SWAP)
-                && !(flow->ssn_state.session_flags & SSNFLAG_CLIENT_SWAPPED))
+        /* New session, previous was marked as reset.  Clear the reset flag. */
+        uint32_t session_flags = flow->clear_session_flags( SSNFLAG_RESET );
+        if ((session_flags & SSNFLAG_CLIENT_SWAP) && !(session_flags & SSNFLAG_CLIENT_SWAPPED))
         {
-            TcpTracker trk = tmp->client;
+            TcpTracker trk = tss->client;
             sfip_t ip = flow->client_ip;
             uint16_t port = flow->client_port;
 
-            tmp->client = tmp->server;
-            tmp->server = trk;
+            tss->client = tss->server;
+            tss->server = trk;
 
             flow->client_ip = flow->server_ip;
             flow->server_ip = ip;
@@ -1237,317 +1240,317 @@ static void NewTcpSession(Packet* p, Flow* flow, StreamTcpConfig* dstPolicy, Tcp
 
             if (!flow->two_way_traffic())
             {
-                if (flow->ssn_state.session_flags & SSNFLAG_SEEN_CLIENT)
+                if (session_flags & SSNFLAG_SEEN_CLIENT)
                 {
-                    flow->ssn_state.session_flags ^= SSNFLAG_SEEN_CLIENT;
-                    flow->ssn_state.session_flags |= SSNFLAG_SEEN_SERVER;
+                    session_flags ^= SSNFLAG_SEEN_CLIENT;
+                    session_flags |= SSNFLAG_SEEN_SERVER;
                 }
-                else if (flow->ssn_state.session_flags & SSNFLAG_SEEN_SERVER)
+                else if (session_flags & SSNFLAG_SEEN_SERVER)
                 {
-                    flow->ssn_state.session_flags ^= SSNFLAG_SEEN_SERVER;
-                    flow->ssn_state.session_flags |= SSNFLAG_SEEN_CLIENT;
+                    session_flags ^= SSNFLAG_SEEN_SERVER;
+                    session_flags |= SSNFLAG_SEEN_CLIENT;
                 }
             }
-            flow->ssn_state.session_flags |= SSNFLAG_CLIENT_SWAPPED;
+
+            session_flags |= SSNFLAG_CLIENT_SWAPPED;
+            flow->update_session_flags( session_flags );
         }
-        init_flush_policy(flow, &tmp->server);
-        init_flush_policy(flow, &tmp->client);
+        init_flush_policy(flow, &tss->server);
+        init_flush_policy(flow, &tss->client);
 
 #ifdef DEBUG_STREAM_EX
-        PrintTcpSession(tmp);
+        PrintTcpSession(tss);
 #endif
         flow->set_expire(p, dstPolicy->session_timeout);
 
         AddStreamSession(&sfBase,
-                flow->session_state & STREAM_STATE_MIDSTREAM ?
-                SSNFLAG_MIDSTREAM : 0);
+                flow->session_state & STREAM_STATE_MIDSTREAM ? SSNFLAG_MIDSTREAM : 0);
 
-        StreamUpdatePerfBaseState(&sfBase, tmp->flow, TCP_STATE_SYN_SENT);
+        StreamUpdatePerfBaseState(&sfBase, tss->flow, TCP_STATE_SYN_SENT);
 
         EventInternal(INTERNAL_EVENT_SESSION_ADD);
 
-        tmp->ecn = 0;
-        assert(!tmp->tcp_init);
-        tmp->tcp_init = true;
+        tss->ecn = 0;
+        assert(!tss->tcp_init);
+        tss->tcp_init = true;
 
         tcpStats.trackers_created++;
     }
 }
 
-static void NewTcpSessionOnSyn(Packet* p, Flow* flow, TcpDataBlock* tdb,
-        StreamTcpConfig* dstPolicy)
+static void NewTcpSessionOnSyn(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* dstPolicy)
 {
+    const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+
     PROFILE_VARS; MODULE_PROFILE_START(s5TcpNewSessPerfStats);
-    TcpSession* tmp;
-    {
-        /******************************************************************
-         * start new sessions on proper SYN packets
-         *****************************************************************/
-        tmp = (TcpSession*) flow->session;
-        DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on SYN!\n");
+    TcpSession* tss;
 
-        flow->ssn_state.session_flags |= SSNFLAG_SEEN_CLIENT;
+    /******************************************************************
+     * start new sessions on proper SYN packets
+     *****************************************************************/
+    tss = (TcpSession*) flow->session;
+    DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on SYN!\n");
 
-        if (p->ptrs.tcph->are_flags_set(TH_CWR | TH_ECE))
-        {
-            flow->ssn_state.session_flags |= SSNFLAG_ECN_CLIENT_QUERY;
-        }
+    flow->set_session_flags( SSNFLAG_SEEN_CLIENT );
 
-        /* setup the stream trackers */
-        tmp->client.s_mgr.state = TCP_STATE_SYN_SENT;
-        tmp->client.isn = tdb->seq;
-        tmp->client.l_unackd = tdb->seq + 1;
-        tmp->client.l_nxt_seq = tmp->client.l_unackd;
+    if (tcph->are_flags_set(TH_CWR | TH_ECE))
+        flow->set_session_flags( SSNFLAG_ECN_CLIENT_QUERY );
 
-        if (tdb->seq != tdb->end_seq)
-            tmp->client.l_nxt_seq += (tdb->end_seq - tdb->seq - 1);
+    /* setup the stream trackers */
+    /* Set the StreamTcpConfig for each direction (pkt from client) */
+    tss->client.config = dstPolicy; // FIXIT-M use external binding for both dirs
+    tss->server.config = dstPolicy; // (applies to all the blocks in this funk)
+    SetOSPolicy(flow, tss);
 
-        tmp->client.l_window = tdb->win;
-        tmp->client.ts_last_pkt = p->pkth->ts.tv_sec;
+    tss->client.s_mgr.state = TCP_STATE_SYN_SENT;
+    tss->client.isn = tdb->seq;
+    tss->client.l_unackd = tdb->seq + 1;
+    tss->client.l_nxt_seq = tss->client.l_unackd;
 
-        tmp->server.seglist_base_seq = tmp->client.l_unackd;
-        tmp->server.r_nxt_ack = tmp->client.l_unackd;
-        tmp->server.r_win_base = tdb->seq + 1;
+    if (tdb->seq != tdb->end_seq)
+        tss->client.l_nxt_seq += (tdb->end_seq - tdb->seq - 1);
 
-        DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", tmp->server.seglist_base_seq);
-        tmp->server.s_mgr.state = TCP_STATE_LISTEN;
+    tss->client.l_window = tdb->win;
+    tss->client.ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
 
-        tmp->client.flags |= StreamGetTcpTimestamp(p, &tmp->client.ts_last, 0);
-        if (tmp->client.ts_last == 0)
-            tmp->client.flags |= TF_TSTAMP_ZERO;
-        tmp->client.flags |= StreamGetMss(p, &tmp->client.mss);
-        tmp->client.flags |= StreamGetWscale(p, &tmp->client.wscale);
+    tss->server.seglist_base_seq = tss->client.l_unackd;
+    tss->server.r_nxt_ack = tss->client.l_unackd;
+    tss->server.r_win_base = tdb->seq + 1;
 
-        /* Set the StreamTcpConfig for each direction (pkt from client) */
-        tmp->client.config = dstPolicy; // FIXIT-M use external binding for both dirs
-        tmp->server.config = dstPolicy; // (applies to all the blocks in this funk)
+    DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", tss->server.seglist_base_seq);
+    tss->server.s_mgr.state = TCP_STATE_LISTEN;
+
+    tss->client.flags |= tss->client.normalizer->get_tcp_timestamp(tdb, false);
+    tss->client.ts_last = tdb->ts;
+    if (tss->client.ts_last == 0)
+        tss->client.flags |= TF_TSTAMP_ZERO;
+    tss->client.flags |= StreamGetMss(tdb->pkt, &tss->client.mss);
+    tss->client.flags |= StreamGetWscale(tdb->pkt, &tss->client.wscale);
+
+    CopyMacAddr(tdb->pkt, tss, FROM_CLIENT);
 
-        CopyMacAddr(p, tmp, FROM_CLIENT);
-    }
     tcpStats.sessions_on_syn++;
-    NewTcpSession(p, flow, dstPolicy, tmp);
+    NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
     MODULE_PROFILE_END(s5TcpNewSessPerfStats);
 }
 
-static void NewTcpSessionOnSynAck(Packet* p, Flow* flow, TcpDataBlock* tdb,
-        StreamTcpConfig* dstPolicy)
+static void NewTcpSessionOnSynAck(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* dstPolicy)
 {
-    PROFILE_VARS; MODULE_PROFILE_START(s5TcpNewSessPerfStats);
-    TcpSession* tmp;
-    {
-        tmp = (TcpSession*) flow->session;
-        DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on SYN_ACK!\n");
+    const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
 
-        flow->ssn_state.session_flags |= SSNFLAG_SEEN_SERVER;
-
-        if (p->ptrs.tcph->are_flags_set(TH_CWR | TH_ECE))
-        {
-            flow->ssn_state.session_flags |= SSNFLAG_ECN_SERVER_REPLY;
-        }
+    PROFILE_VARS; MODULE_PROFILE_START(s5TcpNewSessPerfStats);
+    TcpSession* tss;
+
+    tss = (TcpSession*) flow->session;
+    DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on SYN_ACK!\n");
+
+    flow->set_session_flags( SSNFLAG_SEEN_SERVER );
+    if (tcph->are_flags_set(TH_CWR | TH_ECE))
+        flow->set_session_flags( SSNFLAG_ECN_SERVER_REPLY );
+
+    /* setup the stream trackers */
+    /* Set the config for each direction (pkt from server) */
+    tss->server.config = dstPolicy;
+    tss->client.config = dstPolicy;
+    SetOSPolicy(flow, tss);
+
+    tss->server.s_mgr.state = TCP_STATE_SYN_RCVD;
+    tss->server.isn = tdb->seq;
+    tss->server.l_unackd = tdb->seq + 1;
+    tss->server.l_nxt_seq = tss->server.l_unackd;
+    tss->server.l_window = tdb->win;
+
+    tss->server.seglist_base_seq = tdb->ack;
+    tss->server.r_win_base = tdb->ack;
+    tss->server.r_nxt_ack = tdb->ack;
+    tss->server.ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
+
+    tss->client.seglist_base_seq = tss->server.l_unackd;
+    tss->client.r_nxt_ack = tss->server.l_unackd;
+    tss->client.r_win_base = tdb->seq + 1;
+    tss->client.l_nxt_seq = tdb->ack;
+    tss->client.isn = tdb->ack - 1;
+
+    DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", tss->client.seglist_base_seq);
+    tss->client.s_mgr.state = TCP_STATE_SYN_SENT;
+
+    tss->server.flags |= tss->server.normalizer->get_tcp_timestamp(tdb, false);
+    tss->server.ts_last = tdb->ts;
+    if (tss->server.ts_last == 0)
+        tss->server.flags |= TF_TSTAMP_ZERO;
+    tss->server.flags |= StreamGetMss(tdb->pkt, &tss->server.mss);
+    tss->server.flags |= StreamGetWscale(tdb->pkt, &tss->server.wscale);
+
+    CopyMacAddr(tdb->pkt, tss, FROM_SERVER);
 
-        /* setup the stream trackers */
-        tmp->server.s_mgr.state = TCP_STATE_SYN_RCVD;
-        tmp->server.isn = tdb->seq;
-        tmp->server.l_unackd = tdb->seq + 1;
-        tmp->server.l_nxt_seq = tmp->server.l_unackd;
-        tmp->server.l_window = tdb->win;
-
-        tmp->server.seglist_base_seq = tdb->ack;
-        tmp->server.r_win_base = tdb->ack;
-        tmp->server.r_nxt_ack = tdb->ack;
-        tmp->server.ts_last_pkt = p->pkth->ts.tv_sec;
-
-        tmp->client.seglist_base_seq = tmp->server.l_unackd;
-        tmp->client.r_nxt_ack = tmp->server.l_unackd;
-        tmp->client.r_win_base = tdb->seq + 1;
-        tmp->client.l_nxt_seq = tdb->ack;
-        tmp->client.isn = tdb->ack - 1;
-
-        DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", tmp->client.seglist_base_seq);
-        tmp->client.s_mgr.state = TCP_STATE_SYN_SENT;
-
-        tmp->server.flags |= StreamGetTcpTimestamp(p, &tmp->server.ts_last, 0);
-        if (tmp->server.ts_last == 0)
-            tmp->server.flags |= TF_TSTAMP_ZERO;
-        tmp->server.flags |= StreamGetMss(p, &tmp->server.mss);
-        tmp->server.flags |= StreamGetWscale(p, &tmp->server.wscale);
-
-        /* Set the config for each direction (pkt from server) */
-        tmp->server.config = dstPolicy;
-        tmp->client.config = dstPolicy;
-
-        CopyMacAddr(p, tmp, FROM_SERVER);
-    }
     tcpStats.sessions_on_syn_ack++;
-    NewTcpSession(p, flow, dstPolicy, tmp);
+    NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
     MODULE_PROFILE_END(s5TcpNewSessPerfStats);
 }
 
-static void NewTcpSessionOn3Way(Packet* p, Flow* flow, TcpDataBlock* tdb,
+static void NewTcpSessionOn3Way(Flow* flow, TcpDataBlock* tdb,
         StreamTcpConfig* dstPolicy)
 {
+    const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+
     PROFILE_VARS; MODULE_PROFILE_START(s5TcpNewSessPerfStats);
-    TcpSession* tmp;
-    {
-        /******************************************************************
-         * start new sessions on completion of 3-way (ACK only, no data)
-         *****************************************************************/
-        tmp = (TcpSession*) flow->session;
-        DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on ACK!\n");
+    TcpSession* tss;
 
-        flow->ssn_state.session_flags |= SSNFLAG_SEEN_CLIENT;
+    /******************************************************************
+     * start new sessions on completion of 3-way (ACK only, no data)
+     *****************************************************************/
+    tss = (TcpSession*) flow->session;
+    DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on ACK!\n");
 
-        if (p->ptrs.tcph->are_flags_set(TH_CWR | TH_ECE))
-        {
-            flow->ssn_state.session_flags |= SSNFLAG_ECN_CLIENT_QUERY;
-        }
+    flow->set_session_flags( SSNFLAG_SEEN_CLIENT );
 
-        /* setup the stream trackers */
-        tmp->client.s_mgr.state = TCP_STATE_ESTABLISHED;
-        tmp->client.isn = tdb->seq;
-        tmp->client.l_unackd = tdb->seq + 1;
-        tmp->client.l_nxt_seq = tmp->client.l_unackd;
-        tmp->client.l_window = tdb->win;
+    if (tcph->are_flags_set(TH_CWR | TH_ECE))
+        flow->set_session_flags( SSNFLAG_ECN_CLIENT_QUERY );
 
-        tmp->client.ts_last_pkt = p->pkth->ts.tv_sec;
+    /* setup the stream trackers */
+    /* Set the config for each direction (pkt from client) */
+     tss->client.config = dstPolicy;
+     tss->server.config = dstPolicy;
+     SetOSPolicy(flow, tss);
 
-        tmp->server.seglist_base_seq = tmp->client.l_unackd;
-        tmp->server.r_nxt_ack = tmp->client.l_unackd;
-        tmp->server.r_win_base = tdb->seq + 1;
+    tss->client.s_mgr.state = TCP_STATE_ESTABLISHED;
+    tss->client.isn = tdb->seq;
+    tss->client.l_unackd = tdb->seq + 1;
+    tss->client.l_nxt_seq = tss->client.l_unackd;
+    tss->client.l_window = tdb->win;
 
-        DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", tmp->server.seglist_base_seq);
-        tmp->server.s_mgr.state = TCP_STATE_ESTABLISHED;
+    tss->client.ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
 
-        tmp->client.flags |= StreamGetTcpTimestamp(p, &tmp->client.ts_last, 0);
-        if (tmp->client.ts_last == 0)
-            tmp->client.flags |= TF_TSTAMP_ZERO;
-        tmp->client.flags |= StreamGetMss(p, &tmp->client.mss);
-        tmp->client.flags |= StreamGetWscale(p, &tmp->client.wscale);
+    tss->server.seglist_base_seq = tss->client.l_unackd;
+    tss->server.r_nxt_ack = tss->client.l_unackd;
+    tss->server.r_win_base = tdb->seq + 1;
 
-        /* Set the config for each direction (pkt from client) */
-        tmp->client.config = dstPolicy;
-        tmp->server.config = dstPolicy;
+    DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", tss->server.seglist_base_seq);
+    tss->server.s_mgr.state = TCP_STATE_ESTABLISHED;
+
+    tss->client.flags |= tss->client.normalizer->get_tcp_timestamp(tdb, false);
+    tss->client.ts_last = tdb->ts;
+    if (tss->client.ts_last == 0)
+        tss->client.flags |= TF_TSTAMP_ZERO;
+    tss->client.flags |= StreamGetMss(tdb->pkt, &tss->client.mss);
+    tss->client.flags |= StreamGetWscale(tdb->pkt, &tss->client.wscale);
+
+    CopyMacAddr(tdb->pkt, tss, FROM_CLIENT);
 
-        CopyMacAddr(p, tmp, FROM_CLIENT);
-    }
     tcpStats.sessions_on_3way++;
-    NewTcpSession(p, flow, dstPolicy, tmp);
+    NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
     MODULE_PROFILE_END(s5TcpNewSessPerfStats);
 }
 
-static void NewTcpSessionOnData(Packet* p, Flow* flow, TcpDataBlock* tdb,
-        StreamTcpConfig* dstPolicy)
+static void NewTcpSessionOnData(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* dstPolicy)
 {
-    PROFILE_VARS; MODULE_PROFILE_START(s5TcpNewSessPerfStats);
-    TcpSession* tmp;
-    {
-        tmp = (TcpSession*) flow->session;
-        DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on data packet (ACK|PSH)!\n");
+    const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
 
-        if (flow->ssn_state.direction == FROM_CLIENT)
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "Session direction is FROM_CLIENT\n");
-
-            /* Sender is client (src port is higher) */
-            flow->ssn_state.session_flags |= SSNFLAG_SEEN_CLIENT;
+    PROFILE_VARS; MODULE_PROFILE_START(s5TcpNewSessPerfStats);
+    TcpSession* tss;
 
-            if (p->ptrs.tcph->are_flags_set(TH_CWR | TH_ECE))
-                flow->ssn_state.session_flags |= SSNFLAG_ECN_CLIENT_QUERY;
+    tss = (TcpSession*) flow->session;
+    DebugMessage(DEBUG_STREAM_STATE, "Creating new session tracker on data packet (ACK|PSH)!\n");
 
-            /* setup the stream trackers */
-            tmp->client.s_mgr.state = TCP_STATE_ESTABLISHED;
-            tmp->client.isn = tdb->seq;
-            tmp->client.l_unackd = tdb->seq;
-            tmp->client.l_nxt_seq = tmp->client.l_unackd;
-            tmp->client.l_window = tdb->win;
+    /* Set the config for each direction (pkt from client) */
+    tss->client.config = dstPolicy;
+    tss->server.config = dstPolicy;
+    SetOSPolicy(flow, tss);
+    if (flow->ssn_state.direction == FROM_CLIENT)
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "Session direction is FROM_CLIENT\n");
 
-            tmp->client.ts_last_pkt = p->pkth->ts.tv_sec;
+        /* Sender is client (src port is higher) */
+        flow->set_session_flags( SSNFLAG_SEEN_CLIENT );
+        if (tcph->are_flags_set(TH_CWR | TH_ECE))
+            flow->set_session_flags( SSNFLAG_ECN_CLIENT_QUERY );
 
-            tmp->server.seglist_base_seq = tmp->client.l_unackd;
-            tmp->server.r_nxt_ack = tmp->client.l_unackd;
-            tmp->server.r_win_base = tdb->seq;
-            tmp->server.l_window = 0; /* reset later */
+        /* setup the stream trackers */
+        tss->client.s_mgr.state = TCP_STATE_ESTABLISHED;
+        tss->client.isn = tdb->seq;
+        tss->client.l_unackd = tdb->seq;
+        tss->client.l_nxt_seq = tss->client.l_unackd;
+        tss->client.l_window = tdb->win;
 
-            /* Next server packet is what was ACKd */
-            //tmp->server.l_nxt_seq = tdb->ack + 1;
-            tmp->server.l_unackd = tdb->ack - 1;
+        tss->client.ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
 
-            DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", tmp->server.seglist_base_seq);
-            tmp->server.s_mgr.state = TCP_STATE_ESTABLISHED;
+        tss->server.seglist_base_seq = tss->client.l_unackd;
+        tss->server.r_nxt_ack = tss->client.l_unackd;
+        tss->server.r_win_base = tdb->seq;
+        tss->server.l_window = 0; /* reset later */
 
-            tmp->client.flags |= StreamGetTcpTimestamp(p, &tmp->client.ts_last,
-                    0);
-            if (tmp->client.ts_last == 0)
-                tmp->client.flags |= TF_TSTAMP_ZERO;
+        /* Next server packet is what was ACKd */
+        //tss->server.l_nxt_seq = tdb->ack + 1;
+        tss->server.l_unackd = tdb->ack - 1;
 
-            tmp->client.flags |= StreamGetMss(p, &tmp->client.mss);
-            tmp->client.flags |= StreamGetWscale(p, &tmp->client.wscale);
+        DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", tss->server.seglist_base_seq);
+        tss->server.s_mgr.state = TCP_STATE_ESTABLISHED;
 
-            /* Set the config for each direction (pkt from client) */
-            tmp->client.config = dstPolicy;
-            tmp->server.config = dstPolicy;
+        tss->client.flags |= tss->client.normalizer->get_tcp_timestamp(tdb, false);
+        tss->client.ts_last = tdb->ts;
+        if (tss->client.ts_last == 0)
+            tss->client.flags |= TF_TSTAMP_ZERO;
 
-            CopyMacAddr(p, tmp, FROM_CLIENT);
-        }
-        else
-        {
-            DebugMessage(DEBUG_STREAM_STATE, "Session direction is FROM_SERVER\n");
+        tss->client.flags |= StreamGetMss(tdb->pkt, &tss->client.mss);
+        tss->client.flags |= StreamGetWscale(tdb->pkt, &tss->client.wscale);
 
-            /* Sender is server (src port is lower) */
-            flow->ssn_state.session_flags |= SSNFLAG_SEEN_SERVER;
+        CopyMacAddr(tdb->pkt, tss, FROM_CLIENT);
+    }
+    else
+    {
+        DebugMessage(DEBUG_STREAM_STATE, "Session direction is FROM_SERVER\n");
 
-            /* setup the stream trackers */
-            tmp->server.s_mgr.state = TCP_STATE_ESTABLISHED;
-            tmp->server.isn = tdb->seq;
-            tmp->server.l_unackd = tdb->seq;
-            tmp->server.l_nxt_seq = tmp->server.l_unackd;
-            tmp->server.l_window = tdb->win;
+        /* Sender is server (src port is lower) */
+        flow->set_session_flags( SSNFLAG_SEEN_SERVER );
 
-            tmp->server.seglist_base_seq = tdb->ack;
-            tmp->server.r_win_base = tdb->ack;
-            tmp->server.r_nxt_ack = tdb->ack;
-            tmp->server.ts_last_pkt = p->pkth->ts.tv_sec;
+        /* setup the stream trackers */
+        tss->server.s_mgr.state = TCP_STATE_ESTABLISHED;
+        tss->server.isn = tdb->seq;
+        tss->server.l_unackd = tdb->seq;
+        tss->server.l_nxt_seq = tss->server.l_unackd;
+        tss->server.l_window = tdb->win;
 
-            tmp->client.seglist_base_seq = tmp->server.l_unackd;
-            tmp->client.r_nxt_ack = tmp->server.l_unackd;
-            tmp->client.r_win_base = tdb->seq;
-            tmp->client.l_window = 0; /* reset later */
-            tmp->client.isn = tdb->ack - 1;
+        tss->server.seglist_base_seq = tdb->ack;
+        tss->server.r_win_base = tdb->ack;
+        tss->server.r_nxt_ack = tdb->ack;
+        tss->server.ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
 
-            DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", tmp->client.seglist_base_seq);
-            tmp->client.s_mgr.state = TCP_STATE_ESTABLISHED;
+        tss->client.seglist_base_seq = tss->server.l_unackd;
+        tss->client.r_nxt_ack = tss->server.l_unackd;
+        tss->client.r_win_base = tdb->seq;
+        tss->client.l_window = 0; /* reset later */
+        tss->client.isn = tdb->ack - 1;
 
-            tmp->server.flags |= StreamGetTcpTimestamp(p, &tmp->server.ts_last,
-                    0);
-            if (tmp->server.ts_last == 0)
-                tmp->server.flags |= TF_TSTAMP_ZERO;
+        DebugFormat(DEBUG_STREAM_STATE, "seglist_base_seq = %X\n", tss->client.seglist_base_seq);
+        tss->client.s_mgr.state = TCP_STATE_ESTABLISHED;
 
-            tmp->server.flags |= StreamGetMss(p, &tmp->server.mss);
-            tmp->server.flags |= StreamGetWscale(p, &tmp->server.wscale);
+        tss->server.flags |= tss->server.normalizer->get_tcp_timestamp(tdb, 0);
+        tss->server.ts_last = tdb->ts;
+        if (tss->server.ts_last == 0)
+            tss->server.flags |= TF_TSTAMP_ZERO;
 
-            /* Set the config for each direction (pkt from server) */
-            tmp->server.config = dstPolicy;
-            tmp->client.config = dstPolicy;
+        tss->server.flags |= StreamGetMss(tdb->pkt, &tss->server.mss);
+        tss->server.flags |= StreamGetWscale(tdb->pkt, &tss->server.wscale);
 
-            CopyMacAddr(p, tmp, FROM_SERVER);
-        }
+        CopyMacAddr(tdb->pkt, tss, FROM_SERVER);
     }
 
     tcpStats.sessions_on_data++;
-    NewTcpSession(p, flow, dstPolicy, tmp);
+    NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
     MODULE_PROFILE_END(s5TcpNewSessPerfStats);
 }
 
-static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig* config)
+static int ProcessTcp(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* config)
 {
     int retcode = ACTION_NOTHING;
     int eventcode = 0;
     int got_ts = 0;
     int new_ssn = 0;
     int ts_action = ACTION_NOTHING;
-    TcpSession *tcpssn = NULL;
-    TcpTracker *talker = NULL;
-    TcpTracker *listener = NULL;
+    const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+    TcpSession* tcpssn = NULL;
+    TcpTracker* talker = NULL;
+    TcpTracker* listener = NULL;
     DEBUG_WRAP( const char* t = NULL; const char* l = NULL; );
     PROFILE_VARS;
 
@@ -1557,7 +1560,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
         return retcode;
     }
 
-    tcpssn = (TcpSession*) flow->session;
+    tcpssn = ( TcpSession* ) flow->session;
 
     MODULE_PROFILE_START(s5TcpStatePerfStats);
 
@@ -1565,7 +1568,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
     {
         // FIXIT-L expected flow should be checked by flow_con before we
         // get here
-        char ignore = flow_con->expected_flow(flow, p);
+        char ignore = flow_con->expected_flow(flow, tdb->pkt);
 
         if (ignore)
         {
@@ -1575,33 +1578,33 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
         }
 
         bool require3Way = config->require_3whs();
-        bool allow_midstream = config->midstream_allowed(p);
+        bool allow_midstream = config->midstream_allowed(tdb->pkt);
 
-        if (p->ptrs.tcph->is_syn_only())
+        if (tcph->is_syn_only())
         {
             DebugMessage(DEBUG_STREAM_STATE, "Stream SYN PACKET, establishing lightweight session direction.\n");
             /* SYN packet from client */
             flow->ssn_state.direction = FROM_CLIENT;
             flow->session_state |= STREAM_STATE_SYN;
 
-            if (require3Way || (StreamPacketHasWscale(p) & TF_WSCALE) || (p->dsize > 0))
+            if (require3Way || (StreamPacketHasWscale(tdb->pkt) & TF_WSCALE) || (tdb->pkt->dsize > 0))
             {
                 /* Create TCP session if we
                  * 1) require 3-WAY HS, OR
                  * 2) client sent wscale option, OR
                  * 3) have data
                  */
-                NewTcpSessionOnSyn(p, flow, tdb, config);
+                NewTcpSessionOnSyn( flow, tdb, config);
                 new_ssn = 1;
-                NormalTrackECN(tcpssn, (TCPHdr*) p->ptrs.tcph, require3Way);
+                tcpssn->server.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
             }
 
             /* Nothing left todo here */
         }
-        else if (p->ptrs.tcph->is_syn_ack())
+        else if (tcph->is_syn_ack())
         {
             /* SYN-ACK from server */
-            if ((flow->session_state == STREAM_STATE_NONE) || (flow->ssn_state.session_flags & SSNFLAG_RESET))
+            if ((flow->session_state == STREAM_STATE_NONE) || (flow->get_session_flags() & SSNFLAG_RESET))
             {
                 DebugMessage(DEBUG_STREAM_STATE, "Stream SYN|ACK PACKET, establishing lightweight session direction.\n");
                 flow->ssn_state.direction = FROM_SERVER;
@@ -1611,42 +1614,45 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
 
             if (!require3Way || allow_midstream)
             {
-                NewTcpSessionOnSynAck(p, flow, tdb, config);
+                NewTcpSessionOnSynAck(flow, tdb, config);
                 new_ssn = 1;
             }
 
-            NormalTrackECN(tcpssn, (TCPHdr*) p->ptrs.tcph, require3Way);
+            tcpssn->client.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
         }
-        else if (p->ptrs.tcph->is_ack() && !p->ptrs.tcph->is_rst() && (flow->session_state & STREAM_STATE_SYN_ACK))
+        else if (tcph->is_ack() && !tcph->is_rst() && (flow->session_state & STREAM_STATE_SYN_ACK))
         {
             /* 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;
-            NewTcpSessionOn3Way(p, flow, tdb, config);
+            NewTcpSessionOn3Way(flow, tdb, config);
             new_ssn = 1;
-            NormalTrackECN(tcpssn, (TCPHdr*) p->ptrs.tcph, require3Way);
+            tcpssn->server.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
             StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_ESTABLISHED);
         }
-        else if (p->dsize && (!require3Way || allow_midstream))
+        else if (tdb->pkt->dsize && (!require3Way || allow_midstream))
         {
             /* create session on data, need to figure out direction, etc
                Assume from client, can update later */
-            if (p->ptrs.sp > p->ptrs.dp)
+            if (tdb->pkt->ptrs.sp > tdb->pkt->ptrs.dp)
                 flow->ssn_state.direction = FROM_CLIENT;
             else
                 flow->ssn_state.direction = FROM_SERVER;
 
             flow->session_state |= STREAM_STATE_MIDSTREAM;
-            flow->ssn_state.session_flags |= SSNFLAG_MIDSTREAM;
+            flow->set_session_flags( SSNFLAG_MIDSTREAM );
 
-            NewTcpSessionOnData(p, flow, tdb, config);
+            NewTcpSessionOnData(flow, tdb, config);
             new_ssn = 1;
-            NormalTrackECN(tcpssn, (TCPHdr*) p->ptrs.tcph, require3Way);
+            if(flow->ssn_state.direction == FROM_CLIENT)
+                tcpssn->server.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
+            else
+                tcpssn->client.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
 
             if (flow->session_state & STREAM_STATE_ESTABLISHED)
                 StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_ESTABLISHED);
         }
-        else if (!p->dsize)
+        else if (!tdb->pkt->dsize)
         {
             /* Do nothing. */
             MODULE_PROFILE_END(s5TcpStatePerfStats);
@@ -1657,7 +1663,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
     {
         /* If session is already marked as established */
         if (!(flow->session_state & STREAM_STATE_ESTABLISHED)
-                && (!config->require_3whs() || config->midstream_allowed(p)))
+                && (!config->require_3whs() || config->midstream_allowed(tdb->pkt)))
         {
             /* If not requiring 3-way Handshake... */
 
@@ -1665,7 +1671,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
              * or maybe on SYN-ACK, or anything else */
 
             /* Need to update Lightweight session state */
-            if (p->ptrs.tcph->is_syn_ack())
+            if (tcph->is_syn_ack())
             {
                 /* SYN-ACK from server */
                 if (flow->session_state != STREAM_STATE_NONE)
@@ -1673,20 +1679,20 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                     flow->session_state |= STREAM_STATE_SYN_ACK;
                 }
             }
-            else if (p->ptrs.tcph->is_ack() && (flow->session_state & STREAM_STATE_SYN_ACK))
+            else if (tcph->is_ack() && (flow->session_state & STREAM_STATE_SYN_ACK))
             {
                 flow->session_state |= STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED;
                 StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_ESTABLISHED);
             }
         }
-        if (p->ptrs.tcph->is_syn())
-            NormalTrackECN(tcpssn, (TCPHdr*) p->ptrs.tcph, config->require_3whs());
+        if (tcph->is_syn())
+            tcpssn->server.normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, config->require_3whs() );
     }
 
-    if (p->packet_flags & PKT_FROM_SERVER)
+    if (tdb->pkt->packet_flags & PKT_FROM_SERVER)
     {
         DebugMessage(DEBUG_STREAM_STATE,  "Stream: Updating on packet from server\n");
-        flow->ssn_state.session_flags |= SSNFLAG_SEEN_SERVER;
+        flow->set_session_flags( SSNFLAG_SEEN_SERVER );
 
         if (tcpssn->tcp_init)
         {
@@ -1698,35 +1704,32 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                 t = "Server";
                 l = "Client");
 
-        if (talker && talker->s_mgr.state == TCP_STATE_LISTEN
-                && ((p->ptrs.tcph->th_flags & (TH_SYN | TH_ACK)) == TH_SYN))
-        {
+        if( talker && ( talker->s_mgr.state == TCP_STATE_LISTEN ) && tcph->is_syn_only() )
             eventcode |= 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))
         {
-            FinishServerInit(p, tdb, tcpssn);
-            if ((p->ptrs.tcph->th_flags & TH_ECE) && ( flow->ssn_state.session_flags & SSNFLAG_ECN_CLIENT_QUERY ))
-            {
-                flow->ssn_state.session_flags |= SSNFLAG_ECN_SERVER_REPLY;
-            }
+            FinishServerInit(tdb, tcpssn);
+            if( tcph->are_flags_set( TH_ECE ) && ( flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY ) )
+                flow->set_session_flags( SSNFLAG_ECN_SERVER_REPLY );
 
-            if (flow->ssn_state.session_flags & SSNFLAG_SEEN_CLIENT)
+            if( flow->get_session_flags() & SSNFLAG_SEEN_CLIENT )
             {
                 // should TCP state go to established too?
                 flow->session_state |= STREAM_STATE_ESTABLISHED;
-                flow->ssn_state.session_flags |= SSNFLAG_ESTABLISHED;
-                StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_ESTABLISHED);
+                flow->set_session_flags( SSNFLAG_ESTABLISHED );
+                StreamUpdatePerfBaseState( &sfBase, flow, TCP_STATE_ESTABLISHED );
             }
         }
         if (!flow->inner_server_ttl)
-            flow->set_ttl(p, false);
-    } else
+            flow->set_ttl(tdb->pkt, false);
+    }
+    else
     {
         DebugMessage(DEBUG_STREAM_STATE, "Stream: Updating on packet from client\n");
         /* if we got here we had to see the SYN already... */
-        flow->ssn_state.session_flags |= SSNFLAG_SEEN_CLIENT;
+        flow->set_session_flags( SSNFLAG_SEEN_CLIENT );
         if (tcpssn->tcp_init)
         {
             talker = &tcpssn->client;
@@ -1740,30 +1743,30 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
         if ((flow->session_state & STREAM_STATE_MIDSTREAM) && !(flow->session_state & STREAM_STATE_ESTABLISHED))
         {
             /* Midstream and seen server. */
-            if (flow->ssn_state.session_flags & SSNFLAG_SEEN_SERVER)
+            if (flow->get_session_flags() & SSNFLAG_SEEN_SERVER)
             {
                 flow->session_state |= STREAM_STATE_ESTABLISHED;
-                flow->ssn_state.session_flags |= SSNFLAG_ESTABLISHED;
+                flow->set_session_flags( SSNFLAG_ESTABLISHED );
             }
         }
         if (!flow->inner_client_ttl)
-            flow->set_ttl(p, true);
+            flow->set_ttl(tdb->pkt, true);
     }
 
     /*
      * check for SYN on reset session
      */
-    if ((flow->ssn_state.session_flags & SSNFLAG_RESET) && (p->ptrs.tcph->th_flags & TH_SYN))
+    if( ( flow->get_session_flags() & SSNFLAG_RESET ) && tcph->is_syn() )
     {
-        if (!tcpssn->tcp_init || (listener->s_mgr.state == TCP_STATE_CLOSED)
-                || (talker->s_mgr.state == TCP_STATE_CLOSED))
+        if ( !tcpssn->tcp_init || ( listener->s_mgr.state == TCP_STATE_CLOSED )
+                || ( talker->s_mgr.state == TCP_STATE_CLOSED ) )
         {
             /* Listener previously issued a reset
                Talker is re-SYN-ing */
             // FIXIT-L this leads to bogus 129:20
             TcpSessionCleanup(flow, 1);
 
-            if (p->ptrs.tcph->th_flags & TH_RST)
+            if( tcph->is_rst() )
             {
                 /* FIXIT-M  In inline mode, only one of the normalizations
                  *           can occur.  If the first normalization
@@ -1777,50 +1780,44 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                  */
 
                 /* Got SYN/RST.  We're done. */
-                NormalTrimPayloadIfSyn(p, 0, tdb);
-                NormalTrimPayloadIfRst(p, 0, tdb);
+                listener->normalizer->trim_syn_payload( tdb );
+                listener->normalizer->trim_rst_payload( tdb );
                 MODULE_PROFILE_END(s5TcpStatePerfStats);
                 return retcode | ACTION_RST;
             }
-            else if (p->ptrs.tcph->is_syn_only())
+            else if (tcph->is_syn_only())
             {
                 flow->ssn_state.direction = FROM_CLIENT;
                 flow->session_state = STREAM_STATE_SYN;
-                flow->set_ttl(p, true);
-                NewTcpSessionOnSyn(p, flow, tdb, config);
+                flow->set_ttl(tdb->pkt, true);
+                NewTcpSessionOnSyn( flow, tdb, config);
                 tcpStats.resyns++;
                 new_ssn = 1;
 
                 bool require3Way = config->require_3whs();
-                NormalTrackECN(tcpssn, (TCPHdr*) p->ptrs.tcph, require3Way);
-
-                {
-                    listener = &tcpssn->server;
-                    talker = &tcpssn->client;
-                }
-                flow->ssn_state.session_flags = SSNFLAG_SEEN_CLIENT;
+                listener = &tcpssn->server;
+                talker = &tcpssn->client;
+                listener->normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
+                flow->update_session_flags( SSNFLAG_SEEN_CLIENT );
             }
-            else if (p->ptrs.tcph->is_syn_ack())
+            else if (tcph->is_syn_ack())
             {
-                if (config->midstream_allowed(p))
+                if (config->midstream_allowed(tdb->pkt))
                 {
                     flow->ssn_state.direction = FROM_SERVER;
                     flow->session_state = STREAM_STATE_SYN_ACK;
-                    flow->set_ttl(p, false);
-                    NewTcpSessionOnSynAck(p, flow, tdb, config);
+                    flow->set_ttl(tdb->pkt, false);
+                    NewTcpSessionOnSynAck( flow, tdb, config);
                     tcpStats.resyns++;
                     tcpssn = (TcpSession*) flow->session;
                     new_ssn = 1;
                 }
 
                 bool require3Way = config->require_3whs();
-                NormalTrackECN(tcpssn, (TCPHdr*) p->ptrs.tcph, require3Way);
-
-                {
-                    listener = &tcpssn->client;
-                    talker = &tcpssn->server;
-                }
-                flow->ssn_state.session_flags = SSNFLAG_SEEN_SERVER;
+                listener = &tcpssn->client;
+                talker = &tcpssn->server;
+                listener->normalizer->ecn_tracker( (tcp::TCPHdr *) tcph, require3Way );
+                flow->update_session_flags( SSNFLAG_SEEN_SERVER );
             }
         }
 
@@ -1829,30 +1826,30 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
 
     // FIXIT-L why flush here instead of just purge?
     // s5_ignored_session() may be disabling detection too soon if we really want to flush
-    if (stream.ignored_session(flow, p))
+    if (stream.ignored_session(flow, tdb->pkt))
     {
         if (talker && (talker->flags & TF_FORCE_FLUSH))
         {
-            tcpssn->flush_talker(p);
+            tcpssn->flush_talker(tdb->pkt);
             talker->flags &= ~TF_FORCE_FLUSH;
         }
         if (listener && (listener->flags & TF_FORCE_FLUSH))
         {
-            tcpssn->flush_listener(p);
+            tcpssn->flush_listener(tdb->pkt);
             listener->flags &= ~TF_FORCE_FLUSH;
         }
-        p->packet_flags |= PKT_IGNORE;
+        tdb->pkt->packet_flags |= PKT_IGNORE;
         retcode |= ACTION_DISABLE_INSPECTION;
     }
 
     /* Handle data on SYN */
-    if ((p->dsize) && p->ptrs.tcph->is_syn())
+    if ((tdb->pkt->dsize) && tcph->is_syn())
     {
         /* MacOS accepts data on SYN, so don't alert if policy is MACOS */
         if (talker->os_policy != STREAM_POLICY_MACOS)
         {
             // remove data on SYN
-            NormalTrimPayloadIfSyn(p, 0, tdb);
+            listener->normalizer->trim_syn_payload( tdb );
 
             if (Normalize_GetMode(NORM_TCP_TRIM_SYN) == NORM_MODE_OFF)
             {
@@ -1875,9 +1872,9 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
     DebugFormat(DEBUG_STREAM_STATE, "   %s state: %s(%d)\n", l,  state_names[listener->s_mgr.state], listener->s_mgr.state);
 
     // may find better placement to eliminate redundant flag checks
-    if (p->ptrs.tcph->th_flags & TH_SYN)
+    if( tcph->is_syn() )
         talker->s_mgr.sub_state |= SUB_SYN_SENT;
-    if (p->ptrs.tcph->th_flags & TH_ACK)
+    if( tcph->is_ack() )
         talker->s_mgr.sub_state |= SUB_ACK_SENT;
 
     /*
@@ -1885,7 +1882,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
      */
     if ((TCP_STATE_SYN_SENT == listener->s_mgr.state) && (TCP_STATE_LISTEN == talker->s_mgr.state))
     {
-        if (p->ptrs.tcph->th_flags & TH_ACK)
+        if( tcph->is_ack() )
         {
             /*
              * make sure we've got a valid segment
@@ -1894,25 +1891,25 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
             {
                 DebugMessage(DEBUG_STREAM_STATE,  "Pkt ack is out of bounds, bailing!\n");
                 inc_tcp_discards();
-                NormalTrimPayloadIfWin(p, 0, tdb);
+                listener->normalizer->trim_win_payload( tdb );
                 LogTcpEvents(eventcode);
                 MODULE_PROFILE_END(s5TcpStatePerfStats);
                 return retcode | ACTION_BAD_PKT;
             }
         }
 
-        talker->flags |= StreamGetTcpTimestamp(p, &tdb->ts, 0);
+        talker->flags |= talker->normalizer->get_tcp_timestamp(tdb, false);
         if (tdb->ts == 0)
             talker->flags |= TF_TSTAMP_ZERO;
 
         /*
          * catch resets sent by server
          */
-        if (p->ptrs.tcph->th_flags & TH_RST)
+        if( tcph->is_rst() )
         {
             DebugMessage(DEBUG_STREAM_STATE, "got RST\n");
 
-            NormalTrimPayloadIfRst(p, 0, tdb);
+            listener->normalizer->trim_rst_payload( tdb );
 
             /* Reset is valid when in SYN_SENT if the
              * ack field ACKs the SYN.
@@ -1925,7 +1922,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                  * additional data sent from one side or the other isn't
                  * processed (and is dropped in inline mode).
                  */
-                flow->ssn_state.session_flags |= SSNFLAG_RESET;
+                flow->set_session_flags( SSNFLAG_RESET );
                 talker->s_mgr.state = TCP_STATE_CLOSED;
                 StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_CLOSING);
                 /* Leave listener open, data may be in transit */
@@ -1937,21 +1934,19 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
             DebugMessage(DEBUG_STREAM_STATE, "bad sequence number, bailing\n");
             inc_tcp_discards();
             eventcode |= EVENT_BAD_RST;
-            NormalDropPacketIf(p, NORM_TCP_BLOCK);
+            listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
             LogTcpEvents(eventcode);
             MODULE_PROFILE_END(s5TcpStatePerfStats);
             return retcode;
         }
 
-        /*
-         * finish up server init
-         */
-        if (p->ptrs.tcph->th_flags & TH_SYN)
+        // finish up server init
+        if( tcph->is_syn() )
         {
-            FinishServerInit(p, tdb, tcpssn);
+            FinishServerInit(tdb, tcpssn);
             if (talker->flags & TF_TSTAMP)
             {
-                talker->ts_last_pkt = p->pkth->ts.tv_sec;
+                talker->ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
                 talker->ts_last = tdb->ts;
             }
 
@@ -1962,8 +1957,8 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
             DebugMessage(DEBUG_STREAM_STATE, "Finish server init didn't get called!\n");
         }
 
-        if ((p->ptrs.tcph->th_flags & TH_ECE) && ( flow->ssn_state.session_flags & SSNFLAG_ECN_CLIENT_QUERY) )
-            flow->ssn_state.session_flags |= SSNFLAG_ECN_SERVER_REPLY;
+        if( tcph->are_flags_set( TH_ECE ) && ( flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY ) )
+            flow->set_session_flags( SSNFLAG_ECN_SERVER_REPLY );
 
         /*
          * explicitly set the state
@@ -1981,31 +1976,25 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
      * This is per RFC 1323.
      */
     if ((talker->flags & TF_WSCALE) && (listener->flags & TF_WSCALE))
-    {
         tdb->win <<= talker->wscale;
-    }
 
     /* Check for session hijacking -- compare mac address to the ones
-     * that were recorded at session startup.
-     */
+     * that were recorded at session startup. */
 #ifdef DAQ_PKT_FLAG_PRE_ROUTING
-    if (!(p->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING))
+    if (!(tdb->pkt->pkth->flags & DAQ_PKT_FLAG_PRE_ROUTING))
 #endif
     {
-        eventcode |= ValidMacAddress(talker, listener, p);
+        eventcode |= ValidMacAddress(talker, listener, tdb->pkt);
     }
 
-    /* Check timestamps */
-    ts_action = ValidTimestamp(talker, listener, tdb, p, &eventcode, &got_ts);
+    ts_action = listener->normalizer->handle_paws( tdb, &eventcode, &got_ts );
 
-    /*
-     * check RST validity
-     */
-    if (p->ptrs.tcph->th_flags & TH_RST)
+    // check RST validity
+    if( tcph->is_rst() )
     {
-        NormalTrimPayloadIfRst(p, 0, tdb);
+        listener->normalizer->trim_rst_payload( tdb );
 
-        if (ValidRst(flow, listener, tdb))
+        if (listener->normalizer->validate_rst( tdb ))
         {
             DebugMessage(DEBUG_STREAM_STATE, "Got RST, bailing\n");
 
@@ -2014,13 +2003,13 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                     || listener->s_mgr.state == TCP_STATE_CLOSE_WAIT
                     || listener->s_mgr.state == TCP_STATE_CLOSING)
             {
-                tcpssn->flush_talker(p);
-                tcpssn->flush_listener(p);
+                tcpssn->flush_talker(tdb->pkt);
+                tcpssn->flush_listener(tdb->pkt);
                 tcpssn->set_splitter(true, nullptr);
                 tcpssn->set_splitter(false, nullptr);
                 flow->free_application_data();
             }
-            flow->ssn_state.session_flags |= SSNFLAG_RESET;
+            flow->set_session_flags( SSNFLAG_RESET );
             talker->s_mgr.state = TCP_STATE_CLOSED;
             talker->s_mgr.sub_state |= SUB_RST_SENT;
             StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_CLOSING);
@@ -2039,7 +2028,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
         DebugMessage(DEBUG_STREAM_STATE, "bad sequence number, bailing\n");
         inc_tcp_discards();
         eventcode |= EVENT_BAD_RST;
-        NormalDropPacketIf(p, NORM_TCP_BLOCK);
+        listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
         LogTcpEvents(eventcode);
         MODULE_PROFILE_END(s5TcpStatePerfStats);
         return retcode | ts_action;
@@ -2049,11 +2038,11 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
         /* check for valid seqeuence/retrans */
         if (listener->config->policy != STREAM_POLICY_PROXY
                 and (listener->s_mgr.state >= TCP_STATE_ESTABLISHED)
-                and !ValidSeq(p, flow, listener, tdb))
+                and !ValidSeq(flow, listener, tdb))
         {
             DebugMessage(DEBUG_STREAM_STATE, "bad sequence number, bailing\n");
             inc_tcp_discards();
-            NormalTrimPayloadIfWin(p, 0, tdb);
+            listener->normalizer->trim_win_payload( tdb );
             LogTcpEvents(eventcode);
             MODULE_PROFILE_END(s5TcpStatePerfStats);
             return retcode | ts_action;
@@ -2078,11 +2067,11 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
     if (got_ts && SEQ_EQ(listener->r_win_base, tdb->seq))
     {
         if ((int32_t) (tdb->ts - talker->ts_last) >= 0||
-                (uint32_t)p->pkth->ts.tv_sec >= talker->ts_last_pkt+PAWS_24DAYS)
+                (uint32_t)tdb->pkt->pkth->ts.tv_sec >= talker->ts_last_pkt + PAWS_24DAYS)
         {
             DebugMessage(DEBUG_STREAM_STATE, "updating timestamps...\n");
             talker->ts_last = tdb->ts;
-            talker->ts_last_pkt = p->pkth->ts.tv_sec;
+            talker->ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
         }
     } else
     {
@@ -2092,13 +2081,13 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
     /*
      * check for repeat SYNs
      */
-    if (!new_ssn && ((p->ptrs.tcph->th_flags & (TH_SYN | TH_ACK)) == TH_SYN))
+    if( !new_ssn && tcph->is_syn_only() )
     {
         int action;
-        if (!SEQ_EQ(tdb->seq, talker->isn) && NormalDropPacketIf(p, NORM_TCP_BLOCK))
+        if (!SEQ_EQ(tdb->seq, talker->isn) && listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK))
             action = ACTION_BAD_PKT;
         else if (talker->s_mgr.state >= TCP_STATE_ESTABLISHED)
-            action = RepeatedSyn(listener, talker, tdb, tcpssn);
+            action = listener->normalizer->handle_repeated_syn( tdb );
         else
             action = ACTION_NOTHING;
 
@@ -2123,22 +2112,22 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
             /* got a window too large, alert! */
             eventcode |= EVENT_WINDOW_TOO_LARGE;
             inc_tcp_discards();
-            NormalDropPacketIf(p, NORM_TCP_BLOCK);
+            listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
             LogTcpEvents(eventcode);
             MODULE_PROFILE_END(s5TcpStatePerfStats);
             return retcode | ACTION_BAD_PKT;
         }
-        else if ((p->packet_flags & PKT_FROM_CLIENT) && (tdb->win <= SLAM_MAX)
+        else if ((tdb->pkt->packet_flags & PKT_FROM_CLIENT) && (tdb->win <= SLAM_MAX)
                 && (tdb->ack == listener->isn + 1)
-                && !(p->ptrs.tcph->th_flags & (TH_FIN | TH_RST))
-                && !(flow->ssn_state.session_flags & SSNFLAG_MIDSTREAM))
+                && !( 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! */
             eventcode |= EVENT_WINDOW_SLAM;
             inc_tcp_discards();
 
-            if (NormalDropPacketIf(p, NORM_TCP_BLOCK))
+            if (listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK))
             {
                 LogTcpEvents(eventcode);
                 MODULE_PROFILE_END(s5TcpStatePerfStats);
@@ -2160,10 +2149,8 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
         }
     }
 
-    /*
-     * process ACK flags
-     */
-    if (p->ptrs.tcph->th_flags & TH_ACK)
+    // 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, state_names[listener->s_mgr.state]);
@@ -2177,21 +2164,20 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                 DebugMessage(DEBUG_STREAM_STATE, "listener state is SYN_SENT...\n");
                 if (IsBetween(listener->l_unackd, listener->l_nxt_seq, tdb->ack))
                 {
-                    UpdateSsn(p, listener, talker, tdb);
-                    flow->ssn_state.session_flags |= SSNFLAG_ESTABLISHED;
+                    UpdateSsn(listener, talker, tdb);
+                    flow->set_session_flags( SSNFLAG_ESTABLISHED );
                     flow->session_state |= STREAM_STATE_ESTABLISHED;
                     listener->s_mgr.state = TCP_STATE_ESTABLISHED;
                     talker->s_mgr.state = TCP_STATE_ESTABLISHED;
-                    StreamUpdatePerfBaseState(&sfBase, flow,
-                            TCP_STATE_ESTABLISHED);
+                    StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_ESTABLISHED);
                     /* Indicate this packet completes 3-way handshake */
-                    p->packet_flags |= PKT_STREAM_TWH;
+                    tdb->pkt->packet_flags |= PKT_STREAM_TWH;
                 }
 
                 talker->flags |= got_ts;
                 if (got_ts && SEQ_EQ(listener->r_nxt_ack, tdb->seq))
                 {
-                    talker->ts_last_pkt = p->pkth->ts.tv_sec;
+                    talker->ts_last_pkt = tdb->pkt->pkth->ts.tv_sec;
                     talker->ts_last = tdb->ts;
                 }
 
@@ -2199,11 +2185,11 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
 
             case TCP_STATE_ESTABLISHED:
             case TCP_STATE_CLOSE_WAIT:
-                UpdateSsn(p, listener, talker, tdb);
+                UpdateSsn( listener, talker, tdb);
                 break;
 
             case TCP_STATE_FIN_WAIT_1:
-                UpdateSsn(p, listener, talker, tdb);
+                UpdateSsn(listener, talker, tdb);
 
                 DebugFormat(DEBUG_STREAM_STATE, "tdb->ack %X >= talker->r_nxt_ack %X\n", tdb->ack, talker->r_nxt_ack);
 
@@ -2214,7 +2200,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                         eventcode |= EVENT_WINDOW_SLAM;
                         inc_tcp_discards();
 
-                        if (NormalDropPacketIf(p, NORM_TCP_BLOCK))
+                        if (listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK))
                         {
                             LogTcpEvents(eventcode);
                             MODULE_PROFILE_END(s5TcpStatePerfStats);
@@ -2224,16 +2210,16 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
 
                     listener->s_mgr.state = TCP_STATE_FIN_WAIT_2;
 
-                    if ((p->ptrs.tcph->th_flags & TH_FIN))
+                    if( tcph->is_fin() )
                     {
                         DebugMessage(DEBUG_STREAM_STATE, "seq ok, setting state!\n");
 
                         if (talker->s_mgr.state_queue == TCP_STATE_NONE)
                         {
                             talker->s_mgr.state = TCP_STATE_LAST_ACK;
-                            EndOfFileHandle(p, tcpssn);
+                            EndOfFileHandle(tdb->pkt, tcpssn);
                         }
-                        if (flow->ssn_state.session_flags & SSNFLAG_MIDSTREAM)
+                        if (flow->get_session_flags() & SSNFLAG_MIDSTREAM)
                         {
                             // FIXIT-L this should be handled below in fin section
                             // but midstream sessions fail the seq test
@@ -2254,25 +2240,25 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                 break;
 
             case TCP_STATE_FIN_WAIT_2:
-                UpdateSsn(p, listener, talker, tdb);
+                UpdateSsn(listener, talker, tdb);
                 if (SEQ_GT(tdb->ack, listener->l_nxt_seq))
                 {
                     eventcode |= EVENT_BAD_ACK;
                     LogTcpEvents(eventcode);
-                    NormalDropPacketIf(p, NORM_TCP_BLOCK);
+                    listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
                     MODULE_PROFILE_END(s5TcpStatePerfStats);
                     return retcode | ACTION_BAD_PKT;
                 }
                 break;
 
             case TCP_STATE_CLOSING:
-                UpdateSsn(p, listener, talker, tdb);
+                UpdateSsn(listener, talker, tdb);
                 if (SEQ_GEQ(tdb->end_seq, listener->r_nxt_ack))
                     listener->s_mgr.state = TCP_STATE_TIME_WAIT;
                 break;
 
             case TCP_STATE_LAST_ACK:
-                UpdateSsn(p, listener, talker, tdb);
+                UpdateSsn( listener, talker, tdb);
 
                 if (SEQ_EQ(tdb->ack, listener->l_nxt_seq))
                     listener->s_mgr.state = TCP_STATE_CLOSED;
@@ -2283,13 +2269,13 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                 break;
         }
 
-        CheckFlushPolicyOnAck(tcpssn, talker, listener, p);
+        CheckFlushPolicyOnAck(tcpssn, talker, listener,tdb->pkt);
     }
 
     /*
      * handle data in the segment
      */
-    if (p->dsize)
+    if (tdb->pkt->dsize)
     {
         DebugFormat(DEBUG_STREAM_STATE, "   %s state: %s(%d) getting data\n",
                 l, state_names[listener->s_mgr.state], listener->s_mgr.state);
@@ -2304,13 +2290,13 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
             //EventDataOnClosed(talker->config);
             eventcode |= EVENT_DATA_ON_CLOSED;
             retcode |= ACTION_BAD_PKT;
-            NormalDropPacketIf(p, NORM_TCP_BLOCK);
+            listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
         }
         else if (TCP_STATE_CLOSED == talker->s_mgr.state)
         {
             /* data on a segment when we're not accepting data any more
                alert! */
-            if (flow->ssn_state.session_flags & SSNFLAG_RESET)
+            if (flow->get_session_flags() & SSNFLAG_RESET)
             {
                 //EventDataAfterReset(listener->config);
                 if (talker->s_mgr.sub_state & SUB_RST_SENT)
@@ -2324,7 +2310,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                 eventcode |= EVENT_DATA_ON_CLOSED;
             }
             retcode |= ACTION_BAD_PKT;
-            NormalDropPacketIf(p, NORM_TCP_BLOCK);
+            listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
         }
         else
         {
@@ -2335,7 +2321,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
             {
                 // these normalizations can't be done if we missed setup. and
                 // window is zero in one direction until we've seen both sides.
-                if (!(flow->ssn_state.session_flags & SSNFLAG_MIDSTREAM))
+                if (!(flow->get_session_flags() & SSNFLAG_MIDSTREAM))
                 {
                     // sender of syn w/mss limits payloads from peer
                     // since we store mss on sender side, use listener mss
@@ -2343,36 +2329,33 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                     TcpTracker* st = listener;
 
                     // trim to fit in window and mss as needed
-                    NormalTrimPayloadIfWin(p, (st->r_win_base + st->l_window) - st->r_nxt_ack, tdb);
+                    st->normalizer->trim_win_payload(tdb, (st->r_win_base + st->l_window) - st->r_nxt_ack);
 
                     if (st->mss)
-                        NormalTrimPayloadIfMss(p, st->mss, tdb);
+                        st->normalizer->trim_mss_payload( tdb, st->mss );
 
-                    NormalCheckECN(tcpssn, p);
+                    st->normalizer->ecn_stripper( tdb->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 ((p->ptrs.tcph->th_flags != 0)
+            // 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 == STREAM_POLICY_LINUX)
                     or (config->policy == STREAM_POLICY_PROXY))
             {
-                ProcessTcpData(p, listener, tcpssn, tdb, config);
+                ProcessTcpData( listener, tcpssn, tdb, config);
             }
             else
             {
                 eventcode |= EVENT_DATA_WITHOUT_FLAGS;
-                NormalDropPacketIf(p, NORM_TCP_BLOCK);
+                listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
             }
         }
 
-        CheckFlushPolicyOnData(tcpssn, talker, listener, p);
+        CheckFlushPolicyOnData(tcpssn, talker, listener, tdb->pkt);
     }
 
-    if (p->ptrs.tcph->th_flags & TH_FIN)
+    if( tcph->is_fin() )
     {
         DebugMessage(DEBUG_STREAM_STATE, "Got a FIN...\n");
         DebugFormat(DEBUG_STREAM_STATE,  "   %s state: %s(%d)\n", l, state_names[talker->s_mgr.state], talker->s_mgr.state);
@@ -2404,7 +2387,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                         && (listener->flush_policy != STREAM_FLPOLICY_ON_DATA)
                         && Normalize_IsEnabled(NORM_TCP_IPS))
                 {
-                    p->packet_flags |= PKT_PDU_TAIL;
+                    tdb->pkt->packet_flags |= PKT_PDU_TAIL;
                 }
             }
             switch (talker->s_mgr.state)
@@ -2415,10 +2398,10 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                         talker->s_mgr.state_queue = TCP_STATE_CLOSING;
 
                     talker->s_mgr.state = TCP_STATE_FIN_WAIT_1;
-                    EndOfFileHandle(p, tcpssn);
+                    EndOfFileHandle(tdb->pkt, tcpssn);
 
-                    if (!p->dsize)
-                        CheckFlushPolicyOnData(tcpssn, talker, listener, p);
+                    if (!tdb->pkt->dsize)
+                        CheckFlushPolicyOnData(tcpssn, talker, listener, tdb->pkt);
 
                     StreamUpdatePerfBaseState(&sfBase, tcpssn->flow, TCP_STATE_CLOSING);
                     break;
@@ -2428,8 +2411,8 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                     break;
 
                 case TCP_STATE_FIN_WAIT_1:
-                    if (!p->dsize)
-                        RetransmitHandle(p, tcpssn);
+                    if (!tdb->pkt->dsize)
+                        RetransmitHandle(tdb->pkt, tcpssn);
                     break;
 
                 default:
@@ -2439,7 +2422,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
 
             if ((talker->s_mgr.state == TCP_STATE_FIN_WAIT_1) || (talker->s_mgr.state == TCP_STATE_LAST_ACK))
             {
-                uint32_t end_seq = (flow->ssn_state.session_flags & SSNFLAG_MIDSTREAM)
+                uint32_t end_seq = (flow->get_session_flags() & SSNFLAG_MIDSTREAM)
                     ? tdb->end_seq - 1 : tdb->end_seq;
 
                 if ((listener->s_mgr.expected_flags == TH_ACK) && SEQ_GEQ(end_seq, listener->s_mgr.transition_seq))
@@ -2447,7 +2430,7 @@ static int ProcessTcp(Flow* flow, Packet* p, TcpDataBlock* tdb, StreamTcpConfig*
                     DebugMessage(DEBUG_STREAM_STATE, "FIN beyond previous, ignoring\n");
                     eventcode |= EVENT_BAD_FIN;
                     LogTcpEvents(eventcode);
-                    NormalDropPacketIf(p, NORM_TCP_BLOCK);
+                    listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
                     MODULE_PROFILE_END(s5TcpStatePerfStats);
                     return retcode | ACTION_BAD_PKT;
                 }
@@ -2481,28 +2464,23 @@ dupfin:
     DebugFormat(DEBUG_STREAM_STATE, "   %s [talker] state: %s\n", t, state_names[talker->s_mgr.state]);
     DebugFormat(DEBUG_STREAM_STATE, "   %s state: %s(%d)\n", l, state_names[listener->s_mgr.state], listener->s_mgr.state);
 
-    /*
-     * handle TIME_WAIT timer stuff
-     */
+    // handle TIME_WAIT timer stuff
     if ((talker->s_mgr.state == TCP_STATE_TIME_WAIT && listener->s_mgr.state == TCP_STATE_CLOSED)
             || (listener->s_mgr.state == TCP_STATE_TIME_WAIT && talker->s_mgr.state == TCP_STATE_CLOSED)
             || (listener->s_mgr.state == TCP_STATE_TIME_WAIT && talker->s_mgr.state ==  TCP_STATE_TIME_WAIT))
     {
-        // The last ACK is a part of the session.
-        // Delete the session after processing is complete.
+        // The last ACK is a part of the session. Delete the session after processing is complete.
         LogTcpEvents(eventcode);
-        TcpSessionCleanup(flow, 0, p);
+        TcpSessionCleanup(flow, 0, tdb->pkt);
         flow->session_state |= STREAM_STATE_CLOSED;
         MODULE_PROFILE_END(s5TcpStatePerfStats);
         return retcode | ACTION_LWSSN_CLOSED;
     }
-    else if (listener->s_mgr.state == TCP_STATE_CLOSED && talker->s_mgr.state == TCP_STATE_SYN_SENT)
+    else if( listener->s_mgr.state == TCP_STATE_CLOSED
+             && talker->s_mgr.state == TCP_STATE_SYN_SENT )
     {
-        if ( ( p->ptrs.tcph->th_flags & TH_SYN )  && !(p->ptrs.tcph->th_flags & TH_ACK)
-                && !(p->ptrs.tcph->th_flags & TH_RST))
-        {
-            flow->set_expire(p, config->session_timeout);
-        }
+        if( tcph->is_syn_only() )
+            flow->set_expire(tdb->pkt, config->session_timeout);
     }
 
     LogTcpEvents(eventcode);
@@ -2574,7 +2552,7 @@ void TcpSession::cleanup()
 
 void TcpSession::clear()
 {
-    if (tcp_init)
+    if( tcp_init )
         // this does NOT flush data
         TcpSessionClear(flow, this, 1);
 }
@@ -3067,7 +3045,7 @@ midstream_pickup_allowed: if (!p->ptrs.tcph->is_syn_ack()
     if (stream.expired_session(flow, p))
     {
         /* Session is timed out */
-        if (flow->ssn_state.session_flags & SSNFLAG_RESET)
+        if (flow->get_session_flags() & SSNFLAG_RESET)
         {
             /* If this one has been reset, delete the TCP
              * portion, and start a new. */
@@ -3083,7 +3061,7 @@ midstream_pickup_allowed: if (!p->ptrs.tcph->is_syn_ack()
         tcpStats.timeouts++;
     }
 
-    status = ProcessTcp(flow, p, &tdb, config);
+    status = ProcessTcp(flow, &tdb, config);
 
     DebugMessage(DEBUG_STREAM_STATE, "Finished Stream TCP cleanly!\n---------------------------------------------------\n");
 
index fa56049f56229d8a57b9c97808139f094faf399c..84de55bf50d652b8ba58703d15ed287c06166e74 100644 (file)
@@ -28,6 +28,8 @@
 #include "stream/paf.h"
 #include "flow/session.h"
 
+class TcpNormalizer;
+
 // TBD-EDM - these includes are for functions moved to a new file to group related functionality
 // in specific files ... these functional groups will be further refactored as the stream tcp
 // rewrite continues...
@@ -134,6 +136,7 @@ struct TcpTracker
     uint32_t xtradata_mask; /* extra data available to log */
 
     uint16_t os_policy;
+    TcpNormalizer* normalizer;
     uint16_t reassembly_policy;
 
     uint16_t wscale; /* window scale setting */