]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2426 in SNORT/snort3 from ~DAVMCPHE/snort3:stream_tcp_fixits...
authorRuss Combs (rucombs) <rucombs@cisco.com>
Thu, 17 Sep 2020 17:50:55 +0000 (17:50 +0000)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Thu, 17 Sep 2020 17:50:55 +0000 (17:50 +0000)
Squashed commit of the following:

commit 13038c9f32725d9286103fca639511b3d236378d
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Wed Sep 16 16:55:38 2020 -0400

    stream_tcp: refactor tcp handling of no flags to drop packet before any processing, don't generate event

commit 3e19864b0c21b1a08295e8d0c935cfb29d216d91
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Mon Sep 14 09:22:40 2020 -0400

    stream_tcp: updates to resolve PR review comments

commit 0d05172e8d97fc8c98105ec7636a258e9a1d7f8a
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Wed Sep 9 10:05:01 2020 -0400

    stream_tcp: merge the setup methods of the TcpStreamSession and TcpSession classes into a single method in TcpSession

commit df18ba9cdd09abe0400ae41820d2f1d4ca688068
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Wed Aug 26 09:33:15 2020 -0400

    stream_tcp: add PegCount for tcp packets received with an invalid ack

commit ac9f49387302084104403c3c0a490741bd00fe92
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Wed Aug 26 09:14:27 2020 -0400

    stream_tcp: delete unused packet action flags, set action flags via its setter

commit bd0cf57e31549ec2fc9eb82cf4f3d276e0bd8db9
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Wed Aug 26 08:09:31 2020 -0400

    stream_tcp: delete redundant calls to flush data when FIN is received

commit 3280c0ba1d11d045459483d741ab8b81031ca070
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Thu Aug 13 10:34:15 2020 -0400

    stream_tcp: handle bad tcp packets consistently when normalizing in ips mode

commit 3058628b9d04b8e513c92e63ee20265fb76f3f97
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Tue Aug 11 16:04:18 2020 -0400

    stream_tcp: add an assert to catch tcp state/event combination that should not occur

commit 0f383f759e850602e17e12ea6fd78f35b31a81c0
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Tue Aug 11 15:55:40 2020 -0400

    stream_tcp: remove FIXIT-H to add ack validation, the ack is already validated when processed on the listener side

commit 7570270137e4ee288ab892a81305dc2cc4671849
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Tue Aug 11 15:43:52 2020 -0400

    stream_tcp: implement helper function to return true if the TCP packet is a data segment, false otherwise

commit acd13bf5378f9f80c4d757ef710c4d104d77d714
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Tue Aug 11 15:21:46 2020 -0400

    stream_tcp: this FIXIT-H has been removed because by definition an Ack Sent event in TcpStateNone means the SYN-ACK was not seen, so no way to do the check suggested

commit b4ebcb37e6c2045b0f78bd4e12f1d2b3eb337353
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Mon Aug 10 10:02:02 2020 -0400

    stream_tcp: arrange TCP tracker member vars to optimize storage requirements, add helper functions to access private splitter functions

    stream_tcp: refactor tracker and reassembler classes to improve encapsulation and move member variables to appropriate class

commit ce9d8536c14011dc4dc33f43d33259a76c0f6e9d
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Tue Jul 21 13:31:28 2020 -0400

    stream_tcp: fix issues with stream_tcp handling of the TCP MSS option

34 files changed:
src/stream/tcp/held_packet_queue.cc
src/stream/tcp/ips_stream_reassemble.cc
src/stream/tcp/segment_overlap_editor.h
src/stream/tcp/stream_tcp.cc
src/stream/tcp/tcp_debug_trace.h
src/stream/tcp/tcp_defs.h
src/stream/tcp/tcp_event_logger.h
src/stream/tcp/tcp_module.cc
src/stream/tcp/tcp_module.h
src/stream/tcp/tcp_normalizer.cc
src/stream/tcp/tcp_normalizers.cc
src/stream/tcp/tcp_reassembler.cc
src/stream/tcp/tcp_reassembler.h
src/stream/tcp/tcp_reassemblers.h
src/stream/tcp/tcp_segment_descriptor.h
src/stream/tcp/tcp_session.cc
src/stream/tcp/tcp_state_close_wait.cc
src/stream/tcp/tcp_state_closed.cc
src/stream/tcp/tcp_state_closing.cc
src/stream/tcp/tcp_state_established.cc
src/stream/tcp/tcp_state_fin_wait1.cc
src/stream/tcp/tcp_state_fin_wait2.cc
src/stream/tcp/tcp_state_handler.cc
src/stream/tcp/tcp_state_handler.h
src/stream/tcp/tcp_state_last_ack.cc
src/stream/tcp/tcp_state_listen.cc
src/stream/tcp/tcp_state_none.cc
src/stream/tcp/tcp_state_syn_recv.cc
src/stream/tcp/tcp_state_syn_sent.cc
src/stream/tcp/tcp_state_time_wait.cc
src/stream/tcp/tcp_stream_session.cc
src/stream/tcp/tcp_stream_session.h
src/stream/tcp/tcp_stream_tracker.cc
src/stream/tcp/tcp_stream_tracker.h

index 889a3f25e2a2dd4725dbee4bc3a3d47ff8f4bbdf..1b4d6dcc901b9cb084e5940d45fbf4fdfc8cf5b2 100644 (file)
@@ -43,8 +43,7 @@ void HeldPacket::adjust_expiration(const timeval& delta, bool up)
 
 HeldPacket::HeldPacket(DAQ_Msg_h msg, uint32_t seq, const timeval& exp, TcpStreamTracker& trk)
     : daq_msg(msg), seq_num(seq), expiration(exp), tracker(trk), expired(false)
-{
-}
+{ }
 
 HeldPacketQueue::iter_t HeldPacketQueue::append(DAQ_Msg_h msg, uint32_t seq,
     TcpStreamTracker& trk)
@@ -69,7 +68,6 @@ bool HeldPacketQueue::execute(const timeval& cur_time, int max_remove)
         auto held_packet = q.begin();
         if ( held_packet->has_expired(cur_time) )
         {
-            assert(held_packet == held_packet->get_tracker().held_packet);
             held_packet->get_tracker().perform_partial_flush();
             tcpStats.held_packet_timeouts++;
         }
index 64d9c4ecbf286db97dc8801b85949246a4b33851..e491cd4376ceaec73195fd0a91a01cb95d1850cd 100644 (file)
@@ -117,13 +117,13 @@ IpsOption::EvalStatus ReassembleOption::eval(Cursor&, Packet* pkt)
         {
             if ( srod.direction & SSN_DIR_FROM_SERVER )
             {
-                tcpssn->server.flush_policy = STREAM_FLPOLICY_IGNORE;
+                tcpssn->server.set_flush_policy(STREAM_FLPOLICY_IGNORE);
                 Stream::set_splitter(lwssn, true);
             }
 
             if ( srod.direction & SSN_DIR_FROM_CLIENT )
             {
-                tcpssn->client.flush_policy = STREAM_FLPOLICY_IGNORE;
+                tcpssn->client.set_flush_policy(STREAM_FLPOLICY_IGNORE);
                 Stream::set_splitter(lwssn, false);
             }
         }
@@ -133,13 +133,13 @@ IpsOption::EvalStatus ReassembleOption::eval(Cursor&, Packet* pkt)
             // FIXIT-M PAF need to check for ips / on-data
             if ( srod.direction & SSN_DIR_FROM_SERVER )
             {
-                tcpssn->server.flush_policy = STREAM_FLPOLICY_ON_ACK;
+                tcpssn->server.set_flush_policy(STREAM_FLPOLICY_ON_ACK);
                 Stream::set_splitter(lwssn, true, new AtomSplitter(true));
             }
 
             if ( srod.direction & SSN_DIR_FROM_CLIENT )
             {
-                tcpssn->client.flush_policy = STREAM_FLPOLICY_ON_ACK;
+                tcpssn->client.set_flush_policy(STREAM_FLPOLICY_ON_ACK);
                 Stream::set_splitter(lwssn, false, new AtomSplitter(false));
             }
         }
@@ -319,7 +319,7 @@ TEST_CASE("IPS Stream Reassemble", "[ips_stream_reassemble][stream_tcp]")
         StreamSplitter* ss = Stream::get_splitter(flow, true);
         CHECK( ( ss != nullptr ) );
         CHECK( ( !ss->is_paf() ) );
-        CHECK( ( ( ( TcpSession* )pkt->flow->session)->server.flush_policy
+        CHECK( ( ( ( TcpSession* )pkt->flow->session)->server.get_flush_policy()
             == STREAM_FLPOLICY_IGNORE ) );
     }
 #endif
index 116151ebd29b9980c04e92495bd9d334270ecf54..ee7f0688c4f101ec47c706a9e13b3f1fac124327 100644 (file)
@@ -23,6 +23,7 @@
 #define SEGMENT_OVERLAP_EDITOR_H
 
 #include "normalize/normalize.h"
+#include "stream/paf.h"
 #include "tcp_segment_node.h"
 
 class TcpSession;
@@ -37,8 +38,6 @@ struct SegmentOverlapState
     const uint8_t* rdata;
 
     TcpSegmentList seglist;
-    StreamPolicy reassembly_policy;
-
     uint32_t seglist_base_seq;      /* seq of first queued segment */
     uint32_t seg_count;             /* number of current queued segments */
     uint32_t seg_bytes_total;       /* total bytes currently queued */
@@ -58,6 +57,7 @@ struct SegmentOverlapState
     uint16_t len;
     uint16_t rsize;
     int8_t tcp_ips_data;
+    StreamPolicy reassembly_policy;
 
     bool keep_segment;
 
@@ -68,15 +68,31 @@ struct SegmentOverlapState
     void init_soe(TcpSegmentDescriptor& tsd, TcpSegmentNode* left, TcpSegmentNode* right);
 };
 
+/* Only track a maximum number of alerts per session */
+#define MAX_SESSION_ALERTS 8
+struct StreamAlertInfo
+{
+    /* For storing alerts that have already been seen on the session */
+    uint32_t gid;
+    uint32_t sid;
+    uint32_t seq;
+    // if we log extra data, event_* is used to correlate with alert
+    uint32_t event_id;
+    uint32_t event_second;
+};
+
 struct TcpReassemblerState
 {
     SegmentOverlapState sos;
     TcpStreamTracker* tracker;
     uint32_t flush_count;   // number of flushed queued segments
     uint32_t xtradata_mask; // extra data available to log
-    bool server_side;
+    StreamAlertInfo alerts[MAX_SESSION_ALERTS];
+    uint8_t alert_count = 0;
     uint8_t ignore_dir;
     uint8_t packet_dir;
+    bool server_side;
+    PAF_State paf_state;
 };
 
 class SegmentOverlapEditor
index 59a5894f651df6b969e6eac640523e3de033ebc2..563ca56dd05cf344a4457caba7591f942dc2e739 100644 (file)
@@ -141,8 +141,8 @@ static const InspectApi tcp_api =
         0,
         API_RESERVED,
         API_OPTIONS,
-        MOD_NAME,
-        MOD_HELP,
+        STREAM_TCP_MOD_NAME,
+        STREAM_TCP_MOD_HELP,
         mod_ctor,
         mod_dtor
     },
index bc8253825a257f0b12bef7805aaed7a764c880da..21c2a6b65424c4265d990bb68b47797d07def234 100644 (file)
@@ -89,11 +89,11 @@ inline void TraceState(TcpStreamTracker& a, TcpStreamTracker& b, const char* s)
         RMT(a, rcv_nxt, b), RMT(a, r_win_base, b), a.get_iss(), a.get_irs());
 
     fprintf(stdout, "\n");
-    unsigned paf = (a.splitter and a.splitter->is_paf()) ? 2 : 0;
-    unsigned fpt = a.flush_policy ? 192 : 0;
+    unsigned paf = ( a.is_splitter_paf() ) ? 2 : 0;
+    unsigned fpt = a.get_flush_policy() ? 192 : 0;
 
     fprintf(stdout, "           FP=%s:%-4u SC=%-4u FL=%-4u SL=%-5u BS=%-4u",
-        flushxt[a.flush_policy + paf], fpt,
+        flushxt[a.get_flush_policy() + paf], fpt,
         a.reassembler.get_seg_count(), a.reassembler.get_flush_count(),
         a.reassembler.get_seg_bytes_logical(),
         a.reassembler.get_seglist_base_seq() - b.get_iss());
index 23af99b072d1e96b2340456a0c96d66b02737b9b..9193079d579de8265c5919496e70efd41d125bac 100644 (file)
@@ -31,18 +31,10 @@ struct Packet;
 
 /* actions */
 #define ACTION_NOTHING               0x00000000
-#define ACTION_FLUSH_SENDER_STREAM   0x00000001
-#define ACTION_FLUSH_RECEIVER_STREAM 0x00000002
-#define ACTION_DROP_SESSION          0x00000004
-#define ACTION_ACK_SENDER_DATA       0x00000008
-#define ACTION_ACK_RECEIVER_DATA     0x00000010
-#define ACTION_SET_SSN               0x00000040
-#define ACTION_COMPLETE_TWH          0x00000080
-#define ACTION_RST                   0x00000100
-#define ACTION_BAD_SEQ               0x00000200
-#define ACTION_BAD_PKT               0x00000400
-#define ACTION_LWSSN_CLOSED          0x00000800
-#define ACTION_DISABLE_INSPECTION    0x00001000
+#define ACTION_RST                   0x00000001
+#define ACTION_BAD_PKT               0x00000002
+#define ACTION_LWSSN_CLOSED          0x00000004
+#define ACTION_DISABLE_INSPECTION    0x00000008
 
 #define TF_NONE             0x0000
 #define TF_WSCALE           0x0001
