]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2189 in SNORT/snort3 from ~DAVMCPHE/snort3:fallback to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 15 May 2020 21:40:47 +0000 (21:40 +0000)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 15 May 2020 21:40:47 +0000 (21:40 +0000)
Squashed commit of the following:

commit 0031d861c9c23b1a08e27a77d10d8ee68f4f7fb4
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Fri May 1 13:23:54 2020 -0400

    dce_rpc: code style cleanups

commit 5a9614634d99202a0202494b6021116edea1d7e4
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Wed Apr 29 11:24:49 2020 -0400

    dce_rpc: generate alert when dce splitter aborts due to invalid fragment length

commit 75e56ee0f0a6e875c13de32963b58f15e3c43c7f
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Fri May 8 17:16:47 2020 -0400

    stream_tcp: call splitter->finish() before reassemble() when flushing when PAF aborts due to gap in queued data

commit 39336beb1c4421ebb2124a2beb20ae1c8a5ae9b1
Author: russ <rucombs@cisco.com>
Date:   Tue Apr 21 14:20:50 2020 -0400

    stream_tcp: clear gadget from Flow object once fallback has happened in both directions

    stream_tcp: when paf aborts due to gap in data set splitter state to ABORT

    stream_tcp: only clear gadget after both splitters have aborted

    loggers: when logging alert only use inspector buffers and name when the inspector's paf splitter is assigned for the direction of the alert"

18 files changed:
src/log/log_text.cc
src/log/log_text.h
src/loggers/alert_fast.cc
src/service_inspectors/dce_rpc/dce_tcp_paf.cc
src/stream/paf.cc
src/stream/stream.h
src/stream/tcp/segment_overlap_editor.h
src/stream/tcp/stream_tcp.cc
src/stream/tcp/tcp_defs.h
src/stream/tcp/tcp_module.cc
src/stream/tcp/tcp_module.h
src/stream/tcp/tcp_normalizers.cc
src/stream/tcp/tcp_reassembler.cc
src/stream/tcp/tcp_reassembler.h
src/stream/tcp/tcp_segment_node.cc
src/stream/tcp/tcp_session.cc
src/stream/tcp/tcp_session.h
src/stream/tcp/tcp_stream_session.cc