index af8ac2f58ad65f721170d688c0ca5e3d7338bebe..9c086962f59dfd397135eae102b54358efa7be1c 100644 (file)
@@ -52,16 +52,11 @@ public:
     TcpEventLogger() = default;
 
     void clear_tcp_events()
-    {
-        tcp_events = 0;
-    }
+    { tcp_events = 0; }
 
     void set_tcp_event(int eventcode)
-    {
-        tcp_events |= eventcode;
-    }
+    { tcp_events |= eventcode; }
 
-    void set_tcp_internal_syn_event();
     void log_tcp_events();
     void log_internal_event(uint32_t eventSid);
 
index 3cc1bac50c963dccf6e84e2089f529b9c95ec53b..cfc7712699909b723a220254932bf7339afc4ea0 100644 (file)
@@ -44,6 +44,10 @@ const PegInfo tcp_pegs[] =
     { CountType::SUM, "restarts", "sessions restarted" },
     { CountType::SUM, "resyns", "SYN received on established session" },
     { CountType::SUM, "discards", "tcp packets discarded" },
+    { CountType::SUM, "discards_skipped", "tcp packet discards skipped due to normalization disabled" },
+    { CountType::SUM, "invalid_seq_num", "tcp packets received with an invalid sequence number" },
+    { CountType::SUM, "invalid_ack", "tcp packets received with an invalid ack number" },
+    { CountType::SUM, "no_flags_set", "tcp packets received with no TCP flags set" },
     { CountType::SUM, "events", "events generated" },
     { CountType::SUM, "ignored", "tcp packets ignored" },
     { CountType::SUM, "untracked", "tcp packets not tracked" },
@@ -64,6 +68,7 @@ const PegInfo tcp_pegs[] =
         "number of times the maximum queued segment limit was reached" },
     { CountType::SUM, "exceeded_max_bytes",
         "number of times the maximum queued byte limit was reached" },
+    { CountType::SUM, "payload_fully_trimmed", "segments with no data after trimming" },
     { CountType::SUM, "internal_events", "135:X events generated" },
     { CountType::SUM, "client_cleanups",
         "number of times data from server was flushed when session released" },
@@ -229,7 +234,7 @@ static const RuleMap stream_tcp_rules[] =
 };
 
 StreamTcpModule::StreamTcpModule() :
-    Module(MOD_NAME, MOD_HELP, s_params)
+    Module(STREAM_TCP_MOD_NAME, STREAM_TCP_MOD_HELP, s_params)
 {
     config = nullptr;
 }
@@ -243,7 +248,7 @@ ProfileStats* StreamTcpModule::get_profile(
     switch ( index )
     {
     case 0:
-        name = MOD_NAME;
+        name = STREAM_TCP_MOD_NAME;
         parent = nullptr;
         return &s5TcpPerfStats;
 
index c87706e1c176e52f76fad568a2e8d0ef91a73320..f651e3bb62bbaf6b707fd0a7dddbdb8db862340b 100644 (file)
@@ -52,7 +52,6 @@
 extern const PegInfo tcp_pegs[];
 
 extern THREAD_LOCAL snort::ProfileStats s5TcpPerfStats;
-extern THREAD_LOCAL snort::ProfileStats streamSizePerfStats;
 
 struct TcpStats
 {
@@ -62,6 +61,10 @@ struct TcpStats
     PegCount restarts;
     PegCount resyns;
     PegCount discards;
+    PegCount discards_skipped;
+    PegCount invalid_seq_num;
+    PegCount invalid_ack;
+    PegCount no_flags_set;
     PegCount events;
     PegCount ignored;
     PegCount no_pickups;
@@ -80,6 +83,7 @@ struct TcpStats
     PegCount gaps;
     PegCount exceeded_max_segs;
     PegCount exceeded_max_bytes;
+    PegCount payload_fully_trimmed;
     PegCount internalEvents;
     PegCount client_cleanups;
     PegCount server_cleanups;
@@ -108,17 +112,12 @@ struct TcpStats
 
 extern THREAD_LOCAL struct TcpStats tcpStats;
 
-inline void inc_tcp_discards()
-{
-    tcpStats.discards++;
-}
-
 //-------------------------------------------------------------------------
 // stream_tcp module
 //-------------------------------------------------------------------------
 
-#define MOD_NAME "stream_tcp"
-#define MOD_HELP "stream inspector for TCP flow tracking and stream normalization and reassembly"
+#define STREAM_TCP_MOD_NAME "stream_tcp"
+#define STREAM_TCP_MOD_HELP "stream inspector for TCP flow tracking and stream normalization and reassembly"
 
 namespace snort
 {
index a269441fc097c34d6f457f8837443cb8befe3e59..1d848d4ad0d7b95418c50c77e0fc057972287568 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "tcp_normalizer.h"
 
+#include "tcp_module.h"
 #include "tcp_stream_session.h"
 #include "tcp_stream_tracker.h"
 
@@ -57,8 +58,7 @@ NormPegs TcpNormalizer::get_normalization_counts(unsigned& c)
 }
 
 void TcpNormalizer::trim_payload(
-    TcpNormalizerState&,
-    TcpSegmentDescriptor& tsd, uint32_t max, NormMode mode, TcpPegCounts peg)
+    TcpNormalizerState&, TcpSegmentDescriptor& tsd, uint32_t max, NormMode mode, TcpPegCounts peg)
 {
     if (mode == NORM_MODE_ON)
     {
@@ -72,8 +72,7 @@ void TcpNormalizer::trim_payload(
 }
 
 bool TcpNormalizer::strip_tcp_timestamp(
-    TcpNormalizerState&,
-    TcpSegmentDescriptor& tsd, const tcp::TcpOption* opt, NormMode mode)
+    TcpNormalizerState&, TcpSegmentDescriptor& tsd, const tcp::TcpOption* opt, NormMode mode)
 {
     tcp_norm_stats[PC_TCP_TS_NOP][mode]++;
 
@@ -98,9 +97,11 @@ bool TcpNormalizer::packet_dropper(
     if (mode == NORM_MODE_ON)
     {
         tsd.drop_packet();
+        tcpStats.discards++;
         return true;
     }
 
+    tcpStats.discards_skipped++;
     return false;
 }
 
@@ -282,7 +283,6 @@ int TcpNormalizer::validate_paws_timestamp(
         else
         {
             /* bail, we've got a packet outside the PAWS window! */
-            //inc_tcp_discards();
             tns.session->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
             packet_dropper(tns, tsd, NORM_TCP_OPT);
             return ACTION_BAD_PKT;
@@ -293,7 +293,6 @@ int TcpNormalizer::validate_paws_timestamp(
         PAWS_24DAYS ) )
     {
         /* this packet is from way too far into the future */
-        //inc_tcp_discards();
         tns.session->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
         packet_dropper(tns, tsd, NORM_TCP_OPT);
         return ACTION_BAD_PKT;
@@ -358,6 +357,7 @@ int TcpNormalizer::handle_paws_no_timestamps(
             ( tns.tracker->get_tf_flags() & TF_TSTAMP ) )
         {
             tns.session->tel.set_tcp_event(EVENT_BAD_TIMESTAMP);
+            packet_dropper(tns, tsd, NORM_TCP_BLOCK);
             return ACTION_BAD_PKT;
         }
     }
index e6515712c2488ab68b5c917a7cb2392958ca35e6..5303ba19293ed0cf87d8f9b7f5389524437cba34 100644 (file)
@@ -193,10 +193,7 @@ static inline int handle_repeated_syn_mswin(
         return ACTION_RST;
     }
     else
-    {
-        inc_tcp_discards();
         return ACTION_NOTHING;
-    }
 }
 
 static inline int handle_repeated_syn_bsd(
@@ -210,10 +207,7 @@ static inline int handle_repeated_syn_bsd(
         return ACTION_RST;
     }
     else
-    {
-        inc_tcp_discards();
         return ACTION_NOTHING;
-    }
 }
 
 // Linux, Win2k3 et al.  do not support timestamps if the 3whs used a 0 timestamp.
@@ -337,7 +331,6 @@ int TcpNormalizerMacOS::handle_repeated_syn(
     TcpNormalizerState&, TcpSegmentDescriptor&)
 {
     /* MACOS ignores a 2nd SYN, regardless of the sequence number. */
-    inc_tcp_discards();
     return ACTION_NOTHING;
 }
 
index e85dace90a1105bb386c0fe345654bc2efe780a2..222089b49783a83460c7acfda29a2c9489ae3cba 100644 (file)
@@ -123,11 +123,10 @@ bool TcpReassembler::flush_data_ready(TcpReassemblerState& trs)
 {
     // needed by stream_reassemble:action disable; can fire on rebuilt
     // packets, yanking the splitter out from under us :(
-    if (!trs.tracker->flush_policy or !trs.tracker->splitter)
+    if ( !trs.tracker->is_reassembly_enabled() )
         return false;
 
-    if ( (trs.tracker->flush_policy == STREAM_FLPOLICY_ON_DATA) or
-        trs.tracker->splitter->is_paf() )
+    if ( (trs.tracker->get_flush_policy() == STREAM_FLPOLICY_ON_DATA) or trs.tracker->is_splitter_paf() )
         return ( is_segment_pending_flush(trs) );
 
     return ( get_pending_segment_count(trs, 2) > 1 );  // FIXIT-L return false?
@@ -205,10 +204,10 @@ void TcpReassembler::add_reassembly_segment(
     const int32_t new_size = len - slide - trunc_len;
     assert(new_size >= 0);
 
+    // if trimming will delete all data, don't insert this segment in the queue
     if ( new_size <= 0 )
     {
-        // Zero size data because of trimming. Don't insert it.
-        inc_tcp_discards();
+        tcpStats.payload_fully_trimmed++;
         trs.tracker->normalizer.trim_win_payload(tsd);
         return;
     }
@@ -248,17 +247,69 @@ void TcpReassembler::dup_reassembly_segment(
     *retSeg = tsn;
 }
 
+bool TcpReassembler::add_alert(TcpReassemblerState& trs, uint32_t gid, uint32_t sid)
+{
+    if ( trs.alert_count >= MAX_SESSION_ALERTS)
+        return false;
+
+    StreamAlertInfo* ai = trs.alerts + trs.alert_count;
+    ai->gid = gid;
+    ai->sid = sid;
+    ai->seq = 0;
+    ai->event_id = 0;
+    ai->event_second = 0;
+
+    trs.alert_count++;
+
+    return true;
+}
+
+bool TcpReassembler::check_alerted(TcpReassemblerState& trs, uint32_t gid, uint32_t sid)
+{
+    for (int i = 0; i < trs.alert_count; i++)
+    {
+        /*  This is a rebuilt packet and if we've seen this alert before,
+         *  return that we have previously alerted on original packet.
+         */
+        if (trs.alerts[i].gid == gid && trs.alerts[i].sid == sid)
+            return true;
+    }
+
+    return false;
+}
+
+int TcpReassembler::update_alert(TcpReassemblerState& trs, uint32_t gid, uint32_t sid,
+    uint32_t event_id, uint32_t event_second)
+{
+    // FIXIT-M comparison of seq_num is wrong, compare value is always 0, should be seq_num of wire packet
+    uint32_t seq_num = 0;
+
+    for (unsigned i = 0; i < trs.alert_count; i++)
+    {
+        StreamAlertInfo* ai = &trs.alerts[i];
+
+        if (ai->gid == gid && ai->sid == sid && SEQ_EQ(ai->seq, seq_num))
+        {
+            ai->event_id = event_id;
+            ai->event_second = event_second;
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
 void TcpReassembler::purge_alerts(TcpReassemblerState& trs)
 {
     Flow* flow = trs.sos.session->flow;
 
-    for (int i = 0; i < trs.tracker->alert_count; i++)
+    for (int i = 0; i < trs.alert_count; i++)
     {
-        StreamAlertInfo* ai = trs.tracker->alerts + i;
+        StreamAlertInfo* ai = trs.alerts + i;
         Stream::log_extra_data(flow, trs.xtradata_mask, ai->event_id, ai->event_second);
     }
     if ( !flow->is_suspended() )
-        trs.tracker->alert_count = 0;
+        trs.alert_count = 0;
 }
 
 void TcpReassembler::purge_to_seq(TcpReassemblerState& trs, uint32_t flush_seq)
@@ -377,7 +428,7 @@ uint32_t TcpReassembler::get_flush_data_len(
     unsigned int flush_len = ( tsn->c_len <= max ) ? tsn->c_len : max;
 
     // copy only to flush point
-    if ( paf_active(&trs.tracker->paf_state) && SEQ_GT(tsn->c_seq + flush_len, to_seq) )
+    if ( paf_active(&trs.paf_state) && SEQ_GT(tsn->c_seq + flush_len, to_seq) )
         flush_len = to_seq - tsn->c_seq;
 
     return flush_len;
@@ -397,16 +448,16 @@ int TcpReassembler::flush_data_segments(
         TcpSegmentNode* tsn = trs.sos.seglist.cur_rseg;
         unsigned bytes_copied = 0;
         unsigned bytes_to_copy = get_flush_data_len(
-            trs, tsn, to_seq, trs.tracker->splitter->max(p->flow));
+            trs, tsn, to_seq, trs.tracker->get_splitter()->max(p->flow));
         assert(bytes_to_copy);
 
         if ( !tsn->next or (bytes_to_copy < tsn->c_len) or
             SEQ_EQ(tsn->c_seq + bytes_to_copy, to_seq) or
-            (total_flushed + tsn->c_len > trs.tracker->splitter->get_max_pdu()) )
+            (total_flushed + tsn->c_len > trs.tracker->get_splitter()->get_max_pdu()) )
         {
             flags |= PKT_PDU_TAIL;
         }
-        const StreamBuffer sb = trs.tracker->splitter->reassemble(
+        const StreamBuffer sb = trs.tracker->get_splitter()->reassemble(
             trs.sos.session->flow, total, total_flushed, tsn->payload(),
             bytes_to_copy, flags, bytes_copied);
 
@@ -546,8 +597,8 @@ int TcpReassembler::_flush_to_seq(
         if ( footprint > Packet::max_dsize )    // max stream buffer size
             footprint = Packet::max_dsize;
 
-        if ( trs.tracker->splitter->is_paf() and
-            ( trs.tracker->get_tf_flags() & TF_MISSING_PREV_PKT ) )
+        if ( trs.tracker->is_splitter_paf()
+            and ( trs.tracker->get_tf_flags() & TF_MISSING_PREV_PKT ) )
             fallback(*trs.tracker, trs.server_side);
 
         Packet* pdu = initialize_pdu(trs, p, pkt_flags, trs.sos.seglist.cur_rseg->tv);
@@ -583,8 +634,8 @@ int TcpReassembler::_flush_to_seq(
         }
 
         // FIXIT-L must check because above may clear trs.sos.session
-        if ( trs.tracker->splitter )
-            trs.tracker->splitter->update();
+        if ( trs.tracker->get_splitter() )
+            trs.tracker->get_splitter()->update();
 
         // FIXIT-L abort should be by PAF callback only since recovery may be possible
         if ( trs.tracker->get_tf_flags() & TF_MISSING_PKT )
@@ -612,7 +663,7 @@ int TcpReassembler::flush_to_seq(
         return 0;
 
     if ( !flush_data_ready(trs) and !(trs.tracker->get_tf_flags() & TF_FORCE_FLUSH) and
-        !trs.tracker->splitter->is_paf() )
+        !trs.tracker->is_splitter_paf() )
         return 0;
 
     trs.tracker->clear_tf_flags(TF_MISSING_PKT | TF_MISSING_PREV_PKT);
@@ -643,7 +694,7 @@ int TcpReassembler::do_zero_byte_flush(TcpReassemblerState& trs, Packet* p, uint
 {
     unsigned bytes_copied = 0;
 
-    const StreamBuffer sb = trs.tracker->splitter->reassemble(
+    const StreamBuffer sb = trs.tracker->get_splitter()->reassemble(
         trs.sos.session->flow, 0, 0, nullptr, 0, (PKT_PDU_HEAD | PKT_PDU_TAIL), bytes_copied);
 
      if ( sb.data )
@@ -658,8 +709,8 @@ int TcpReassembler::do_zero_byte_flush(TcpReassemblerState& trs, Packet* p, uint
         show_rebuilt_packet(trs, pdu);
         Analyzer::get_local_analyzer()->inspect_rebuilt(pdu);
 
-        if ( trs.tracker->splitter )
-            trs.tracker->splitter->update();
+        if ( trs.tracker->get_splitter() )
+            trs.tracker->get_splitter()->update();
      }
 
      return bytes_copied;
@@ -706,7 +757,7 @@ uint32_t TcpReassembler::get_q_sequenced(TcpReassemblerState& trs)
         trs.sos.seglist.cur_rseg = tsn;
     }
     uint32_t len = 0;
-    const uint32_t limit = trs.tracker->splitter->get_max_pdu();
+    const uint32_t limit = trs.tracker->get_splitter()->get_max_pdu();
 
     while ( len < limit and next_no_gap(*tsn) )
     {
@@ -757,7 +808,7 @@ int TcpReassembler::flush_stream(
     TcpReassemblerState& trs, Packet* p, uint32_t dir, bool final_flush)
 {
     // this is not always redundant; stream_reassemble rule option causes trouble
-    if ( !trs.tracker->flush_policy or !trs.tracker->splitter )
+    if ( !trs.tracker->is_reassembly_enabled() )
         return 0;
 
     uint32_t bytes;
@@ -849,8 +900,8 @@ void TcpReassembler::flush_queued_segments(
         p = set_packet(flow, trs.packet_dir, trs.server_side);
     }
 
-    bool pending = clear and paf_initialized(&trs.tracker->paf_state)
-        and (!trs.tracker->splitter or trs.tracker->splitter->finish(flow) );
+    bool pending = clear and paf_initialized(&trs.paf_state)
+        and (!trs.tracker->get_splitter() or trs.tracker->get_splitter()->finish(flow) );
 
     if ( pending and !(flow->ssn_state.ignore_direction & trs.ignore_dir) )
         final_flush(trs, p, trs.packet_dir);
@@ -904,7 +955,7 @@ int32_t TcpReassembler::flush_pdu_ips(TcpReassemblerState& trs, uint32_t* flags,
     if ( !tsn )
         tsn = trs.sos.seglist.cur_rseg;
 
-    else if ( paf_initialized(&trs.tracker->paf_state) )
+    else if ( paf_initialized(&trs.paf_state) )
     {
         assert(trs.sos.seglist.cur_rseg);
         total = tsn->c_seq - trs.sos.seglist.cur_rseg->c_seq;
@@ -915,9 +966,9 @@ int32_t TcpReassembler::flush_pdu_ips(TcpReassemblerState& trs, uint32_t* flags,
         total += tsn->c_len;
 
         uint32_t end = tsn->c_seq + tsn->c_len;
-        uint32_t pos = paf_position(&trs.tracker->paf_state);
+        uint32_t pos = paf_position(&trs.paf_state);
 
-        if ( paf_initialized(&trs.tracker->paf_state) && SEQ_LEQ(end, pos) )
+        if ( paf_initialized(&trs.paf_state) && SEQ_LEQ(end, pos) )
         {
             if ( !next_no_gap(*tsn) )
                 return -1;
@@ -927,7 +978,7 @@ int32_t TcpReassembler::flush_pdu_ips(TcpReassemblerState& trs, uint32_t* flags,
         }
 
         int32_t flush_pt = paf_check(
-            trs.tracker->splitter, &trs.tracker->paf_state, p, tsn->payload(),
+            trs.tracker->get_splitter(), &trs.paf_state, p, tsn->payload(),
             tsn->c_len, total, tsn->c_seq, flags);
 
         if (flush_pt >= 0)
@@ -954,9 +1005,8 @@ static inline bool both_splitters_aborted(Flow* flow)
 
 static inline void fallback(TcpStreamTracker& trk, bool server_side, uint16_t max)
 {
-    delete trk.splitter;
-    trk.splitter = new AtomSplitter(!server_side, max);
-    trk.paf_state.paf = StreamSplitter::START;
+    trk.set_splitter(new AtomSplitter(!server_side, max));
+    trk.reassembler.reset_paf();
     tcpStats.partial_fallbacks++;
 }
 
@@ -1008,9 +1058,9 @@ int32_t TcpReassembler::flush_pdu_ackd(TcpReassemblerState& trs, uint32_t* flags
     {
         uint32_t size = tsn->c_len;
         uint32_t end = tsn->c_seq + tsn->c_len;
-        uint32_t pos = paf_position(&trs.tracker->paf_state);
+        uint32_t pos = paf_position(&trs.paf_state);
 
-        if ( paf_initialized(&trs.tracker->paf_state) && SEQ_LEQ(end, pos) )
+        if ( paf_initialized(&trs.paf_state) && SEQ_LEQ(end, pos) )
         {
             total += size;
             tsn = tsn->next;
@@ -1023,7 +1073,7 @@ int32_t TcpReassembler::flush_pdu_ackd(TcpReassemblerState& trs, uint32_t* flags
         total += size;
 
         int32_t flush_pt = paf_check(
-            trs.tracker->splitter, &trs.tracker->paf_state, p, tsn->payload(),
+            trs.tracker->get_splitter(), &trs.paf_state, p, tsn->payload(),
             size, total, tsn->c_seq, flags);
 
         if ( flush_pt >= 0 )
@@ -1039,14 +1089,14 @@ int32_t TcpReassembler::flush_pdu_ackd(TcpReassemblerState& trs, uint32_t* flags
             // instead of creating more, but smaller, packets
             // FIXIT-L just flush to end of segment to avoid splitting
             // instead of all avail?
-            if ( !trs.tracker->splitter->is_paf() )
+            if ( !trs.tracker->is_splitter_paf() )
             {
                 // get_q_footprint() w/o side effects
                 int32_t avail = trs.tracker->r_win_base - trs.sos.seglist_base_seq;
 
                 if ( avail > flush_pt )
                 {
-                    paf_jump(&trs.tracker->paf_state, avail - flush_pt);
+                    paf_jump(&trs.paf_state, avail - flush_pt);
                     return avail;
                 }
             }
@@ -1062,7 +1112,7 @@ int TcpReassembler::flush_on_data_policy(TcpReassemblerState& trs, Packet* p)
     uint32_t flushed = 0;
     last_pdu = nullptr;
 
-    switch ( trs.tracker->flush_policy )
+    switch ( trs.tracker->get_flush_policy() )
     {
     case STREAM_FLPOLICY_IGNORE:
         return 0;
@@ -1089,7 +1139,7 @@ int TcpReassembler::flush_on_data_policy(TcpReassemblerState& trs, Packet* p)
             flush_amt = flush_pdu_ips(trs, &flags, p);
         }
 
-        if ( !flags && trs.tracker->splitter->is_paf() )
+        if ( !flags && trs.tracker->is_splitter_paf() )
         {
             fallback(*trs.tracker, trs.server_side);
             return flush_on_data_policy(trs, p);
@@ -1101,7 +1151,7 @@ int TcpReassembler::flush_on_data_policy(TcpReassemblerState& trs, Packet* p)
     if ( trs.tracker->is_retransmit_of_held_packet(p) )
         flushed = perform_partial_flush(trs, p, flushed);
 
-    // FIXIT-H a drop rule will yoink the seglist out from under us
+    // FIXIT-M a drop rule will yoink the seglist out from under us
     // because apply_delayed_action is only deferred to end of context
     // this is causing stability issues
     if ( flushed and trs.sos.seg_count and
@@ -1123,7 +1173,7 @@ int TcpReassembler::flush_on_ack_policy(TcpReassemblerState& trs, Packet* p)
     uint32_t flushed = 0;
     last_pdu = nullptr;
 
-    switch (trs.tracker->flush_policy)
+    switch ( trs.tracker->get_flush_policy() )
     {
     case STREAM_FLPOLICY_IGNORE:
         return 0;
@@ -1138,8 +1188,8 @@ int TcpReassembler::flush_on_ack_policy(TcpReassemblerState& trs, Packet* p)
             if ( !flush_amt )
                 flush_amt = trs.sos.seglist.cur_rseg->c_seq - trs.sos.seglist_base_seq;
 
-            if ( trs.tracker->paf_state.paf == StreamSplitter::ABORT )
-                trs.tracker->splitter->finish(p->flow);
+            if ( trs.paf_state.paf == StreamSplitter::ABORT )
+                trs.tracker->get_splitter()->finish(p->flow);
 
             // for consistency with other cases, should return total
             // but that breaks flushing pipelined pdus
@@ -1156,8 +1206,7 @@ int TcpReassembler::flush_on_ack_policy(TcpReassemblerState& trs, Packet* p)
                 break;  // bail if nothing flushed
         }
 
-        if ( (trs.tracker->paf_state.paf == StreamSplitter::ABORT) &&
-            (trs.tracker->splitter && trs.tracker->splitter->is_paf()) )
+        if ( (trs.paf_state.paf == StreamSplitter::ABORT) && trs.tracker->is_splitter_paf() )
         {
             fallback(*trs.tracker, trs.server_side);
             return flush_on_ack_policy(trs, p);
@@ -1345,10 +1394,10 @@ uint32_t TcpReassembler::perform_partial_flush(TcpReassemblerState& trs, Flow* f
 // are not null.
 uint32_t TcpReassembler::perform_partial_flush(TcpReassemblerState& trs, Packet* p, uint32_t flushed)
 {
-    if ( trs.tracker->splitter->init_partial_flush(p->flow) )
+    if ( trs.tracker->get_splitter()->init_partial_flush(p->flow) )
     {
         flushed += flush_stream(trs, p, trs.packet_dir, false);
-        paf_jump(&trs.tracker->paf_state, flushed);
+        paf_jump(&trs.paf_state, flushed);
         tcpStats.partial_flushes++;
         tcpStats.partial_flush_bytes += flushed;
         if ( trs.sos.seg_count )
index ba8fd5111f8357c4266e14701cd58d368cccc597..ea609984c63182e3e75a740a53564c318b4f5ba2 100644 (file)
@@ -39,6 +39,10 @@ public:
     virtual int flush_on_data_policy(TcpReassemblerState&, snort::Packet*);
     virtual int flush_on_ack_policy(TcpReassemblerState&, snort::Packet*);
     virtual void trace_segments(TcpReassemblerState&);
+    virtual bool add_alert(TcpReassemblerState&, uint32_t gid, uint32_t sid);
+    virtual bool check_alerted(TcpReassemblerState&, uint32_t gid, uint32_t sid);
+    virtual int update_alert(TcpReassemblerState&, uint32_t gid, uint32_t sid,
+        uint32_t event_id, uint32_t event_second);
     virtual void purge_alerts(TcpReassemblerState&);
 
     uint32_t perform_partial_flush(TcpReassemblerState&, snort::Flow*);
index c7cad8915e9dff99c3e797326b6b85f861077b6b..928a8da53f2850fb6ca993899867ed62756d8637 100644 (file)
@@ -49,6 +49,15 @@ public:
     void queue_packet_for_reassembly(TcpSegmentDescriptor& tsd)
     { reassembler->queue_packet_for_reassembly(trs, tsd); }
 
+    bool add_alert(uint32_t gid, uint32_t sid)
+    { return reassembler->add_alert(trs, gid, sid); }
+
+    bool check_alerted(uint32_t gid, uint32_t sid)
+    { return reassembler->check_alerted(trs, gid, sid); }
+
+    int update_alert(uint32_t gid, uint32_t sid, uint32_t event_id, uint32_t event_second)
+    { return reassembler->update_alert(trs, gid, sid, event_id, event_second); }
+
     void purge_alerts()
     { reassembler->purge_alerts(trs); }
 
@@ -118,6 +127,15 @@ public:
     uint32_t perform_partial_flush(snort::Flow* flow)
     { return reassembler->perform_partial_flush(trs, flow); }
 
+    void reset_paf()
+    { paf_reset(&trs.paf_state); }
+
+    void clear_paf()
+    { paf_clear(&trs.paf_state); }
+
+    void setup_paf()
+    { paf_setup(&trs.paf_state); }
+
 private:
     TcpReassembler* reassembler = nullptr;
     TcpReassemblerState trs;
index dd665649e72777968aaed29707002f5803abb74a..222558bbbc63ebf3e3b8b753c242c60dd62b58b1 100644 (file)
@@ -114,6 +114,9 @@ public:
         pkt->dsize = seg_len;
     }
 
+    bool is_data_segment() const
+    { return pkt->dsize > 0; }
+
     void update_len(int32_t offset)
     {
         assert(!meta_ack_packet);
index a109d7532567d0d76d066f32e963168bbbe6b286..3fe36e117feec129f912945b2eb8c561647bd3cc 100644 (file)
@@ -96,11 +96,21 @@ TcpSession::~TcpSession()
     memory::MemoryCap::update_deallocations(sizeof(*this));
 }
 
-bool TcpSession::setup(Packet* p)
+bool TcpSession::setup(Packet*)
 {
-    TcpStreamSession::setup(p);
+    client.init_tcp_state();
+    server.init_tcp_state();
+    lws_init = tcp_init = false;
+    generate_3whs_alert = true;
+    cleaning = false;
     splitter_init = false;
 
+    pkt_action_mask = ACTION_NOTHING;
+    ecn = 0;
+    ingress_index = egress_index = 0;
+    ingress_group = egress_group = 0;
+    daq_flags = address_space_id = 0;
+
     tcp_config = get_tcp_cfg(flow->ssn_server);
     flow->set_default_session_timeout(tcp_config->session_timeout, false);
     set_os_policy();
@@ -194,15 +204,14 @@ void TcpSession::clear_session(bool free_flow_data, bool flush_segments, bool re
     if ( restart )
     {
         flow->restart(free_flow_data);
-        paf_reset(&client.paf_state);
-        paf_reset(&server.paf_state);
-
+        client.reassembler.reset_paf();
+        server.reassembler.reset_paf();
     }
     else
     {
         flow->clear(free_flow_data);
-        paf_clear(&client.paf_state);
-        paf_clear(&server.paf_state);
+        client.reassembler.clear_paf();
+        server.reassembler.clear_paf();
     }
 
     set_splitter(true, nullptr);
@@ -300,7 +309,7 @@ bool TcpSession::flow_exceeds_config_thresholds(const TcpSegmentDescriptor& tsd)
 {
     TcpStreamTracker* listener = tsd.get_listener();
 
-    if ( listener->flush_policy == STREAM_FLPOLICY_IGNORE )
+    if ( listener->get_flush_policy() == STREAM_FLPOLICY_IGNORE )
         return true;
 
     // FIXIT-M any discards must be counted and in many cases alerted as well
@@ -372,6 +381,7 @@ void TcpSession::update_stream_order(const TcpSegmentDescriptor& tsd, bool align
         else
             listener->order = 1;
         break;
+
     case 1:
         if ( aligned )
         {
@@ -379,6 +389,7 @@ void TcpSession::update_stream_order(const TcpSegmentDescriptor& tsd, bool align
             listener->order = 2;
         }
         break;
+
     default:
         if ( aligned )
             tsd.set_packet_flags(PKT_STREAM_ORDER_OK);
@@ -413,8 +424,8 @@ int TcpSession::process_tcp_data(TcpSegmentDescriptor& tsd)
     if (seq == listener->rcv_nxt)
     {
         /* check if we're in the window */
-        if (tcp_config->policy != StreamPolicy::OS_PROXY
-            and listener->normalizer.get_stream_window(tsd) == 0)
+        if ( tcp_config->policy != StreamPolicy::OS_PROXY
+            and listener->normalizer.get_stream_window(tsd) == 0 )
         {
             listener->normalizer.trim_win_payload(tsd);
             return STREAM_UNALIGNED;
@@ -424,7 +435,7 @@ int TcpSession::process_tcp_data(TcpSegmentDescriptor& tsd)
         // FIXIT-L for ips, must move all the way to first hole or right end
         listener->rcv_nxt = tsd.get_end_seq();
 
-        if (tsd.get_len() != 0)
+        if ( tsd.is_data_segment() )
         {
             update_stream_order(tsd, true);
             process_tcp_stream(tsd);
@@ -440,13 +451,13 @@ int TcpSession::process_tcp_data(TcpSegmentDescriptor& tsd)
         // some cases.
 
         /* check if we're in the window */
-        if (tcp_config->policy != StreamPolicy::OS_PROXY
-            and listener->normalizer.get_stream_window(tsd) == 0)
+        if ( tcp_config->policy != StreamPolicy::OS_PROXY
+            and listener->normalizer.get_stream_window(tsd) == 0 )
         {
             listener->normalizer.trim_win_payload(tsd);
             return STREAM_UNALIGNED;
         }
-        if (tsd.get_len() != 0)
+        if ( tsd.is_data_segment() )
         {
             update_stream_order(tsd, false);
             process_tcp_stream(tsd);
@@ -567,7 +578,7 @@ bool TcpSession::handle_syn_on_reset_session(TcpSegmentDescriptor& tsd)
             /* Got SYN/RST.  We're done. */
             listener->normalizer.trim_syn_payload(tsd);
             listener->normalizer.trim_rst_payload(tsd);
-            pkt_action_mask |= ACTION_RST;
+            set_pkt_action_flag(ACTION_RST);
             return false;
         }
         else if ( tcph->is_syn_only() )
@@ -625,7 +636,7 @@ void TcpSession::update_ignored_session(TcpSegmentDescriptor& tsd)
         }
 
         tsd.set_packet_flags(PKT_IGNORE);
-        pkt_action_mask |= ACTION_DISABLE_INSPECTION;
+        set_pkt_action_flag(ACTION_DISABLE_INSPECTION);
         tcpStats.ignored++;
     }
 }
@@ -642,7 +653,7 @@ void TcpSession::handle_data_on_syn(TcpSegmentDescriptor& tsd)
     {
         listener->normalizer.trim_syn_payload(tsd);
         tel.set_tcp_event(EVENT_DATA_ON_SYN);
-        pkt_action_mask |= ACTION_BAD_PKT;
+        set_pkt_action_flag(ACTION_BAD_PKT);
     }
 }
 
@@ -729,9 +740,8 @@ bool TcpSession::check_for_window_slam(TcpSegmentDescriptor& tsd)
     {
         /* got a window too large, alert! */
         tel.set_tcp_event(EVENT_WINDOW_TOO_LARGE);
-        inc_tcp_discards();
         listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
-        pkt_action_mask |= ACTION_BAD_PKT;
+        set_pkt_action_flag(ACTION_BAD_PKT);
         return true;
     }
     else if ( tsd.is_packet_from_client() && (tsd.get_wnd() <= SLAM_MAX)
@@ -741,13 +751,9 @@ bool TcpSession::check_for_window_slam(TcpSegmentDescriptor& tsd)
     {
         /* got a window slam alert! */
         tel.set_tcp_event(EVENT_WINDOW_SLAM);
-        inc_tcp_discards();
-
-        if ( listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK) )
-        {
-            pkt_action_mask |= ACTION_BAD_PKT;
-            return true;
-        }
+        listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
+        set_pkt_action_flag(ACTION_BAD_PKT);
+        return true;
     }
 
     return false;
@@ -776,43 +782,30 @@ void TcpSession::handle_data_segment(TcpSegmentDescriptor& tsd)
         // FIXIT-M move this to normalizer base class, handle OS_PROXY in derived class
         if ( tcp_config->policy != StreamPolicy::OS_PROXY )
         {
-            /* check for valid sequence/retrans */
+            // drop packet if sequence num is invalid
             if ( !listener->is_segment_seq_valid(tsd) )
+            {
+                tcpStats.invalid_seq_num++;
+                listener->normalizer.trim_win_payload(tsd);
                 return;
+            }
 
             // 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->get_session_flags() & SSNFLAG_MIDSTREAM) && flow->two_way_traffic() )
             {
-                // sender of syn w/mss limits payloads from peer since we store mss on
-                // sender side, use listener mss same reasoning for window size
-                TcpStreamTracker* st = listener;
+                // trim to fit in listener's window and mss
+                listener->normalizer.trim_win_payload
+                    (tsd, (listener->r_win_base + listener->get_snd_wnd() - listener->rcv_nxt));
 
-                // trim to fit in window and mss as needed
-                st->normalizer.trim_win_payload(
-                    tsd, (st->r_win_base + st->get_snd_wnd() - st->rcv_nxt));
+                if ( listener->get_mss() )
+                    listener->normalizer.trim_mss_payload(tsd, listener->get_mss());
 
-                // FIXIT-H: MSS is not set on client so packets sent to client are not trimmed
-                // use case?
-                if ( st->get_mss() )
-                    st->normalizer.trim_mss_payload(tsd, st->get_mss());
-
-                st->normalizer.ecn_stripper(tsd);
+                listener->normalizer.ecn_stripper(tsd);
             }
         }
 
-        // 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 ( (tsd.get_tcph()->th_flags != 0) or (tcp_config->policy == StreamPolicy::OS_LINUX)
-                or (tcp_config->policy == StreamPolicy::OS_PROXY) )
-        {
-            process_tcp_data(tsd);
-        }
-        else
-        {
-            tel.set_tcp_event(EVENT_DATA_WITHOUT_FLAGS);
-            listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
-        }
+        process_tcp_data(tsd);
     }
 
     listener->reassembler.flush_on_data_policy(tsd.get_pkt());
@@ -837,7 +830,7 @@ void TcpSession::check_for_repeated_syn(TcpSegmentDescriptor& tsd)
     if ( !SEQ_EQ(tsd.get_seq(), talker->get_iss()) and
         listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK) )
     {
-        action = ACTION_BAD_PKT;
+        set_pkt_action_flag(ACTION_BAD_PKT);
     }
     else if ( talker->get_tcp_state() >= TcpStreamTracker::TCP_ESTABLISHED and
         talker->get_tcp_state() < TcpStreamTracker::TCP_CLOSED )
@@ -890,7 +883,7 @@ void TcpSession::flush_client(Packet* p)
 void TcpSession::flush_tracker(
     TcpStreamTracker& tracker, Packet* p, uint32_t dir, bool final_flush)
 {
-    if ( final_flush && (!tracker.splitter || !tracker.splitter->finish(flow)) )
+    if ( final_flush && (!tracker.get_splitter() || !tracker.get_splitter()->finish(flow)) )
          return;
 
      tracker.set_tf_flags(TF_FORCE_FLUSH);
@@ -937,11 +930,11 @@ static inline void set_window_scale(TcpSegmentDescriptor& tsd)
 
 void TcpSession::check_events_and_actions(const TcpSegmentDescriptor& tsd)
 {
+    tel.log_tcp_events();
+
     if ( tsd.is_meta_ack_packet() )
         return;
 
-    tel.log_tcp_events();
-
     Packet* p = tsd.get_pkt();
     if ( !(pkt_action_mask & ACTION_LWSSN_CLOSED) )
     {
@@ -971,8 +964,8 @@ bool TcpSession::ignore_this_packet(Packet* p)
 
     if ( flow->ssn_state.ignore_direction != SSN_DIR_NONE )
     {
-        server.flush_policy = STREAM_FLPOLICY_IGNORE;
-        client.flush_policy = STREAM_FLPOLICY_IGNORE;
+        server.set_flush_policy(STREAM_FLPOLICY_IGNORE);
+        client.set_flush_policy(STREAM_FLPOLICY_IGNORE);
         return true;
     }
 
@@ -1005,7 +998,7 @@ void TcpSession::precheck(Packet* p)
 
 void TcpSession::init_tcp_packet_analysis(TcpSegmentDescriptor& tsd)
 {
-    if ( !splitter_init and tsd.get_len() > 0 )
+    if ( !splitter_init and tsd.is_data_segment() )
     {
         if ( !(tcp_config->flags & STREAM_CONFIG_NO_REASSEMBLY) )
         {
@@ -1054,32 +1047,23 @@ bool TcpSession::validate_packet_established_session(TcpSegmentDescriptor& tsd)
 
     if ( tsd.is_policy_inline() )
        if ( tsd.get_tcph()->is_ack() && !listener->is_ack_valid(tsd.get_ack()) )
-           pkt_action_mask |= ACTION_BAD_PKT;
+       {
+           listener->normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
+           set_pkt_action_flag(ACTION_BAD_PKT);
+       }
 
     if ( !tsd.is_meta_ack_packet() )
-        pkt_action_mask |= listener->normalizer.handle_paws(tsd);
+        set_pkt_action_flag(listener->normalizer.handle_paws(tsd));
 
     return ( pkt_action_mask & ACTION_BAD_PKT ) ? false : true;
 }
 
 int TcpSession::process_tcp_packet(TcpSegmentDescriptor& tsd)
 {
-    if ( tsm->eval(tsd) )
-    {
-        check_events_and_actions(tsd);
-        S5TraceTCP(tsd);
-    }
-    else
-    {
-        if ( pkt_action_mask & ACTION_BAD_PKT )
-        {
-            inc_tcp_discards();
-            check_events_and_actions(tsd);
-        }
+    tsm->eval(tsd);
+    check_events_and_actions(tsd);
 
-        tel.log_tcp_events();
-        S5TraceTCP(tsd);
-    }
+    S5TraceTCP(tsd);
 
     return ACTION_NOTHING;
 }
index acc7fb2399de8e8e516b2f6ed18cf85980675ca1..f36e1cade2bfa41d46f37aa5fb5b2a51cc0fa0f1 100644 (file)
@@ -32,14 +32,13 @@ using namespace snort;
 
 TcpStateCloseWait::TcpStateCloseWait(TcpStateMachine& tsm) :
     TcpStateHandler(TcpStreamTracker::TCP_CLOSE_WAIT, tsm)
-{
-}
+{ }
 
 bool TcpStateCloseWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs() );
 
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
 
     return true;
@@ -93,9 +92,10 @@ bool TcpStateCloseWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tr
     {
         if ( !flow->two_way_traffic() )
             trk.set_tf_flags(TF_FORCE_FLUSH);
-        if ( tsd.get_len() > 0 )
+        if ( tsd.is_data_segment() )
             trk.session->handle_data_segment(tsd);
     }
+
     return true;
 }
 
@@ -108,10 +108,7 @@ bool TcpStateCloseWait::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& tr
         trk.session->set_pkt_action_flag(ACTION_RST);
         tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
     }
-    else
-    {
-        trk.session->tel.set_tcp_event(EVENT_BAD_RST);
-    }
+
     return true;
 }
 
index 575e69e829474e8241de3a2f6ebb58e0143bd69c..9633c7f25a72a99b773aa4d804de4451ae70f3fe 100644 (file)
@@ -35,8 +35,7 @@ using namespace snort;
 
 TcpStateClosed::TcpStateClosed(TcpStateMachine& tsm) :
     TcpStateHandler(TcpStreamTracker::TCP_CLOSED, tsm)
-{
-}
+{ }
 
 bool TcpStateClosed::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
@@ -99,7 +98,7 @@ bool TcpStateClosed::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.update_tracker_ack_recv(tsd);
 
-    if( tsd.get_len() > 0 )
+    if( tsd.is_data_segment() )
     {
         if ( trk.is_rst_pkt_sent() )
             trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RESET);
@@ -117,10 +116,7 @@ bool TcpStateClosed::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
         trk.session->set_pkt_action_flag(ACTION_RST);
     }
-    else
-    {
-        trk.session->tel.set_tcp_event(EVENT_BAD_RST);
-    }
+
     return true;
 }
 
index 22c5b3ee7bbdb45a877e6932bc6ce8894a8ad9ab..ebd67715148e9e90b09073c51f327b76936f174f 100644 (file)
@@ -32,8 +32,7 @@ using namespace snort;
 
 TcpStateClosing::TcpStateClosing(TcpStateMachine& tsm) :
     TcpStateHandler(TcpStreamTracker::TCP_CLOSING, tsm)
-{
-}
+{ }
 
 bool TcpStateClosing::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
@@ -44,7 +43,7 @@ bool TcpStateClosing::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 bool TcpStateClosing::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
     return true;
 }
@@ -112,10 +111,7 @@ bool TcpStateClosing::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         trk.session->set_pkt_action_flag(ACTION_RST);
         tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
     }
-    else
-    {
-        trk.session->tel.set_tcp_event(EVENT_BAD_RST);
-    }
+
     return true;
 }
 
index a6f4e5e77905a07e1a80ec7211523fac9cd32674..3333787c82766cdfb7fc586ac0cafa4a1fce7e1f 100644 (file)
@@ -30,8 +30,7 @@
 
 TcpStateEstablished::TcpStateEstablished(TcpStateMachine& tsm) :
     TcpStateHandler(TcpStreamTracker::TCP_ESTABLISHED, tsm)
-{
-}
+{ }
 
 bool TcpStateEstablished::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
@@ -104,11 +103,8 @@ bool TcpStateEstablished::fin_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 bool TcpStateEstablished::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.update_tracker_ack_recv(tsd);
-    if ( tsd.get_len() > 0 )
-    {
+    if ( tsd.is_data_segment() )
          trk.session->handle_data_segment(tsd);
-         trk.flush_data_on_fin_recv(tsd);
-    }
 
     if ( trk.update_on_fin_recv(tsd) )
     {
@@ -127,13 +123,9 @@ bool TcpStateEstablished::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
         trk.session->set_pkt_action_flag(ACTION_RST);
     }
-    else
-    {
-        trk.session->tel.set_tcp_event(EVENT_BAD_RST);
-    }
 
     // FIXIT-L might be good to create alert specific to RST with data
-    if ( tsd.get_len() > 0 )
+    if ( tsd.is_data_segment() )
         trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
 
     return true;
index 2656058ad821e00e7de3b8564c3466600594b705..43e72b933dfdac92480b4a979f260acd19478108 100644 (file)
@@ -33,8 +33,7 @@ using namespace snort;
 
 TcpStateFinWait1::TcpStateFinWait1(TcpStateMachine& tsm) :
     TcpStateHandler(TcpStreamTracker::TCP_FIN_WAIT1, tsm)
-{
-}
+{ }
 
 bool TcpStateFinWait1::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
@@ -45,14 +44,14 @@ bool TcpStateFinWait1::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
 bool TcpStateFinWait1::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
     return true;
 }
 
 bool TcpStateFinWait1::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
     return true;
 }
@@ -81,7 +80,7 @@ bool TcpStateFinWait1::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker
     trk.update_tracker_ack_recv(tsd);
     if ( check_for_window_slam(tsd, trk) )
     {
-        if ( tsd.get_len() > 0 )
+        if ( tsd.is_data_segment() )
             trk.session->handle_data_segment(tsd);
     }
     return true;
@@ -103,7 +102,7 @@ bool TcpStateFinWait1::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
         bool is_ack_valid = false;
         if ( check_for_window_slam(tsd, trk, &is_ack_valid) )
         {
-            if ( tsd.get_len() > 0 )
+            if ( tsd.is_data_segment() )
                 trk.session->handle_data_segment(tsd);
 
             if ( !flow->two_way_traffic() )
@@ -127,13 +126,9 @@ bool TcpStateFinWait1::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
         trk.session->set_pkt_action_flag(ACTION_RST);
         tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
     }
-    else
-    {
-        trk.session->tel.set_tcp_event(EVENT_BAD_RST);
-    }
 
     // FIXIT-L might be good to create alert specific to RST with data
-    if ( tsd.get_len() > 0 )
+    if ( tsd.is_data_segment() )
         trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
     return true;
 }
@@ -146,13 +141,9 @@ bool TcpStateFinWait1::check_for_window_slam(TcpSegmentDescriptor& tsd, TcpStrea
             && (tsd.get_wnd() == 0))
         {
             trk.session->tel.set_tcp_event(EVENT_WINDOW_SLAM);
-            inc_tcp_discards();
-
-            if (trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK))
-            {
-                trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
-                return false;
-            }
+            trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
+            trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
+            return false;
         }
 
         trk.set_tcp_state(TcpStreamTracker::TCP_FIN_WAIT2);
index f314f147c26449b569ba80fa58212dbaa85fab9f..81df9352fa117528fce21b8967572d0ab9aa4b87 100644 (file)
@@ -32,8 +32,7 @@ using namespace snort;
 
 TcpStateFinWait2::TcpStateFinWait2(TcpStateMachine& tsm) :
     TcpStateHandler(TcpStreamTracker::TCP_FIN_WAIT2, tsm)
-{
-}
+{ }
 
 bool TcpStateFinWait2::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
@@ -44,14 +43,14 @@ bool TcpStateFinWait2::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
 bool TcpStateFinWait2::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
     return true;
 }
 
 bool TcpStateFinWait2::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
     return true;
 }
@@ -72,6 +71,7 @@ bool TcpStateFinWait2::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
     }
     else
         trk.update_tracker_ack_recv(tsd);
+
     return true;
 }
 
@@ -95,9 +95,10 @@ bool TcpStateFinWait2::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker
     else
     {
         trk.update_tracker_ack_recv(tsd);
-        if ( tsd.get_len() > 0 )
+        if ( tsd.is_data_segment() )
             trk.session->handle_data_segment(tsd);
     }
+
     return true;
 }
 
@@ -108,7 +109,7 @@ bool TcpStateFinWait2::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
     trk.update_tracker_ack_recv(tsd);
     if ( trk.update_on_fin_recv(tsd) )
     {
-        if ( tsd.get_len() > 0 )
+        if ( tsd.is_data_segment() )
             trk.session->handle_data_segment(tsd);
 
         if ( !flow->two_way_traffic() )
@@ -128,10 +129,7 @@ bool TcpStateFinWait2::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
         trk.session->set_pkt_action_flag(ACTION_RST);
         tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
     }
-    else
-    {
-        trk.session->tel.set_tcp_event(EVENT_BAD_RST);
-    }
+
     return true;
 }
 
index d0e83344bf74b6eae4208866f5a6024cc785824f..dbf50a8cd96fa975a9a425fefd3d964744653fa3 100644 (file)
 using namespace std;
 
 TcpStateHandler::TcpStateHandler(TcpStreamTracker::TcpState state, TcpStateMachine& tsm)
-{
-    tsm.register_state_handler(state, *this);
-}
+{ tsm.register_state_handler(state, *this); }
 
 bool TcpStateHandler::do_pre_sm_packet_actions(TcpSegmentDescriptor&, TcpStreamTracker&)
-{
-    return true;
-}
+{  return true; }
 
 bool TcpStateHandler::do_post_sm_packet_actions(TcpSegmentDescriptor&, TcpStreamTracker&)
-{
-    return true;
-}
+{ return true; }
 
 bool TcpStateHandler::eval(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
 {
@@ -90,6 +84,9 @@ bool TcpStateHandler::eval(TcpSegmentDescriptor& tsd, TcpStreamTracker& tracker)
     case TcpStreamTracker::TCP_RST_RECV_EVENT:
         return rst_recv(tsd, tracker);
 
+    case TcpStreamTracker::TCP_NO_FLAGS_EVENT:
+        return no_flags(tsd, tracker);
+
     default:
         break;
     }
index b7e014f7f68f333129cb4cb252bf63adb6445430..a53fd2597534d19b6eb87571f142267984ba6c41 100644 (file)
@@ -53,6 +53,11 @@ protected:
     virtual bool fin_recv(TcpSegmentDescriptor&, TcpStreamTracker&) { return true; }
     virtual bool rst_sent(TcpSegmentDescriptor&, TcpStreamTracker&) { return true; }
     virtual bool rst_recv(TcpSegmentDescriptor&, TcpStreamTracker&) { return true; }
+    virtual bool no_flags(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
+    {
+        trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
+        return false;
+    }
 };
 
 #endif
index c779edcec88120a2a0749848ec0d5745173d4f31..f1f01ddb5c1027388c20d2ceec7b646e773cfa3b 100644 (file)
@@ -32,8 +32,7 @@ using namespace snort;
 
 TcpStateLastAck::TcpStateLastAck(TcpStateMachine& tsm) :
     TcpStateHandler(TcpStreamTracker::TCP_LAST_ACK, tsm)
-{
-}
+{ }
 
 bool TcpStateLastAck::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
@@ -44,7 +43,7 @@ bool TcpStateLastAck::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 bool TcpStateLastAck::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
     return true;
 }
@@ -104,13 +103,9 @@ bool TcpStateLastAck::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
         trk.session->set_pkt_action_flag(ACTION_RST);
     }
-    else
-    {
-        trk.session->tel.set_tcp_event(EVENT_BAD_RST);
-    }
 
     // FIXIT-L might be good to create alert specific to RST with data
-    if ( tsd.get_len() > 0 )
+    if ( tsd.is_data_segment() )
         trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
     return true;
 }
index afdb7dc890e84af2efc5292231e577f7318457f4..dfd52b4839397dd495d4fa60efdbda95d86b4ff6 100644 (file)
@@ -37,7 +37,7 @@ TcpStateListen::TcpStateListen(TcpStateMachine& tsm) :
 
 bool TcpStateListen::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( trk.session->tcp_config->require_3whs() || tsd.has_wscale() || ( tsd.get_len() > 0 ) )
+    if ( trk.session->tcp_config->require_3whs() || tsd.has_wscale() || ( tsd.is_data_segment() ) )
     {
         if ( tsd.is_packet_from_server() )
             trk.session->tel.set_tcp_event(EVENT_4WHS);
@@ -50,7 +50,7 @@ bool TcpStateListen::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
     trk.init_on_syn_recv(tsd);
     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
     trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd) );
-    if ( tsd.get_len() > 0 )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
     return true;
 }
@@ -79,7 +79,7 @@ bool TcpStateListen::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& t
     if ( !trk.session->tcp_config->require_3whs() or trk.session->is_midstream_allowed(tsd) )
     {
         trk.init_on_synack_recv(tsd);
-        if ( tsd.get_len() > 0 )
+        if ( tsd.is_data_segment() )
             trk.session->handle_data_segment(tsd);
     }
     else if ( trk.session->tcp_config->require_3whs() )
@@ -93,7 +93,7 @@ bool TcpStateListen::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& t
 bool TcpStateListen::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     if ( trk.session->tcp_config->midstream_allowed(tsd.get_pkt())
-         && (tsd.has_wscale() || (tsd.get_len() > 0 )) )
+         && (tsd.has_wscale() || (tsd.is_data_segment() )) )
     {
         Flow* flow = tsd.get_flow();
         flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_SYN_ACK |
@@ -113,7 +113,7 @@ bool TcpStateListen::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateListen::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( trk.session->is_midstream_allowed(tsd) && (tsd.has_wscale() || (tsd.get_len() > 0 )) )
+    if ( trk.session->is_midstream_allowed(tsd) && (tsd.has_wscale() || (tsd.is_data_segment() )) )
     {
         Flow* flow = tsd.get_flow();
 
index 55ae0980926cf5c3faeda46d8c2cb12ea6b295d1..fa27ecf69d43d96303ecd6b0109c0be5322a22c6 100644 (file)
@@ -32,8 +32,7 @@ using namespace snort;
 
 TcpStateNone::TcpStateNone(TcpStateMachine& tsm) :
     TcpStateHandler(TcpStreamTracker::TCP_STATE_NONE, tsm)
-{
-}
+{ }
 
 bool TcpStateNone::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
@@ -48,7 +47,6 @@ bool TcpStateNone::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateNone::syn_recv(TcpSegmentDescriptor&, TcpStreamTracker&)
 {
-    // FIXIT-H syn received on undefined client, figure this out and do the right thing
     return true;
 }
 
@@ -77,7 +75,7 @@ bool TcpStateNone::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
     {
         trk.init_on_synack_recv(tsd);
         trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-        if ( tsd.get_len() > 0 )
+        if ( tsd.is_data_segment() )
             trk.session->handle_data_segment(tsd);
     }
     else if ( trk.session->tcp_config->require_3whs() )
@@ -90,12 +88,10 @@ bool TcpStateNone::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
 
 bool TcpStateNone::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( trk.session->is_midstream_allowed(tsd) && (tsd.has_wscale() || (tsd.get_len() > 0)) )
+    if ( trk.session->is_midstream_allowed(tsd) && (tsd.has_wscale() || (tsd.is_data_segment())) )
     {
         Flow* flow = tsd.get_flow();
 
-        // FIXIT-H do we need to verify the ACK field is >= the seq of the SYN-ACK?
-        // 3-way Handshake complete, create TCP session
         flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_SYN_ACK |
             STREAM_STATE_ESTABLISHED );
         trk.init_on_3whs_ack_sent(tsd);
@@ -112,7 +108,7 @@ bool TcpStateNone::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateNone::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( trk.session->is_midstream_allowed(tsd) && (tsd.has_wscale() || (tsd.get_len() > 0)) )
+    if ( trk.session->is_midstream_allowed(tsd) && (tsd.has_wscale() || (tsd.is_data_segment())) )
     {
         Flow* flow = tsd.get_flow();
 
@@ -228,10 +224,7 @@ bool TcpStateNone::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
         trk.session->set_pkt_action_flag(ACTION_RST);
     }
-    else
-    {
-        trk.session->tel.set_tcp_event(EVENT_BAD_RST);
-    }
+
     return true;
 }
 
index 1084ea9e957dbc7a058e94742bc400b85e3dd94f..2e6a19e844669487ae4c92845eb1aaffc876c522 100644 (file)
@@ -57,7 +57,7 @@ bool TcpStateSynRecv::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateSynRecv::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
     return true;
 }
@@ -66,8 +66,6 @@ bool TcpStateSynRecv::syn_ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 {
     Flow* flow = tsd.get_flow();
 
-    // FIXIT-H verify ack being sent is valid...
-    // norm/drop + discard
     trk.finish_server_init(tsd);
     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
     flow->session_state |= STREAM_STATE_SYN_ACK;
@@ -86,7 +84,7 @@ bool TcpStateSynRecv::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
         flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
         trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
-        if ( tsd.get_len() )
+        if ( tsd.is_data_segment() )
             trk.session->handle_data_on_syn(tsd);
     }
     return true;
@@ -114,7 +112,7 @@ bool TcpStateSynRecv::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
         trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
-        if ( tsd.get_len() > 0 )
+        if ( tsd.is_data_segment() )
             trk.session->handle_data_segment(tsd);
         else
             trk.session->check_for_window_slam(tsd);
@@ -140,7 +138,7 @@ bool TcpStateSynRecv::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_ESTABLISHED);
         trk.set_tcp_state(TcpStreamTracker::TCP_ESTABLISHED);
     }
-    if ( tsd.get_len() > 0 )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_segment(tsd);
     return true;
 }
@@ -154,11 +152,8 @@ bool TcpStateSynRecv::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         trk.update_tracker_ack_recv(tsd);
         trk.session->set_pkt_action_flag(trk.normalizer.handle_paws(tsd));
         flow->session_state |= STREAM_STATE_ACK;
-        if ( tsd.get_len() > 0 )
-        {
+        if ( tsd.is_data_segment() )
             trk.session->handle_data_segment(tsd);
-            trk.flush_data_on_fin_recv(tsd);
-        }
 
         if ( trk.update_on_fin_recv(tsd) )
         {
@@ -179,13 +174,13 @@ bool TcpStateSynRecv::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
     }
     else
     {
-        inc_tcp_discards();
         trk.session->tel.set_tcp_event(EVENT_BAD_RST);
         trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
+        trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
     }
 
     // FIXIT-L might be good to create alert specific to RST with data
-    if ( tsd.get_len() > 0 )
+    if ( tsd.is_data_segment() )
         trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
     return true;
 }
index c8e8c69f01de38c70dac75b118765b18ce956b23..deb555d996ed63e52cba89cf9ae46228ebbe9482 100644 (file)
@@ -31,8 +31,7 @@ using namespace snort;
 
 TcpStateSynSent::TcpStateSynSent(TcpStateMachine& tsm) :
     TcpStateHandler(TcpStreamTracker::TCP_SYN_SENT, tsm)
-{
-}
+{ }
 
 bool TcpStateSynSent::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
@@ -43,7 +42,7 @@ bool TcpStateSynSent::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 bool TcpStateSynSent::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.finish_client_init(tsd);
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
     trk.set_tcp_state(TcpStreamTracker::TCP_SYN_RECV);
     return true;
@@ -54,11 +53,12 @@ bool TcpStateSynSent::syn_ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
     if ( trk.update_on_3whs_ack(tsd) )
     {
         trk.session->update_timestamp_tracking(tsd);
-        if ( tsd.get_len() )
+        if ( tsd.is_data_segment() )
             trk.session->handle_data_on_syn(tsd);
     }
     else
         trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
+
     return true;
 }
 
@@ -66,8 +66,6 @@ bool TcpStateSynSent::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     Flow* flow = tsd.get_flow();
 
-    // FIXIT-H verify ack being sent is valid...
-    // norm/drop + discard
     trk.update_tracker_ack_sent(tsd);
     flow->set_session_flags(SSNFLAG_ESTABLISHED);
     flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
@@ -79,7 +77,7 @@ bool TcpStateSynSent::ack_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 
 bool TcpStateSynSent::ack_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( tsd.get_len() > 0 )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_segment(tsd);
     return true;
 }
@@ -88,8 +86,6 @@ bool TcpStateSynSent::data_seg_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 {
     Flow* flow = tsd.get_flow();
 
-    // FIXIT-H verify ack being sent is valid...
-    // norm/drop + discard
     trk.update_tracker_ack_sent(tsd);
     flow->set_session_flags(SSNFLAG_ESTABLISHED);
     flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
@@ -107,7 +103,7 @@ bool TcpStateSynSent::data_seg_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker&
 
 bool TcpStateSynSent::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
-    if ( tsd.get_len() > 0 )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_segment(tsd);
     return true;
 }
@@ -122,13 +118,9 @@ bool TcpStateSynSent::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
         trk.session->set_pkt_action_flag(ACTION_RST);
         tsd.get_flow()->session_state |= STREAM_STATE_CLOSED;
     }
-    else
-    {
-        trk.session->tel.set_tcp_event(EVENT_BAD_RST);
-    }
 
     // FIXIT-L might be good to create alert specific to RST with data
-    if ( tsd.get_len() > 0 )
+    if ( tsd.is_data_segment() )
         trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
     return true;
 }
index 9c4351809d3587db254a4cf97bf98d34e7b50c21..6c17227e01b17de3a7258f6d07a2c89079caa551 100644 (file)
@@ -44,7 +44,7 @@ bool TcpStateTimeWait::syn_sent(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
 bool TcpStateTimeWait::syn_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk)
 {
     trk.normalizer.ecn_tracker(tsd.get_tcph(), trk.session->tcp_config->require_3whs());
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         trk.session->handle_data_on_syn(tsd);
 
     return true;
@@ -73,7 +73,7 @@ bool TcpStateTimeWait::fin_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
         trk.normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
         trk.session->set_pkt_action_flag(ACTION_BAD_PKT);
     }
-    else if ( tsd.get_len() > 0 )
+    else if ( tsd.is_data_segment() )
         trk.session->handle_data_segment(tsd);
 
     return true;
@@ -87,14 +87,8 @@ bool TcpStateTimeWait::rst_recv(TcpSegmentDescriptor& tsd, TcpStreamTracker& trk
         trk.session->update_perf_base_state(TcpStreamTracker::TCP_CLOSING);
         trk.session->set_pkt_action_flag(ACTION_RST);
     }
-    else
-    {
-        trk.session->tel.set_tcp_event(EVENT_BAD_RST);
-    }
 
-    // FIXIT-L might be good to create alert specific to RST with data
-    // FIXIT-L refactoring required?  seen this in many places
-    if ( tsd.get_len() > 0 )
+    if ( tsd.is_data_segment() )
         trk.session->tel.set_tcp_event(EVENT_DATA_AFTER_RST_RCVD);
 
     return true;
index 33ba85267ac7d3f8b8d73ed38ce17f7ac8a6f70e..383b846bf1ce4d63865c224ceea68f85a9c47af8 100644 (file)
@@ -58,7 +58,7 @@ void TcpStreamSession::init_new_tcp_session(TcpSegmentDescriptor& tsd)
 void TcpStreamSession::update_session_on_syn_ack()
 {
     /* If session is already marked as established */
-    if ( !( flow->session_state & STREAM_STATE_ESTABLISHED ) )
+    if ( !(flow->session_state & STREAM_STATE_ESTABLISHED) )
     {
         /* SYN-ACK from server */
         if (flow->session_state != STREAM_STATE_NONE)
@@ -72,7 +72,7 @@ void TcpStreamSession::update_session_on_syn_ack()
 void TcpStreamSession::update_session_on_ack()
 {
     /* If session is already marked as established */
-    if ( !( flow->session_state & STREAM_STATE_ESTABLISHED ) )
+    if ( !(flow->session_state & STREAM_STATE_ESTABLISHED) )
     {
         if ( flow->session_state & STREAM_STATE_SYN_ACK )
         {
@@ -89,14 +89,14 @@ void TcpStreamSession::update_session_on_server_packet(TcpSegmentDescriptor& tsd
     tsd.set_listener(client);
 
     /* If we picked this guy up midstream, finish the initialization */
-    if ( !( flow->session_state & STREAM_STATE_ESTABLISHED )
-        && ( flow->session_state & STREAM_STATE_MIDSTREAM ) )
+    if ( !(flow->session_state & STREAM_STATE_ESTABLISHED)
+        && (flow->session_state & STREAM_STATE_MIDSTREAM) )
     {
-        if (tsd.get_tcph()->are_flags_set(TH_ECE)
-            && (flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY))
+        if ( tsd.get_tcph()->are_flags_set(TH_ECE)
+             && (flow->get_session_flags() & SSNFLAG_ECN_CLIENT_QUERY) )
             flow->set_session_flags(SSNFLAG_ECN_SERVER_REPLY);
 
-        if (flow->get_session_flags() & SSNFLAG_SEEN_CLIENT)
+        if ( flow->get_session_flags() & SSNFLAG_SEEN_CLIENT )
         {
             // should TCP state go to established too?
             flow->session_state |= STREAM_STATE_ESTABLISHED;
@@ -120,14 +120,14 @@ void TcpStreamSession::update_session_on_client_packet(TcpSegmentDescriptor& tsd
         && ( flow->session_state & STREAM_STATE_MIDSTREAM ) )
     {
         /* Midstream and seen server. */
-        if (flow->get_session_flags() & SSNFLAG_SEEN_SERVER)
+        if ( flow->get_session_flags() & SSNFLAG_SEEN_SERVER )
         {
             flow->session_state |= STREAM_STATE_ESTABLISHED;
             flow->set_session_flags(SSNFLAG_ESTABLISHED);
         }
     }
 
-    if (!flow->inner_client_ttl && !tsd.is_meta_ack_packet() )
+    if ( !flow->inner_client_ttl && !tsd.is_meta_ack_packet() )
         flow->set_ttl(tsd.get_pkt(), true);
 }
 
@@ -148,8 +148,8 @@ void TcpStreamSession::disable_reassembly(Flow* f)
     client.reassembler.purge_segment_list();
     server.reassembler.purge_segment_list();
 
-    client.flush_policy = STREAM_FLPOLICY_IGNORE;
-    server.flush_policy = STREAM_FLPOLICY_IGNORE;
+    client.set_flush_policy(STREAM_FLPOLICY_IGNORE);
+    server.set_flush_policy(STREAM_FLPOLICY_IGNORE);
 
     client.finalize_held_packet(f);
     server.finalize_held_packet(f);
@@ -159,10 +159,10 @@ uint8_t TcpStreamSession::get_reassembly_direction()
 {
     uint8_t dir = SSN_DIR_NONE;
 
-    if (server.get_flush_policy() != STREAM_FLPOLICY_IGNORE)
+    if ( server.get_flush_policy() != STREAM_FLPOLICY_IGNORE )
         dir |= SSN_DIR_FROM_CLIENT;
 
-    if (client.get_flush_policy() != STREAM_FLPOLICY_IGNORE)
+    if ( client.get_flush_policy() != STREAM_FLPOLICY_IGNORE )
         dir |= SSN_DIR_FROM_SERVER;
 
     return dir;
@@ -170,7 +170,7 @@ uint8_t TcpStreamSession::get_reassembly_direction()
 
 bool TcpStreamSession::is_sequenced(uint8_t dir)
 {
-    if (dir & SSN_DIR_FROM_CLIENT)
+    if ( dir & SSN_DIR_FROM_CLIENT )
     {
         if ( server.get_tf_flags() & ( TF_MISSING_PREV_PKT | TF_PKT_MISSED ) )
             return false;
@@ -189,24 +189,24 @@ bool TcpStreamSession::is_sequenced(uint8_t dir)
  * packet if reassembly for this direction was set mid-session */
 uint8_t TcpStreamSession::missing_in_reassembled(uint8_t dir)
 {
-    if (dir & SSN_DIR_FROM_CLIENT)
+    if ( dir & SSN_DIR_FROM_CLIENT )
     {
         if ( (server.get_tf_flags() & TF_MISSING_PKT)
-            && (server.get_tf_flags() & TF_MISSING_PREV_PKT))
+            && (server.get_tf_flags() & TF_MISSING_PREV_PKT) )
             return SSN_MISSING_BOTH;
-        else if (server.get_tf_flags() & TF_MISSING_PREV_PKT)
+        else if ( server.get_tf_flags() & TF_MISSING_PREV_PKT )
             return SSN_MISSING_BEFORE;
-        else if (server.get_tf_flags() & TF_MISSING_PKT)
+        else if ( server.get_tf_flags() & TF_MISSING_PKT )
             return SSN_MISSING_AFTER;
     }
-    else if (dir & SSN_DIR_FROM_SERVER)
+    else if ( dir & SSN_DIR_FROM_SERVER )
     {
-        if ((client.get_tf_flags() & TF_MISSING_PKT)
-            && (client.get_tf_flags() & TF_MISSING_PREV_PKT))
+        if ( (client.get_tf_flags() & TF_MISSING_PKT)
+            && (client.get_tf_flags() & TF_MISSING_PREV_PKT) )
             return SSN_MISSING_BOTH;
-        else if (client.get_tf_flags() & TF_MISSING_PREV_PKT)
+        else if ( client.get_tf_flags() & TF_MISSING_PREV_PKT )
             return SSN_MISSING_BEFORE;
-        else if (client.get_tf_flags() & TF_MISSING_PKT)
+        else if ( client.get_tf_flags() & TF_MISSING_PKT )
             return SSN_MISSING_AFTER;
     }
 
@@ -215,15 +215,15 @@ uint8_t TcpStreamSession::missing_in_reassembled(uint8_t dir)
 
 bool TcpStreamSession::are_packets_missing(uint8_t dir)
 {
-    if (dir & SSN_DIR_FROM_CLIENT)
+    if ( dir & SSN_DIR_FROM_CLIENT )
     {
-        if (server.get_tf_flags() & TF_PKT_MISSED)
+        if ( server.get_tf_flags() & TF_PKT_MISSED )
             return true;
     }
 
-    if (dir & SSN_DIR_FROM_SERVER)
+    if ( dir & SSN_DIR_FROM_SERVER )
     {
-        if (client.get_tf_flags() & TF_PKT_MISSED)
+        if ( client.get_tf_flags() & TF_PKT_MISSED )
             return true;
     }
 
@@ -232,62 +232,31 @@ bool TcpStreamSession::are_packets_missing(uint8_t dir)
 
 bool TcpStreamSession::add_alert(Packet* p, uint32_t gid, uint32_t sid)
 {
-    TcpStreamTracker& st = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ? server : client;
-    StreamAlertInfo* ai;
-
-    if (st.alert_count >= MAX_SESSION_ALERTS)
-        return false;
-
-    ai = st.alerts + st.alert_count;
-    ai->gid = gid;
-    ai->sid = sid;
-    ai->seq = 0;
-    ai->event_id = 0;
-    ai->event_second = 0;
-
-    st.alert_count++;
+    TcpReassemblerPolicy& trp = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ?
+        server.reassembler : client.reassembler;
 
-    return true;
+    return trp.add_alert(gid, sid);
 }
 
 bool TcpStreamSession::check_alerted(Packet* p, uint32_t gid, uint32_t sid)
 {
-    /* If this is not a rebuilt packet, no need to check further */
-    if (!(p->packet_flags & PKT_REBUILT_STREAM))
+    // only check alerts on rebuilt packets
+    if ( !(p->packet_flags & PKT_REBUILT_STREAM) )
         return false;
 
-    const TcpStreamTracker& st = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ? server : client;
-    for (int i = 0; i < st.alert_count; i++)
-    {
-        /*  This is a rebuilt packet and if we've seen this alert before,
-         *  return that we have previously alerted on original packet.
-         */
-        if (st.alerts[i].gid == gid && st.alerts[i].sid == sid)
-            return true;
-    }
+    TcpReassemblerPolicy& trp = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ?
+        server.reassembler : client.reassembler;
 
-    return false;
+    return trp.check_alerted(gid, sid);
 }
 
 int TcpStreamSession::update_alert(Packet* p, uint32_t gid, uint32_t sid,
     uint32_t event_id, uint32_t event_second)
 {
-    uint32_t seq_num = 0;
-    TcpStreamTracker& st = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ? server : client;
-
-    for (unsigned i = 0; i < st.alert_count; i++)
-    {
-        StreamAlertInfo* ai = &st.alerts[i];
+    TcpReassemblerPolicy& trp = p->ptrs.ip_api.get_src()->equals(flow->client_ip) ?
+        server.reassembler : client.reassembler;
 
-        if (ai->gid == gid && ai->sid == sid && SEQ_EQ(ai->seq, seq_num))
-        {
-            ai->event_id = event_id;
-            ai->event_second = event_second;
-            return 0;
-        }
-    }
-
-    return -1;
+    return trp.update_alert(gid, sid, event_id, event_second);
 }
 
 bool TcpStreamSession::set_packet_action_to_hold(Packet* p)
@@ -350,27 +319,10 @@ void TcpStreamSession::get_packet_header_foo(DAQ_PktHdr_t* pkth, uint32_t dir)
 
 void TcpStreamSession::reset()
 {
-    if (tcp_init)
+    if ( tcp_init )
         clear_session(true, false, false );
 }
 
-bool TcpStreamSession::setup(Packet*)
-{
-    client.init_tcp_state();
-    server.init_tcp_state();
-    lws_init = tcp_init = false;
-    generate_3whs_alert = true;
-    cleaning = false;
-    pkt_action_mask = ACTION_NOTHING;
-    ecn = 0;
-    ingress_index = egress_index = 0;
-    ingress_group = egress_group = 0;
-    daq_flags = address_space_id = 0;
-    tcp_config = nullptr;
-
-    return true;
-}
-
 void TcpStreamSession::cleanup(Packet* p)
 {
     if ( cleaning )
@@ -388,7 +340,6 @@ void TcpStreamSession::cleanup(Packet* p)
 void TcpStreamSession::clear()
 {
     if ( tcp_init )
-        // this does NOT flush data
         clear_session( true, false, false );
 
     TcpHAManager::process_deletion(*flow);
@@ -424,7 +375,5 @@ StreamSplitter* TcpStreamSession::get_splitter(bool to_server)
 }
 
 void TcpStreamSession::start_proxy()
-{
-    tcp_config->policy = StreamPolicy::OS_PROXY;
-}
+{ tcp_config->policy = StreamPolicy::OS_PROXY; }
 
index 7c1fbeecb7f4a6b17bae158bb477cbb7848ec566..b9aa98ccd109977eed7c9142a0197bc02bfbcaf5 100644 (file)
@@ -37,24 +37,23 @@ class TcpStreamSession : public Session
 public:
     ~TcpStreamSession() override;
 
-    bool setup(snort::Packet*) override;
     void clear() override;
     void cleanup(snort::Packet* = nullptr) override;
 
     void set_splitter(bool, snort::StreamSplitter*) override;
     snort::StreamSplitter* get_splitter(bool) override;
 
-    bool is_sequenced(uint8_t /*dir*/) override;
-    bool are_packets_missing(uint8_t /*dir*/) override;
+    bool is_sequenced(uint8_t dir) override;
+    bool are_packets_missing(uint8_t dir) override;
 
     void disable_reassembly(snort::Flow*) override;
     uint8_t get_reassembly_direction() override;
-    uint8_t missing_in_reassembled(uint8_t /*dir*/) override;
+    uint8_t missing_in_reassembled(uint8_t dir) override;
 
     bool add_alert(snort::Packet*, uint32_t gid, uint32_t sid) override;
     bool check_alerted(snort::Packet*, uint32_t gid, uint32_t sid) override;
-    int update_alert(snort::Packet*, uint32_t /*gid*/, uint32_t /*sid*/,
-        uint32_t /*event_id*/, uint32_t /*event_second*/) override;
+    int update_alert(snort::Packet*, uint32_t gid, uint32_t sid,
+        uint32_t event_id, uint32_t event_second) override;
 
     bool set_packet_action_to_hold(snort::Packet*) override;
 
@@ -68,17 +67,12 @@ public:
     void get_packet_header_foo(DAQ_PktHdr_t*, uint32_t dir);
     void set_no_ack(bool);
     bool no_ack_mode_enabled() { return no_ack; }
-
     virtual void update_perf_base_state(char) = 0;
     virtual void clear_session(
         bool free_flow_data, bool flush_segments, bool restart, snort::Packet* p = nullptr) = 0;
-
     virtual void flush() = 0;
-
     virtual TcpStreamTracker::TcpState get_talker_state(TcpSegmentDescriptor&) = 0;
-
     virtual TcpStreamTracker::TcpState get_listener_state(TcpSegmentDescriptor&) = 0;
-
     TcpStreamTracker::TcpState get_peer_state(TcpStreamTracker* me)
     { return me == &client ? server.get_tcp_state() : client.get_tcp_state(); }
 
@@ -127,10 +121,10 @@ public:
     bool generate_3whs_alert = true;
     TcpStreamConfig* tcp_config = nullptr;
     TcpEventLogger tel;
+    bool cleaning = false;
 
 private:
     bool no_ack = false;
-    bool cleaning = false;
 
 protected:
     TcpStreamSession(snort::Flow*);
index 93740df2cbd1d9a54a4bef924751bb7b18d12225..12bc51e1ed20004d704f44529a2f624f894e2814 100644 (file)
@@ -34,7 +34,6 @@
 
 #include "held_packet_queue.h"
 #include "segment_overlap_editor.h"
-#include "tcp_module.h"
 #include "tcp_normalizers.h"
 #include "tcp_reassemblers.h"
 #include "tcp_session.h"
@@ -95,16 +94,17 @@ TcpStreamTracker::TcpEvent TcpStreamTracker::set_tcp_event(const TcpSegmentDescr
             tcp_event = TCP_FIN_SENT_EVENT;
         else if ( tcph->is_ack() || tcph->is_psh() )
         {
-            if ( tsd.get_len() > 0 )
+            if ( tsd.is_data_segment() )
                 tcp_event = TCP_DATA_SEG_SENT_EVENT;
             else
                 tcp_event = TCP_ACK_SENT_EVENT;
         }
-        else if ( tsd.get_len() > 0 )   // FIXIT-H no flags set, how do we handle this?
-                                            // discard; drop if normalizing
-            tcp_event = TCP_DATA_SEG_SENT_EVENT;
         else
-            tcp_event = TCP_ACK_SENT_EVENT;
+        {
+            // count no flags set on the talker side...
+            tcpStats.no_flags_set++;
+            tcp_event = TCP_NO_FLAGS_EVENT;
+        }
     }
     else
     {
@@ -138,16 +138,15 @@ TcpStreamTracker::TcpEvent TcpStreamTracker::set_tcp_event(const TcpSegmentDescr
         }
         else if ( tcph->is_ack() || tcph->is_psh() )
         {
-            if ( tsd.get_len() > 0 )
+            if ( tsd.is_data_segment() )
                 tcp_event = TCP_DATA_SEG_RECV_EVENT;
             else
                 tcp_event = TCP_ACK_RECV_EVENT;
         }
-        else if ( tsd.get_len() > 0 )    // FIXIT-H no flags set, how do we handle this?
-                                             // discard; drop if normalizing
-            tcp_event = TCP_DATA_SEG_RECV_EVENT;
         else
-            tcp_event = TCP_ACK_RECV_EVENT;
+        {
+            tcp_event = TCP_NO_FLAGS_EVENT;
+        }
     }
 
     return tcp_event;
@@ -203,13 +202,14 @@ void TcpStreamTracker::init_tcp_state()
 {
     tcp_state = ( client_tracker ) ?
         TcpStreamTracker::TCP_STATE_NONE : TcpStreamTracker::TCP_LISTEN;
-    flush_policy = STREAM_FLPOLICY_IGNORE;
-    paf_setup(&paf_state);
+
     snd_una = snd_nxt = snd_wnd = 0;
-    rcv_nxt = r_win_base = iss = ts_last = ts_last_packet = 0;
-    small_seg_count = wscale = mss = 0;
+    rcv_nxt = r_win_base = iss = 0;
+    ts_last = ts_last_packet = 0;
+    small_seg_count = 0;
+    wscale = 0;
+    mss = 0;
     tf_flags = 0;
-    alert_count = 0;
     mac_addr_valid = false;
     fin_final_seq = 0;
     fin_seq_status = TcpStreamTracker::FIN_NOT_SEEN;
@@ -217,6 +217,8 @@ void TcpStreamTracker::init_tcp_state()
     rst_pkt_sent = false;
     order = 0;
     held_packet = null_iterator;
+    flush_policy = STREAM_FLPOLICY_IGNORE;
+    reassembler.setup_paf();
 }
 
 //-------------------------------------------------------------------------
@@ -225,7 +227,7 @@ void TcpStreamTracker::init_tcp_state()
 
 void TcpStreamTracker::init_flush_policy()
 {
-    if ( splitter == nullptr )
+    if ( !splitter )
         flush_policy = STREAM_FLPOLICY_IGNORE;
     else if ( normalizer.is_tcp_ips_enabled() )
         flush_policy = STREAM_FLPOLICY_ON_DATA;
@@ -244,7 +246,7 @@ void TcpStreamTracker::set_splitter(StreamSplitter* ss)
         flush_policy = STREAM_FLPOLICY_IGNORE;
     else
     {
-        paf_setup(&paf_state);
+        reassembler.setup_paf();
         reassembler.reset_paf_segment();
     }
 }
@@ -362,7 +364,6 @@ void TcpStreamTracker::init_on_3whs_ack_sent(TcpSegmentDescriptor& tsd)
     ts_last = tsd.get_timestamp();
     if (ts_last == 0)
         tf_flags |= TF_TSTAMP_ZERO;
-    tf_flags |= tsd.init_mss(&mss);
     tf_flags |= tsd.init_wscale(&wscale);
 
     cache_mac_address(tsd, FROM_CLIENT);
@@ -409,7 +410,7 @@ void TcpStreamTracker::init_on_data_seg_sent(TcpSegmentDescriptor& tsd)
     ts_last = tsd.get_timestamp();
     if (ts_last == 0)
         tf_flags |= TF_TSTAMP_ZERO;
-    tf_flags |= ( tsd.init_mss(&mss) | tsd.init_wscale(&wscale) );
+    tf_flags |= tsd.init_wscale(&wscale);
 
     cache_mac_address(tsd, tsd.get_direction() );
     tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
@@ -495,13 +496,6 @@ void TcpStreamTracker::update_tracker_no_ack_sent(TcpSegmentDescriptor& tsd)
 
 void TcpStreamTracker::update_tracker_ack_sent(TcpSegmentDescriptor& tsd)
 {
-    // ** this is how we track the last seq number sent
-    // as is l_unackd is the "last left" seq recvd
-    //snd_una = tsd.get_seg_seq();
-
-    // FIXIT-H add check to validate ack...
-    // norm/drop + discard
-
     if ( SEQ_GT(tsd.get_end_seq(), snd_nxt) )
         snd_nxt = tsd.get_end_seq();
 
@@ -520,9 +514,9 @@ void TcpStreamTracker::update_tracker_ack_sent(TcpSegmentDescriptor& tsd)
 
 bool TcpStreamTracker::update_on_3whs_ack(TcpSegmentDescriptor& tsd)
 {
-    bool good_ack = true;
+    bool good_ack = is_ack_valid(tsd.get_ack());
 
-    if ( is_ack_valid(tsd.get_ack()) )
+    if ( good_ack )
     {
         Flow* flow = tsd.get_flow();
 
@@ -533,22 +527,15 @@ bool TcpStreamTracker::update_on_3whs_ack(TcpSegmentDescriptor& tsd)
         flow->session_state |= ( STREAM_STATE_ACK | STREAM_STATE_ESTABLISHED );
         tcp_state = TcpStreamTracker::TCP_ESTABLISHED;
     }
-    else
-    {
-        inc_tcp_discards();
-        normalizer.trim_win_payload(tsd);
-        good_ack = false;
-    }
 
     return good_ack;
 }
 
 bool TcpStreamTracker::update_on_rst_recv(TcpSegmentDescriptor& tsd)
 {
-    bool good_rst = true;
-
     normalizer.trim_rst_payload(tsd);
-    if ( normalizer.validate_rst(tsd) )
+    bool good_rst = normalizer.validate_rst(tsd);
+    if ( good_rst )
     {
         Flow* flow = tsd.get_flow();
 
@@ -558,9 +545,9 @@ bool TcpStreamTracker::update_on_rst_recv(TcpSegmentDescriptor& tsd)
     }
     else
     {
-        inc_tcp_discards();
+        session->tel.set_tcp_event(EVENT_BAD_RST);
         normalizer.packet_dropper(tsd, NORM_TCP_BLOCK);
-        good_rst = false;
+        session->set_pkt_action_flag(ACTION_BAD_PKT);
     }
 
     return good_rst;
@@ -572,18 +559,6 @@ void TcpStreamTracker::update_on_rst_sent()
     rst_pkt_sent = true;
 }
 
-void TcpStreamTracker::flush_data_on_fin_recv(TcpSegmentDescriptor& tsd)
-{
-    if ( (flush_policy != STREAM_FLPOLICY_ON_ACK)
-        && (flush_policy != STREAM_FLPOLICY_ON_DATA)
-        && normalizer.is_tcp_ips_enabled())
-    {
-        tsd.set_packet_flags(PKT_PDU_TAIL);
-    }
-
-    reassembler.flush_on_data_policy(tsd.get_pkt());
-}
-
 bool TcpStreamTracker::update_on_fin_recv(TcpSegmentDescriptor& tsd)
 {
     if ( SEQ_LT(tsd.get_end_seq(), r_win_base) )
@@ -629,7 +604,7 @@ bool TcpStreamTracker::is_segment_seq_valid(TcpSegmentDescriptor& tsd)
     else
         left_seq = r_win_base;
 
-    if ( tsd.get_len() )
+    if ( tsd.is_data_segment() )
         right_ok = SEQ_GT(tsd.get_end_seq(), left_seq);
     else
         right_ok = SEQ_GEQ(tsd.get_end_seq(), left_seq);
@@ -639,24 +614,12 @@ bool TcpStreamTracker::is_segment_seq_valid(TcpSegmentDescriptor& tsd)
         uint32_t win = normalizer.get_stream_window(tsd);
 
         if ( SEQ_LEQ(tsd.get_seq(), r_win_base + win) )
-        {
             return true;
-        }
         else
-        {
             valid_seq = false;
-        }
     }
     else
-    {
         valid_seq = false;
-    }
-
-    if ( !valid_seq )
-    {
-        inc_tcp_discards();
-        normalizer.trim_win_payload(tsd);
-    }
 
     return valid_seq;
 }
index 4435bdc00b96e89ec1aa0999b55bcf7e998583c2..490c5650fbc3769e1b7adbd85745a54c0bb31940 100644 (file)
 
 #include "segment_overlap_editor.h"
 #include "tcp_defs.h"
+#include "tcp_module.h"
 #include "tcp_normalizers.h"
 #include "tcp_reassemblers.h"
 #include "tcp_segment_descriptor.h"
 
-/* Only track a maximum number of alerts per session */
-#define MAX_SESSION_ALERTS 8
-struct StreamAlertInfo
-{
-    /* For storing alerts that have already been seen on the session */
-    uint32_t sid;
-    uint32_t gid;
-    uint32_t seq;
-    // if we log extra data, event_* is used to correlate with alert
-    uint32_t event_id;
-    uint32_t event_second;
-};
-
 extern const char* tcp_state_names[];
 extern const char* tcp_event_names[];
 
@@ -91,6 +79,7 @@ public:
         TCP_FIN_RECV_EVENT,
         TCP_RST_SENT_EVENT,
         TCP_RST_RECV_EVENT,
+        TCP_NO_FLAGS_EVENT,
         TCP_MAX_EVENTS
     };
 
@@ -202,11 +191,14 @@ public:
 
     bool is_ack_valid(uint32_t cur)
     {
-        // If we haven't seen anything, ie, low & high are 0, return true
         if ( ( snd_una == 0 ) && ( snd_nxt == 0 ) )
             return true;
 
-        return ( SEQ_GEQ(cur, snd_una) && SEQ_LEQ(cur, snd_nxt) );
+        bool valid = SEQ_GEQ(cur, snd_una) && SEQ_LEQ(cur, snd_nxt);
+        if ( !valid )
+            tcpStats.invalid_ack++;
+
+        return valid;
     }
 
     // ack number must ack syn
@@ -252,18 +244,26 @@ public:
     bool is_rst_pkt_sent() const
     { return rst_pkt_sent; }
 
-    snort::StreamSplitter* get_splitter()
-    { return splitter; }
+    void set_flush_policy(FlushPolicy policy)
+    { flush_policy = policy; }
 
     FlushPolicy get_flush_policy()
     { return flush_policy; }
 
     virtual void init_tcp_state();
     virtual void init_flush_policy();
-
     virtual void set_splitter(snort::StreamSplitter* ss);
     virtual void set_splitter(const snort::Flow* flow);
 
+    snort::StreamSplitter* get_splitter()
+    { return splitter; }
+
+    bool is_splitter_paf() const
+    { return splitter && splitter->is_paf(); }
+
+    bool is_reassembly_enabled() const
+    { return  ( splitter and (flush_policy != STREAM_FLPOLICY_IGNORE) ); }
+
     virtual void init_on_syn_sent(TcpSegmentDescriptor&);
     virtual void init_on_syn_recv(TcpSegmentDescriptor&);
     virtual void init_on_synack_sent(TcpSegmentDescriptor&);
@@ -285,7 +285,6 @@ public:
     virtual bool update_on_fin_recv(TcpSegmentDescriptor&);
     virtual bool update_on_fin_sent(TcpSegmentDescriptor&);
     virtual bool is_segment_seq_valid(TcpSegmentDescriptor&);
-    virtual void flush_data_on_fin_recv(TcpSegmentDescriptor&);
     bool set_held_packet(snort::Packet*);
     bool is_retransmit_of_held_packet(snort::Packet*);
     void finalize_held_packet(snort::Packet*);
@@ -327,48 +326,30 @@ public:
 public:
     TcpNormalizerPolicy normalizer;
     TcpReassemblerPolicy reassembler;
-
-    StreamAlertInfo alerts[MAX_SESSION_ALERTS];
-
-    // this is intended to be private to paf but is included
-    // directly to avoid the need for allocation; do not directly
-    // manipulate within this module.
-    PAF_State paf_state;    // for tracking protocol aware flushing
-
     TcpSession* session = nullptr;
-    snort::StreamSplitter* splitter = nullptr;
-
-    FlushPolicy flush_policy = STREAM_FLPOLICY_IGNORE;
 
     uint32_t r_win_base = 0; // remote side window base sequence number (the last ack we got)
     uint32_t small_seg_count = 0;
-
-    uint16_t wscale = 0; /* window scale setting */
-    uint16_t mss = 0; /* max segment size */
-
-    uint8_t alert_count = 0;
     uint8_t order = 0;
-
     FinSeqNumStatus fin_seq_status = TcpStreamTracker::FIN_NOT_SEEN;
 
-    std::list<HeldPacket>::iterator held_packet;
 
 protected:
-    // FIXIT-H reorganize per-flow structs to minimize padding
+    static const std::list<HeldPacket>::iterator null_iterator;
+    std::list<HeldPacket>::iterator held_packet;
+    snort::StreamSplitter* splitter = nullptr;
     uint32_t ts_last_packet = 0;
-    uint32_t ts_last = 0; /* last timestamp (for PAWS) */
-
+    uint32_t ts_last = 0;       // last timestamp (for PAWS)
     uint32_t fin_final_seq = 0;
     uint32_t fin_seq_adjust = 0;
-
+    uint16_t mss = 0;           // max segment size
+    uint16_t wscale = 0;        // window scale setting
     uint16_t tf_flags = 0;
-
     uint8_t mac_addr[6] = { };
     uint8_t tcp_options_len = 0;
+    FlushPolicy flush_policy = STREAM_FLPOLICY_IGNORE;
     bool mac_addr_valid = false;
     bool fin_seq_set = false;  // FIXIT-M should be obviated by tcp state
-
-    static const std::list<HeldPacket>::iterator null_iterator;
 };
 
 // <--- note -- the 'state' parameter must be a reference