index 0c72dbc443496ad3c438fc76888cf45607501235..cbab0915a2583552b0f8be9ae7c1e5f6023f2ac2 100644 (file)
@@ -1160,7 +1160,8 @@ static void obfuscate(Packet* p, const uint8_t* data, int& ip_ob_start, int& ip_
 }
 
 void LogNetData(
-    TextLog* log, const uint8_t* data, const int len, Packet* p, const char* buf_name)
+        TextLog* log, const uint8_t* data, const int len, Packet* p, const char* buf_name,
+        const char* ins_name)
 {
     if ( !len )
         return;
@@ -1177,7 +1178,9 @@ void LogNetData(
 
     const HexAsciiLayout& hal = SnortConfig::get_conf()->output_wide_hex() ? hal_wide : hal_std;
     const char* hdr_off = SnortConfig::verbose_byte_dump() ? hal.offset_hdr : "";
-    const char* ins_name = p->flow and p->flow->gadget ?  p->flow->gadget->get_name() : "snort";
+
+    if ( !ins_name )
+        ins_name = p->flow and p->flow->gadget ?  p->flow->gadget->get_name() : "snort";
 
     TextLog_Print(log, "\n%s.%s[%u]:\n", ins_name, buf_name, len);
     TextLog_Print(log, "%s%s\n", hdr_off, hal.separator);
index d924501ecd076a504b1eb7f524b0d59f2db803c8..6a887640adb19e568834f9adef47b95d589a9d6d 100644 (file)
@@ -43,7 +43,8 @@ SO_PUBLIC void LogPayload(TextLog*, Packet*);
 SO_PUBLIC bool LogAppID(TextLog*, Packet*);
 
 SO_PUBLIC void LogNetData(
-    TextLog*, const uint8_t* data, const int len, Packet*, const char* buf_name = nullptr);
+        TextLog*, const uint8_t* data, const int len, Packet*, const char* buf_name = nullptr,
+        const char* ins_name = nullptr);
 
 SO_PUBLIC void Log2ndHeader(TextLog*, Packet*);
 SO_PUBLIC void LogTCPHeader(TextLog*, Packet*);
index 7ffd70ee6bc46d0556ebe3a28b023dca0948ea7c..7f1a4383704b75f9160e75cd538b489a6a7264ad 100644 (file)
@@ -42,6 +42,8 @@
 #include "detection/detection_engine.h"
 #include "detection/signature.h"
 #include "events/event.h"
+#include "flow/flow.h"
+#include "flow/session.h"
 #include "framework/logger.h"
 #include "framework/module.h"
 #include "log/log_text.h"
@@ -52,6 +54,7 @@
 #include "packet_io/active.h"
 #include "packet_io/sfdaq.h"
 #include "service_inspectors/http_inspect/http_enum.h"
+#include "stream/stream_splitter.h"
 
 using namespace snort;
 using namespace std;
@@ -255,7 +258,18 @@ void FastLogger::log_data(Packet* p, const Event& event)
     bool log_pkt = true;
 
     TextLog_NewLine(fast_log);
-    Inspector* gadget = p->flow ? p->flow->gadget : nullptr;
+    const char* ins_name = "snort";
+    Inspector* gadget = nullptr;
+    if ( p->flow and p->flow->session )
+    {
+        snort::StreamSplitter* ss = p->flow->session->get_splitter(p->is_from_client());
+        if ( ss and ss->is_paf() )
+        {
+            gadget = p->flow->gadget;
+            if ( gadget )
+                ins_name = gadget->get_name();
+        }
+    }
     const char** buffers = gadget ? gadget->get_api()->buffers : nullptr;
 
     if ( buffers )
@@ -269,7 +283,7 @@ void FastLogger::log_data(Packet* p, const Event& event)
         {
 
             if ( gadget->get_buf(id, p, buf) )
-                LogNetData(fast_log, buf.data, buf.len, p, buffers[id-1]);
+                LogNetData(fast_log, buf.data, buf.len, p, buffers[id-1], ins_name);
 
             log_pkt = rsp;
         }
@@ -279,13 +293,13 @@ void FastLogger::log_data(Packet* p, const Event& event)
         InspectionBuffer buf;
 
         if ( gadget->get_buf(InspectionBuffer::IBT_KEY, p, buf) )
-            LogNetData(fast_log, buf.data, buf.len, p);
+            LogNetData(fast_log, buf.data, buf.len, p, nullptr, ins_name);
 
         if ( gadget->get_buf(InspectionBuffer::IBT_HEADER, p, buf) )
-            LogNetData(fast_log, buf.data, buf.len, p);
+            LogNetData(fast_log, buf.data, buf.len, p, nullptr, ins_name);
 
         if ( gadget->get_buf(InspectionBuffer::IBT_BODY, p, buf) )
-            LogNetData(fast_log, buf.data, buf.len, p);
+            LogNetData(fast_log, buf.data, buf.len, p, nullptr, ins_name);
     }
     if (p->has_ip())
         LogIPPkt(fast_log, p);
@@ -298,10 +312,10 @@ void FastLogger::log_data(Packet* p, const Event& event)
         for ( const auto& b : *p->obfuscator )
             buf.replace(b.offset, b.length, b.length, p->obfuscator->get_mask_char());
 
-        LogNetData(fast_log, (const uint8_t*)buf.c_str(), p->dsize, p);
+        LogNetData(fast_log, (const uint8_t*)buf.c_str(), p->dsize, p, nullptr, ins_name);
     }
     else if ( log_pkt )
-        LogNetData(fast_log, p->data, p->dsize, p);
+        LogNetData(fast_log, p->data, p->dsize, p, nullptr, ins_name);
 
     DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
 
index 374816ef39025f08f761d798c31bdb6934e1f02a..fea8cb9a3887993aea7c0e217764ea3e4f3cfb6c 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "dce_tcp_paf.h"
 
+#include "dce_common.h"
 #include "dce_tcp.h"
 
 using namespace snort;
@@ -43,75 +44,70 @@ using namespace snort;
 static StreamSplitter::Status dce2_tcp_paf(DCE2_PafTcpData* ds, Flow* flow, const uint8_t* data,
     uint32_t len, uint32_t flags, uint32_t* fp)
 {
-    uint32_t n = 0;
-    int start_state;
-    StreamSplitter::Status ps = StreamSplitter::SEARCH;
-    uint32_t tmp_fp = 0;
     DCE2_TcpSsnData* sd = get_dce2_tcp_session_data(flow);
-
-    int num_requests = 0;
-
     if ( dce2_paf_abort((DCE2_SsnData*)sd) )
-    {
         return StreamSplitter::ABORT;
-    }
 
-    if (sd == nullptr)
+    if ( !sd )
     {
         bool autodetected = false;
-        if (len >= sizeof(DceRpcCoHdr))
+        if ( len >= sizeof(DceRpcCoHdr) )
         {
             const DceRpcCoHdr* co_hdr = (const DceRpcCoHdr*)data;
 
-            if ((DceRpcCoVersMaj(co_hdr) == DCERPC_PROTO_MAJOR_VERS__5)
+            if ( (DceRpcCoVersMaj(co_hdr) == DCERPC_PROTO_MAJOR_VERS__5)
                 && (DceRpcCoVersMin(co_hdr) == DCERPC_PROTO_MINOR_VERS__0)
                 && (((flags & PKT_FROM_CLIENT)
                         && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND)
                     || ((flags & PKT_FROM_SERVER)
                         && DceRpcCoPduType(co_hdr) == DCERPC_PDU_TYPE__BIND_ACK))
-                && (DceRpcCoFragLen(co_hdr) >= sizeof(DceRpcCoHdr)))
+                && (DceRpcCoFragLen(co_hdr) >= sizeof(DceRpcCoHdr)) )
             {
                 autodetected = true;
             }
         }
-        else if ((*data == DCERPC_PROTO_MAJOR_VERS__5) && (flags & PKT_FROM_CLIENT))
+        else if ( (*data == DCERPC_PROTO_MAJOR_VERS__5) && (flags & PKT_FROM_CLIENT) )
         {
             autodetected = true;
         }
 
-        if (!autodetected)
-        {
+        if ( !autodetected )
             return StreamSplitter::ABORT;
-        }
     }
 
-    start_state = (uint8_t)ds->paf_state;
-
-    while (n < len)
+    int start_state = (uint8_t)ds->paf_state;
+    int num_requests = 0;
+    uint32_t tmp_fp = 0;
+    uint32_t n = 0;
+    while ( n < len )
     {
-        switch (ds->paf_state)
+        switch ( ds->paf_state )
         {
         case DCE2_PAF_TCP_STATES__4:      // Get byte order
             ds->byte_order = DceRpcByteOrder(data[n]);
             ds->paf_state = (DCE2_PafTcpStates)(((int)ds->paf_state) + 1);
             break;
+
         case DCE2_PAF_TCP_STATES__8:
-            if (ds->byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN)
+            if ( ds->byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN )
                 ds->frag_len = data[n];
             else
                 ds->frag_len = data[n] << 8;
             ds->paf_state = (DCE2_PafTcpStates)(((int)ds->paf_state) + 1);
             break;
+
         case DCE2_PAF_TCP_STATES__9:
-            if (ds->byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN)
+            if ( ds->byte_order == DCERPC_BO_FLAG__LITTLE_ENDIAN )
                 ds->frag_len |= data[n] << 8;
             else
                 ds->frag_len |= data[n];
 
             /* If we get a bad frag length abort */
-            if (ds->frag_len < sizeof(DceRpcCoHdr))
+            if ( ds->frag_len < sizeof(DceRpcCoHdr) )
             {
-                return StreamSplitter::ABORT;
+               if ( sd )
+                    dce_alert(GID_DCE2, DCE2_CO_FRAG_LEN_LT_HDR, (dce2CommonStats*)&dce2_tcp_stats, *(DCE2_SsnData*)sd);
+               return StreamSplitter::ABORT;
             }
 
             /* Increment n here so we can continue */
@@ -119,11 +115,12 @@ static StreamSplitter::Status dce2_tcp_paf(DCE2_PafTcpData* ds, Flow* flow, cons
             num_requests++;
             /* Might have multiple PDUs in one segment.  If the last PDU is partial,
              * flush just before it */
-            if ((num_requests == 1) || (n <= len))
+            if ( (num_requests == 1) || (n <= len) )
                 tmp_fp += ds->frag_len;
 
             ds->paf_state = DCE2_PAF_TCP_STATES__0;
             continue;      // we incremented n already
+
         default:
             ds->paf_state = (DCE2_PafTcpStates)(((int)ds->paf_state) + 1);
             break;
@@ -132,13 +129,13 @@ static StreamSplitter::Status dce2_tcp_paf(DCE2_PafTcpData* ds, Flow* flow, cons
         n++;
     }
 
-    if (tmp_fp != 0)
+    if ( tmp_fp != 0 )
     {
         *fp = tmp_fp - start_state;
         return StreamSplitter::FLUSH;
     }
 
-    return ps;
+    return StreamSplitter::SEARCH;
 }
 
 Dce2TcpSplitter::Dce2TcpSplitter(bool c2s) : StreamSplitter(c2s)
index a78be030aecea48812121db43fb312827a99893e..c6f0d3a17c462cfa3106d4916ca8f352a923f735 100644 (file)
@@ -134,7 +134,6 @@ static bool paf_callback (
     const uint8_t* data, uint32_t len, uint32_t flags)
 {
     ps->fpt = 0;
-
     ps->paf = ss->scan(pkt, data, len, flags, &ps->fpt);
 
     if ( ps->paf == StreamSplitter::ABORT )
@@ -143,7 +142,6 @@ static bool paf_callback (
     if ( ps->paf != StreamSplitter::SEARCH )
     {
         ps->fpt += px.idx;
-
         if ( ps->fpt <= px.len )
         {
             px.idx = ps->fpt;
@@ -164,9 +162,8 @@ static inline bool paf_eval (
     {
     case StreamSplitter::SEARCH:
         if ( px.len > px.idx )
-        {
             return paf_callback(ss, ps, px, pkt, data, len, flags);
-        }
+
         return false;
 
     case StreamSplitter::FLUSH:
@@ -202,6 +199,7 @@ static inline bool paf_eval (
                 uint32_t delta = ps->fpt - px.idx;
                 if ( delta > len )
                     return false;
+
                 data += delta;
                 len -= delta;
             }
@@ -270,9 +268,11 @@ int32_t paf_check (
         {
             ps->fpt = 0;
             px.ft = FT_MAX;
+            ps->paf = StreamSplitter::ABORT;
             return paf_flush(ps, px, flags);
         }
         *flags = 0;
+        ps->paf = StreamSplitter::ABORT;
         return -1;
     }
     else if ( SEQ_LEQ(seq + len, ps->seq) )
@@ -285,8 +285,8 @@ int32_t paf_check (
         data += shift;
         len -= shift;
     }
-    ps->seq += len;
 
+    ps->seq += len;
     px.idx = total - len;
 
     // if 'total' is greater than the maximum paf_max AND 'total' is greater
@@ -306,9 +306,7 @@ int32_t paf_check (
         len = len + px.len - total;
     }
     else
-    {
         px.len = total;
-    }
 
     do
     {
@@ -323,6 +321,7 @@ int32_t paf_check (
             paf_jump(ps, fp);
             return fp;
         }
+
         if ( !cont )
             break;
 
index 152d6b6d7a65091e3cb4d4a26d6a30d6d71c5ac9..1c89fcbca7d10eb6987dcb2b7fe4601d8445f498 100644 (file)
@@ -26,7 +26,6 @@
 
 #include "flow/flow.h"
 
-
 struct HostAttributeEntry;
 
 namespace snort
index 52320928517625b89bc8ab677869ef07cd56b022..813f0a94b30407a2d0c1561d8e1b17a4806d630a 100644 (file)
@@ -64,9 +64,7 @@ struct SegmentOverlapState
     bool keep_segment;
 
     ~SegmentOverlapState()
-    {
-        seglist.reset();
-    }
+    { seglist.reset(); }
 
     void init_sos(TcpSession*, StreamPolicy);
     void init_soe(TcpSegmentDescriptor& tsd, TcpSegmentNode* left, TcpSegmentNode* right);
index cd628153360878a08982ef4df98248e1f776eda2..ba647e0d5fb52f6397c23fcd32fb7fdf602963f4 100644 (file)
@@ -54,7 +54,9 @@ public:
     TcpStreamConfig* const config;
 };
 
-StreamTcp::StreamTcp (TcpStreamConfig* c) : config(c) {}
+StreamTcp::StreamTcp (TcpStreamConfig* c)
+    : config(c)
+{ }
 
 StreamTcp::~StreamTcp()
 { delete config; }
index f1135c593951cb08e24fddfdbcb10c054c7a883b..23af99b072d1e96b2340456a0c96d66b02737b9b 100644 (file)
@@ -30,40 +30,33 @@ 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 TF_NONE                     0x0000
-#define TF_WSCALE                   0x0001
-#define TF_TSTAMP                   0x0002
-#define TF_TSTAMP_ZERO              0x0004
-#define TF_MSS                      0x0008
-#define TF_FORCE_FLUSH              0x0010
-#define TF_PKT_MISSED               0x0020  // sticky
-#define TF_MISSING_PKT              0x0040  // used internally
-#define TF_MISSING_PREV_PKT         0x0080  // reset for each reassembled
+#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 TF_NONE             0x0000
+#define TF_WSCALE           0x0001
+#define TF_TSTAMP           0x0002
+#define TF_TSTAMP_ZERO      0x0004
+#define TF_MSS              0x0008
+#define TF_FORCE_FLUSH      0x0010
+#define TF_PKT_MISSED       0x0020  // sticky
+#define TF_MISSING_PKT      0x0040  // used internally
+#define TF_MISSING_PREV_PKT 0x0080  // reset for each reassembled
 
 #define PAWS_WINDOW         60
 #define PAWS_24DAYS         2073600         /* 24 days in seconds */
 
-#define SUB_STATE_NONE 0x00
-#define SUB_SYN_SENT  0x01
-#define SUB_ACK_SENT  0x02
-#define SUB_SETUP_OK  0x03
-#define SUB_RST_SENT  0x04
-#define SUB_FIN_SENT  0x08
-
 #define STREAM_UNALIGNED       0
 #define STREAM_ALIGNED         1
 
index a36d0248cb6732a874e92c68af988355deb355d9..d5bdc687ddfc82d4c5a5530812c2bb9dae6ef6f6 100644 (file)
@@ -86,6 +86,8 @@ const PegInfo tcp_pegs[] =
     { CountType::MAX, "max_packets_held", "maximum number of packets held simultaneously" },
     { CountType::SUM, "partial_flushes", "number of partial flushes initiated" },
     { CountType::SUM, "partial_flush_bytes", "partial flush total bytes" },
+    { CountType::SUM, "inspector_fallbacks", "count of fallbacks from assigned service inspector" },
+    { CountType::SUM, "partial_fallbacks", "count of fallbacks from assigned service stream splitter" },
     { CountType::END, nullptr, nullptr }
 };
 
index 03a98a81c892d3d676595dc37a189dfe3010c044..fd84df72f8911c31773c46a61483207b19c2bf03 100644 (file)
@@ -73,9 +73,9 @@ struct TcpStats
     PegCount segs_released;
     PegCount segs_split;
     PegCount segs_used;
-    PegCount rebuilt_packets;   //iStreamFlushes
+    PegCount rebuilt_packets;
     PegCount rebuilt_buffers;
-    PegCount rebuilt_bytes;     //total_rebuilt_bytes
+    PegCount rebuilt_bytes;
     PegCount overlaps;
     PegCount gaps;
     PegCount exceeded_max_segs;
@@ -100,6 +100,8 @@ struct TcpStats
     PegCount max_packets_held;
     PegCount partial_flushes;
     PegCount partial_flush_bytes;
+    PegCount inspector_fallbacks;
+    PegCount partial_fallbacks;
 };
 
 extern THREAD_LOCAL struct TcpStats tcpStats;
index 3de56b1dace6f5dcd6682e291af3f373b9d3e489..3e71fe2163f53719c394494b7be67164071798a7 100644 (file)
@@ -186,7 +186,7 @@ static inline int handle_repeated_syn_mswin(
     /* Windows has some strange behavior here.  If the sequence of the reset is the
      * next expected sequence, it Resets.  Otherwise it ignores the 2nd SYN.
      */
-    if (SEQ_EQ(tsd.get_seg_seq(), listener->rcv_nxt))
+    if ( SEQ_EQ(tsd.get_seg_seq(), listener->rcv_nxt) )
     {
         session->flow->set_session_flags(SSNFLAG_RESET);
         talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
@@ -203,7 +203,7 @@ static inline int handle_repeated_syn_bsd(
     TcpStreamTracker* talker, const TcpSegmentDescriptor& tsd, TcpStreamSession* session)
 {
     /* If its not a retransmission of the actual SYN... RESET */
-    if (!SEQ_EQ(tsd.get_seg_seq(), talker->get_iss()))
+    if ( !SEQ_EQ(tsd.get_seg_seq(), talker->get_iss()) )
     {
         session->flow->set_session_flags(SSNFLAG_RESET);
         talker->set_tcp_state(TcpStreamTracker::TCP_CLOSED);
@@ -222,7 +222,7 @@ static inline bool paws_3whs_zero_ts_not_supported(
 {
     bool check_ts = true;
 
-    if (talker->get_tf_flags() & TF_TSTAMP_ZERO)
+    if ( talker->get_tf_flags() & TF_TSTAMP_ZERO )
     {
         talker->clear_tf_flags(TF_TSTAMP);
         listener->clear_tf_flags(TF_TSTAMP);
@@ -258,7 +258,7 @@ static inline uint16_t set_urg_offset_linux(const tcp::TCPHdr* tcph, uint16_t ds
 {
     uint16_t urg_offset = 0;
 
-    if (tcph->are_flags_set(TH_URG) )
+    if ( tcph->are_flags_set(TH_URG) )
     {
         urg_offset = tcph->urp();
 
@@ -369,8 +369,8 @@ bool TcpNormalizerHpux11::is_paws_ts_checked_required(
     TcpNormalizerState& tns, TcpSegmentDescriptor& tsd)
 {
     /* HPUX 11 ignores timestamps for out of order segments */
-    if ((tns.tracker->get_tf_flags() & TF_MISSING_PKT) || !SEQ_EQ(tns.tracker->rcv_nxt,
-        tsd.get_seg_seq()))
+    if ( (tns.tracker->get_tf_flags() & TF_MISSING_PKT) || !SEQ_EQ(tns.tracker->rcv_nxt,
+        tsd.get_seg_seq()) )
         return false;
     else
         return true;
index ebaf449555ce7971dcb842993826a63431bb7768..7b39d13fcfdecfb6d553eb8a985a41e26acad755 100644 (file)
@@ -416,7 +416,6 @@ int TcpReassembler::flush_data_segments(
         {
             pdu->data = sb.data;
             pdu->dsize = sb.length;
-            assert(sb.length <= Packet::max_dsize);
         }
 
         total_flushed += bytes_copied;
@@ -546,13 +545,12 @@ int TcpReassembler::_flush_to_seq(
         if ( footprint == 0 )
             return bytes_processed;
 
-        if ( footprint > Packet::max_dsize )
-            /* this is as much as we can pack into a stream buffer */
+        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 ) )
-            fallback(trs);
+            fallback(*trs.tracker, trs.server_side);
 
         Packet* pdu = initialize_pdu(trs, p, pkt_flags, trs.sos.seglist.cur_rseg->tv);
         int32_t flushed_bytes = flush_data_segments(trs, p, footprint, pdu);
@@ -942,16 +940,36 @@ int32_t TcpReassembler::flush_pdu_ips(TcpReassemblerState& trs, uint32_t* flags,
     return -1;
 }
 
-void TcpReassembler::fallback(TcpReassemblerState& trs)
+static inline bool both_splitters_aborted(Flow* flow)
 {
-    bool c2s = trs.tracker->splitter->to_server();
+    uint32_t both_splitters_yoinked = (SSNFLAG_ABORT_CLIENT | SSNFLAG_ABORT_SERVER);
+    return (flow->get_session_flags() & both_splitters_yoinked) == both_splitters_yoinked;
+}
+
+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;
+    ++tcpStats.partial_fallbacks;
+}
 
-    delete trs.tracker->splitter;
-    trs.tracker->splitter = new AtomSplitter(c2s, trs.sos.session->config->paf_max);
-    trs.tracker->paf_state.paf = StreamSplitter::SEARCH;
+void TcpReassembler::fallback(TcpStreamTracker& tracker, bool server_side)
+{
+    uint16_t max = tracker.session->config->paf_max;
+    ::fallback(tracker, server_side, max);
 
-    trs.sos.session->flow->set_session_flags(
-        c2s ? SSNFLAG_ABORT_CLIENT : SSNFLAG_ABORT_SERVER );
+    Flow* flow = tracker.session->flow;
+    if ( server_side )
+        flow->set_session_flags(SSNFLAG_ABORT_SERVER);
+    else
+        flow->set_session_flags(SSNFLAG_ABORT_CLIENT);
+
+    if ( flow->gadget and both_splitters_aborted(flow) )
+    {
+        flow->clear_gadget();
+        ++tcpStats.inspector_fallbacks;
+    }
 }
 
 // iterate over trs.sos.seglist and scan all new acked bytes
@@ -1067,7 +1085,7 @@ int TcpReassembler::flush_on_data_policy(TcpReassemblerState& trs, Packet* p)
 
         if ( !flags && trs.tracker->splitter->is_paf() )
         {
-            fallback(trs);
+            fallback(*trs.tracker, trs.server_side);
             return flush_on_data_policy(trs, p);
         }
     }
@@ -1111,9 +1129,12 @@ int TcpReassembler::flush_on_ack_policy(TcpReassemblerState& trs, Packet* p)
 
         while (flush_amt >= 0)
         {
-            if (!flush_amt)
+            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);
+
             // for consistency with other cases, should return total
             // but that breaks flushing pipelined pdus
             flushed = flush_to_seq(trs, flush_amt, p, flags);
@@ -1129,9 +1150,10 @@ int TcpReassembler::flush_on_ack_policy(TcpReassemblerState& trs, Packet* p)
                 break;  // bail if nothing flushed
         }
 
-        if (!flags && trs.tracker->splitter->is_paf())
+        if ( (trs.tracker->paf_state.paf == StreamSplitter::ABORT) &&
+            (trs.tracker->splitter && trs.tracker->splitter->is_paf()) )
         {
-            fallback(trs);
+            fallback(*trs.tracker, trs.server_side);
             return flush_on_ack_policy(trs, p);
         }
     }
index 6bfc0e566c05015ed08c99f1dd74f4e7ad0d8b4e..81ed91cf00cc097b069b50e826b544aa23cfc6cb 100644 (file)
@@ -81,7 +81,7 @@ protected:
     uint32_t get_reverse_packet_dir(TcpReassemblerState&, const snort::Packet*);
     uint32_t get_forward_packet_dir(TcpReassemblerState&, const snort::Packet*);
     int32_t flush_pdu_ips(TcpReassemblerState&, uint32_t*, snort::Packet*);
-    void fallback(TcpReassemblerState&);
+    void fallback(TcpStreamTracker&, bool server_side);
     int32_t flush_pdu_ackd(TcpReassemblerState&, uint32_t* flags, snort::Packet*);
     void purge_to_seq(TcpReassemblerState&, uint32_t flush_seq);
 
index 13eaa1d4413a61315d4d88fc7ff6e6228727a894..35c75acb8dd8ee2b95a7341b6c26bd125da20e57 100644 (file)
@@ -140,11 +140,9 @@ bool TcpSegmentNode::is_retransmit(const uint8_t* rdata, uint16_t rsize,
 
     if ( orig_dsize == c_len )
     {
-        if ( ( ( c_len <= rsize )and !memcmp(data, rdata, c_len) )
-            or ( ( c_len > rsize )and !memcmp(data, rdata, rsize) ) )
-        {
+        uint16_t cmp_len = ( c_len <= rsize ) ? c_len : rsize;
+        if ( !memcmp(data, rdata, cmp_len) )
             return true;
-        }
     }
     //Checking for a possible split of segment in which case
     //we compare complete data of the segment to find a retransmission
index 62ca780dc9b25558eac6f7e35683e770a6ca3dd0..5d06521d09db321281da3257066243d7dd88bd93 100644 (file)
@@ -498,7 +498,7 @@ void TcpSession::swap_trackers()
 }
 #endif
 
-void TcpSession::NewTcpSessionOnSyn(TcpSegmentDescriptor& tsd)
+void TcpSession::init_session_on_syn(TcpSegmentDescriptor& tsd)
 {
     server.init_on_syn_recv(tsd);
     client.init_on_syn_sent(tsd);
@@ -506,7 +506,7 @@ void TcpSession::NewTcpSessionOnSyn(TcpSegmentDescriptor& tsd)
     tcpStats.sessions_on_syn++;
 }
 
-void TcpSession::NewTcpSessionOnSynAck(TcpSegmentDescriptor& tsd)
+void TcpSession::init_session_on_synack(TcpSegmentDescriptor& tsd)
 {
     server.init_on_synack_sent(tsd);
     client.init_on_synack_recv(tsd);
@@ -552,26 +552,26 @@ bool TcpSession::handle_syn_on_reset_session(TcpSegmentDescriptor& tsd)
             pkt_action_mask |= ACTION_RST;
             return false;
         }
-        else if (tcph->is_syn_only())
+        else if ( tcph->is_syn_only() )
         {
             flow->ssn_state.direction = FROM_CLIENT;
             flow->session_state = STREAM_STATE_SYN;
             flow->set_ttl(tsd.get_pkt(), true);
-            NewTcpSessionOnSyn(tsd);
+            init_session_on_syn(tsd);
             tcpStats.resyns++;
             listener = &server;
             talker = &client;
             listener->normalizer.ecn_tracker(tcph, config->require_3whs());
             flow->update_session_flags(SSNFLAG_SEEN_CLIENT);
         }
-        else if (tcph->is_syn_ack())
+        else if ( tcph->is_syn_ack() )
         {
             if (config->midstream_allowed(tsd.get_pkt()))
             {
                 flow->ssn_state.direction = FROM_SERVER;
                 flow->session_state = STREAM_STATE_SYN_ACK;
                 flow->set_ttl(tsd.get_pkt(), false);
-                NewTcpSessionOnSynAck(tsd);
+                init_session_on_synack(tsd);
                 tcpStats.resyns++;
             }
 
@@ -868,7 +868,7 @@ void TcpSession::flush_tracker(
          return;
 
      tracker.set_tf_flags(TF_FORCE_FLUSH);
-     if ( tracker.reassembler.flush_stream(p, dir) )
+     if ( tracker.reassembler.flush_stream(p, dir, final_flush) )
          tracker.reassembler.purge_flushed_ackd();
 
      tracker.clear_tf_flags(TF_FORCE_FLUSH);
index c23fd1f70c02fd95d6d27fd61b372d8d42c9238a..c8cd67cb8d2db710a4d8419d73d16b279a827094 100644 (file)
@@ -76,9 +76,8 @@ private:
     void process_tcp_stream(TcpSegmentDescriptor&);
     int process_tcp_data(TcpSegmentDescriptor&);
     void swap_trackers();
-    void NewTcpSessionOnSyn(TcpSegmentDescriptor&);
-    void NewTcpSessionOnSynAck(TcpSegmentDescriptor&);
-    int process_dis(snort::Packet*);
+    void init_session_on_syn(TcpSegmentDescriptor&);
+    void init_session_on_synack(TcpSegmentDescriptor&);
     void update_on_3whs_complete(TcpSegmentDescriptor&);
     bool is_flow_handling_packets(snort::Packet*);
     void cleanup_session_if_expired(snort::Packet*);
index a5b2cbe815c58ba9cb3309cbbf696986be5df983..db3ec77aa878bbbbbeabd46c61950dba12918ffd 100644 (file)
@@ -109,7 +109,7 @@ void TcpStreamSession::update_session_on_server_packet(TcpSegmentDescriptor& tsd
 
 void TcpStreamSession::update_session_on_client_packet(TcpSegmentDescriptor& tsd)
 {
-    /* if we got here we had to see the SYN already... */
+    /* if we got here we have seen the SYN already... */
     flow->set_session_flags(SSNFLAG_SEEN_CLIENT);
     talker = &client;
     listener = &server;