]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
properly instantiate prune / purge packet
authorRuss Combs <rucombs@cisco.com>
Thu, 3 Nov 2016 00:38:40 +0000 (20:38 -0400)
committerRuss Combs <rucombs@cisco.com>
Wed, 18 Jan 2017 16:46:37 +0000 (11:46 -0500)
18 files changed:
src/codecs/ip/cd_ipv4.cc
src/detection/detection_engine.cc
src/detection/detection_engine.h
src/detection/fp_detect.cc
src/events/sfeventq.cc
src/events/sfeventq.h
src/flow/flow.cc
src/flow/flow_cache.cc
src/flow/session.h
src/service_inspectors/http_inspect/http_event_gen.h
src/stream/base/stream_base.cc
src/stream/libtcp/tcp_stream_session.cc
src/stream/libtcp/tcp_stream_session.h
src/stream/stream.cc
src/stream/tcp/tcp_reassembler.cc
src/stream/tcp/tcp_reassembler.h
src/stream/tcp/test/tcp_normalizer_test.cc
src/utils/stats.cc

index 941d88c6662a33a0c82f2094528ce530fd8bbd85..d38ab0d0099626af91429f6a6d07078d74fe3301 100644 (file)
@@ -185,6 +185,8 @@ bool Ipv4Codec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
             ip_len - raw.len, ip_len, raw.len);
 
         codec_event(codec, DECODE_IPV4_DGRAM_GT_CAPLEN);
+        // FIXIT-L we should decode this layer if possible instead of stopping now
+        // ip6 etc may have similar issues
         return false;
     }
 #if 0
index a7961aafc31dce4010c4bfb7a1a75f7bf1b99575..63c0ca86df699f4cdc32851ac576a1c5a942c778 100644 (file)
@@ -47,7 +47,6 @@
 
 Trace TRACE_NAME(detection);
 
-static THREAD_LOCAL unsigned s_events = 0;
 static THREAD_LOCAL Ring<unsigned>* offload_ids = nullptr;
 
 void DetectionEngine::thread_init()
@@ -383,7 +382,6 @@ int DetectionEngine::queue_event(const OptTreeNode* otn)
     if ( sfeventq_add(pq, en) )
         return -1;
 
-    s_events++;
     return 0;
 }
 
@@ -407,7 +405,6 @@ int DetectionEngine::queue_event(unsigned gid, unsigned sid, RuleType type)
     if ( sfeventq_add(pq, en) )
         return -1;
 
-    s_events++;
     return 0;
 }
 
@@ -426,9 +423,6 @@ static int log_events(void* event, void* user)
             return 0;  // not enabled
     }
 
-    if ( s_events > 0 )
-        s_events--;
-
     fpLogEvent(en->rtn, en->otn, (Packet*)user);
     sfthreshold_reset();
 
@@ -449,16 +443,9 @@ int DetectionEngine::log_events(Packet* p)
     return 0;
 }
 
-void DetectionEngine::reset_counts()
-{
-    pc.log_limit += s_events;
-    s_events = 0;
-}
-
 void DetectionEngine::reset(Packet* p)
 {
     SF_EVENTQ* pq = p->context->equeue;
-    sfeventq_reset(pq);
-    reset_counts();
+    pc.log_limit += sfeventq_reset(pq);
 }
 
index 03c8fad77f339a5c87bf9e606e5b91b6f36167cf..f6111a3112833f84b4e800fa2370df4413849f88 100644 (file)
@@ -82,9 +82,7 @@ public:
     static int queue_event(unsigned gid, unsigned sid, RuleType = RULE_TYPE__NONE);
 
     static int log_events(Packet*);
-
     static void reset(Packet*);
-    static void reset_counts();
 
     static void disable_all(Packet*);
     static bool all_disabled(Packet*);
index c543f5981e8e9abc13f33a6f6d1889c13dac84db..0f584638ffd49165d8c60394c5ef43e03b01af2c 100644 (file)
@@ -176,8 +176,7 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
     if ( p->ptrs.ip_api.is_valid() )
     {
         filterEvent = sfthreshold_test(
-            otn->sigInfo.generator,
-            otn->sigInfo.id,
+            otn->sigInfo.generator, otn->sigInfo.id,
             p->ptrs.ip_api.get_src(), p->ptrs.ip_api.get_dst(),
             p->pkth->ts.tv_sec);
     }
@@ -187,10 +186,8 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
         cleared.clear();
 
         filterEvent = sfthreshold_test(
-            otn->sigInfo.generator,
-            otn->sigInfo.id,
-            &cleared, &cleared,
-            p->pkth->ts.tv_sec);
+            otn->sigInfo.generator, otn->sigInfo.id,
+            &cleared, &cleared, p->pkth->ts.tv_sec);
     }
 
     if ( (filterEvent < 0) || (filterEvent > 0 && !override) )
index 664cad44896231298864eda7076b6a414d1ed8bb..155ec6fe653af3213692c604cdcd8eb3e6ed5666 100644 (file)
 
 #include "sfeventq.h"
 
+#include <assert.h>
 #include "utils/util.h"
 
 /*
-**  NAME
-**    sfeventq_new::
-*/
-/**
 **  Initialize the event queue.  Provide the max number of nodes that this
 **  queue will support, the number of top nodes to log in the queue, and the
 **  size of the event structure that the user will fill in.
-**
-**  @return integer
-**
-**  @retval -1 failure
-**  @retval  0 success
 */
 SF_EVENTQ* sfeventq_new(int max_nodes, int log_nodes, int event_size)
 {
-    SF_EVENTQ* eq;
-
     if ((max_nodes <= 0) || (log_nodes <= 0) || (event_size <= 0))
         return NULL;
 
-    eq = (SF_EVENTQ*)snort_calloc(sizeof(SF_EVENTQ));
+    SF_EVENTQ* eq = (SF_EVENTQ*)snort_calloc(sizeof(SF_EVENTQ));
 
     /* Initialize the memory for the nodes that we are going to use. */
     eq->node_mem = (SF_EVENTQ_NODE*)snort_calloc(max_nodes, sizeof(SF_EVENTQ_NODE));
@@ -87,16 +77,14 @@ SF_EVENTQ* sfeventq_new(int max_nodes, int log_nodes, int event_size)
     eq->event_size = event_size;
     eq->cur_nodes = 0;
     eq->cur_events = 0;
+    eq->fails = 0;
+
     eq->reserve_event = (char*)(&eq->event_mem[max_nodes * eq->event_size]);
 
     return eq;
 }
 
 /*
-**  NAME
-**    sfeventq_event_alloc::
-*/
-/**
 **  Allocate the memory for an event to add to the event queue.  This
 **  function is meant to be called first, the event structure filled in,
 **  and then added to the queue.  While you can allocate several times before
@@ -131,33 +119,20 @@ void* sfeventq_event_alloc(SF_EVENTQ* eq)
 }
 
 /*
-**  NAME
-**    sfeventq_reset::
-*/
-/**
 **  Resets the event queue.  We also set the reserve event back
 **  to the last event in the queue.
-**
-**  @return void
 */
-void sfeventq_reset(SF_EVENTQ* eq)
+unsigned sfeventq_reset(SF_EVENTQ* eq)
 {
+    unsigned fails = eq->fails;
+    eq->fails = 0;
     eq->head = NULL;
     eq->cur_nodes = 0;
     eq->cur_events = 0;
     eq->reserve_event = (char*)(&eq->event_mem[eq->max_nodes * eq->event_size]);
+    return fails;
 }
 
-/*
-**  NAME
-**    sfeventq_free::
-*/
-/**
-**  Cleanup the event queue.
-**
-**  @return none
-**
-*/
 void sfeventq_free(SF_EVENTQ* eq)
 {
     if (eq == NULL)
@@ -180,10 +155,6 @@ void sfeventq_free(SF_EVENTQ* eq)
 }
 
 /*
-**  NAME
-**    get_eventq_node::
-*/
-/**
 **  This function returns a ptr to the node to use.  We allocate the last
 **  event node if we have exhausted the event queue.  Before we allocate
 **  the last node, we determine if the incoming event has a higher
@@ -204,17 +175,11 @@ static SF_EVENTQ_NODE* get_eventq_node(SF_EVENTQ* eq, void*)
     if (eq->cur_nodes >= eq->max_nodes)
         return NULL;
 
-    /*
-    **  We grab the next node from the node memory.
-    */
+    //  We grab the next node from the node memory.
     return &eq->node_mem[eq->cur_nodes++];
 }
 
 /*
-**  NAME
-**    sfeventq_add:
-*/
-/**
 **  Add this event to the queue using the supplied ordering
 **  function.  If the queue is exhausted, then we compare the
 **  event to be added with the last event, and decide whether
@@ -227,10 +192,7 @@ static SF_EVENTQ_NODE* get_eventq_node(SF_EVENTQ* eq, void*)
 */
 int sfeventq_add(SF_EVENTQ* eq, void* event)
 {
-    SF_EVENTQ_NODE* node;
-
-    if (!event)
-        return -1;
+    assert(event);
 
     /*
     **  If get_eventq_node() returns NULL, this means that
@@ -238,26 +200,26 @@ int sfeventq_add(SF_EVENTQ* eq, void* event)
     **  is lower in priority then the last ranked event.
     **  So we just drop it.
     */
-    node = get_eventq_node(eq, event);
-    if (!node)
+    SF_EVENTQ_NODE* node = get_eventq_node(eq, event);
+
+    if ( !node )
+    {
+        ++eq->fails;
         return -1;
+    }
 
     node->event = event;
     node->next  = NULL;
     node->prev  = NULL;
 
-    /*
-    **  This is the first node
-    */
     if (eq->cur_nodes == 1)
     {
+        //  This is the first node
         eq->head = eq->last = node;
         return 0;
     }
 
-    /*
-    **  This means we are the last node.
-    */
+    //  This means we are the last node.
     node->prev = eq->last;
 
     eq->last->next = node;
@@ -267,10 +229,6 @@ int sfeventq_add(SF_EVENTQ* eq, void* event)
 }
 
 /*
-**  NAME
-**    sfeventq_action::
-*/
-/**
 **  Call the supplied user action function on the highest priority
 **  events.
 **
index 4efd40e41cd33ee479016d95e69b76f00151d876..46f7388f2afbe237562b932735bc9227b38c8e28 100644 (file)
@@ -61,11 +61,12 @@ struct SF_EVENTQ
     */
     int cur_nodes;
     int cur_events;
+    unsigned fails;
 };
 
 SF_EVENTQ* sfeventq_new(int max_nodes, int log_nodes, int event_size);
 void* sfeventq_event_alloc(SF_EVENTQ*);
-void sfeventq_reset(SF_EVENTQ*);
+unsigned sfeventq_reset(SF_EVENTQ*);  // returns fail count since last reset
 int sfeventq_add(SF_EVENTQ*, void* event);
 int sfeventq_action(SF_EVENTQ*, int (* action_func)(void* event, void* user), void* user);
 void sfeventq_free(SF_EVENTQ*);
index c1a3e6ee628480390fe17a9f5e30105b10386a29..7dc1b3e4691e2a5705220abc13f4ecab07b0e25f 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "flow.h"
 
+#include "detection/detection_engine.h"
 #include "flow/ha.h"
 #include "flow/session.h"
 #include "ips_options/ips_flowbits.h"
@@ -125,6 +126,10 @@ inline void Flow::clean()
 
 void Flow::reset(bool do_cleanup)
 {
+    DetectionEngine::onload(this);
+    DetectionEngine::set_packet();
+    DetectionEngine de;
+
     if ( session )
     {
         if ( do_cleanup )
index 1d2782916d4aa2c2217fe6a6d07b6a0c0a2ca60c..13932500796f27030d4edb38d15c5d8da0a8dbbc 100644 (file)
@@ -24,7 +24,6 @@
 
 #include "flow/flow_cache.h"
 
-#include "detection/detection_engine.h"
 #include "flow/ha.h"
 #include "hash/zhash.h"
 #include "helpers/flag_context.h"
@@ -149,7 +148,6 @@ Flow* FlowCache::get(const FlowKey* key)
 
 int FlowCache::release(Flow* flow, PruneReason reason, bool do_cleanup)
 {
-    DetectionEngine::onload(flow);
     flow->reset(do_cleanup);
     prune_stats.update(reason);
     return remove(flow);
index 0a935292efd3d7a73c0fd9c9a6fa36f9263bc9bf..c0bacb0b5084ea46ce8d20e1fe7a17678392d4a4 100644 (file)
@@ -41,7 +41,7 @@ public:
     virtual void restart(Packet*) { }
     virtual void precheck(Packet*) { }
     virtual void clear() = 0;
-    virtual void cleanup() { clear(); }
+    virtual void cleanup(Packet* = nullptr) { clear(); }
 
     virtual bool add_alert(Packet*, uint32_t /*gid*/, uint32_t /*sid*/) { return false; }
     virtual bool check_alerted(Packet*, uint32_t /*gid*/, uint32_t /*sid*/) { return false; }
index 0c93aededb2298767743da283c6fddff67f1242e..bf886d61edb3fa09e63fb3c7cd8b53c3826919db 100644 (file)
@@ -38,6 +38,7 @@ class HttpEventGen
 public:
     virtual ~HttpEventGen() = default;
     void reset() { events_generated = 0; }
+
     virtual void create_event(HttpEnums::EventSid sid)
     {
         assert(((int)sid > 0) && ((int)sid <= MAX));
index 41b38a53c1f01aacde93d2efb79f016953cd9ee0..f0da55aa9e7ac50fde9bbdfe90e091ddeee7ef6b 100644 (file)
@@ -22,9 +22,9 @@
 
 #include "flow/flow_control.h"
 #include "flow/prune_stats.h"
-#include "protocols/packet.h"
 #include "managers/inspector_manager.h"
 #include "profiler/profiler_defs.h"
+#include "protocols/packet.h"
 
 #include "stream_ha.h"
 #include "stream_module.h"
index 683dd9d7bdc1117918afed8a8a609f2df2f432d1..e71d9d81deed20653ecacd34ab3e5446ca633686 100644 (file)
@@ -430,9 +430,9 @@ bool TcpStreamSession::setup(Packet*)
     return true;
 }
 
-void TcpStreamSession::cleanup()
+void TcpStreamSession::cleanup(Packet* p)
 {
-    clear_session( true, true, false );
+    clear_session(true, true, false, p);
 }
 
 void TcpStreamSession::clear()
index a008d518c07683cc02f151f53af556955ef08f49..e0f713a31a57ebecd25478e33e51251452fbd106 100644 (file)
@@ -46,7 +46,7 @@ public:
 
     bool setup(Packet*) override;
     void clear() override;
-    void cleanup() override;
+    void cleanup(Packet* = nullptr) override;
     void set_splitter(bool, StreamSplitter*) override;
     StreamSplitter* get_splitter(bool) override;
     bool is_sequenced(uint8_t /*dir*/) override;
index 164c4d64e22b34a00d46080b68f8c1e230c0946b..5a0974d026d754c291166e1521ba521d8977e7e4 100644 (file)
@@ -178,6 +178,7 @@ void Stream::check_flow_closed(Packet* p)
     if (flow->session_state & STREAM_STATE_CLOSED)
     {
         assert(flow_con);
+        flow->session->cleanup(p);
         flow_con->delete_flow(flow, PruneReason::NONE);
         p->flow = nullptr;
     }
@@ -350,15 +351,6 @@ void Stream::purge_flows()
     if ( !flow_con )
         return;
 
-    // FIXIT-H stream tcp needs to do this and prep pkt to handle
-    // shutdown alerts while rebuilding (during flush before a 
-    // rebuilt packet is available)
-    DetectionEngine::set_packet();
-    DetectionEngine de;
-    // this is a hack to work around the above issue
-    DAQ_PktHdr_t* ph = (DAQ_PktHdr_t*)de.get_packet()->pkth;
-    memset(ph, 0, sizeof(*ph));
-
     flow_con->purge_flows(PktType::IP);
     flow_con->purge_flows(PktType::ICMP);
     flow_con->purge_flows(PktType::TCP);
@@ -369,15 +361,19 @@ void Stream::purge_flows()
 
 void Stream::timeout_flows(time_t cur_time)
 {
-    if ( flow_con )
-        // FIXIT-M batch here or loop vs looping over idle?
-        flow_con->timeout_flows(cur_time);
+    if ( !flow_con )
+        return;
+
+    // FIXIT-M batch here or loop vs looping over idle?
+    flow_con->timeout_flows(cur_time);
 }
 
 void Stream::prune_flows()
 {
-    if ( flow_con )
-        flow_con->prune_one(PruneReason::MEMCAP, false);
+    if ( !flow_con )
+        return;
+
+    flow_con->prune_one(PruneReason::MEMCAP, false);
 }
 
 bool Stream::expected_flow(Flow* f, Packet* p)
index d76a5703351f79b54f4eb09571b3856b96a89327..697fc753dc72700fb8a2f3300706f37675a25ce1 100644 (file)
@@ -31,6 +31,7 @@
 #include "profiler/profiler.h"
 #include "detection/detection_engine.h"
 #include "protocols/packet_manager.h"
+#include "time/packet_time.h"
 
 #include "tcp_module.h"
 #include "tcp_normalizer.h"
@@ -838,11 +839,8 @@ int TcpReassembler::flush_stream(Packet* p, uint32_t dir)
     return flush_to_seq(bytes, p, dir);
 }
 
-void TcpReassembler::final_flush(Packet* p, PegCount& peg, uint32_t dir)
+void TcpReassembler::final_flush(Packet* p, uint32_t dir)
 {
-    if ( !p )
-        peg++;
-
     tracker->set_tf_flags(TF_FORCE_FLUSH);
 
     if ( flush_stream(p, dir) )
@@ -851,17 +849,56 @@ void TcpReassembler::final_flush(Packet* p, PegCount& peg, uint32_t dir)
     tracker->clear_tf_flags(TF_FORCE_FLUSH);
 }
 
+static Packet* set_packet(Flow* flow, uint32_t flags, bool c2s)
+{
+    Packet* p = DetectionEngine::get_current_packet();
+    p->reset();
+
+    DAQ_PktHdr_t* ph = (DAQ_PktHdr_t*)p->pkth;
+    memset(ph, 0, sizeof(*ph));
+    packet_gettimeofday(&ph->ts);
+
+    p->ptrs.set_pkt_type(PktType::PDU);
+    p->proto_bits |= PROTO_BIT__TCP;
+    p->flow = flow;
+    p->packet_flags = flags;
+
+    if ( c2s )
+    {
+        p->ptrs.ip_api.set(flow->client_ip, flow->server_ip);
+        p->ptrs.sp = flow->client_port;
+        p->ptrs.dp = flow->server_port;
+    }
+    else
+    {
+        p->ptrs.ip_api.set(flow->server_ip, flow->client_ip);
+        p->ptrs.sp = flow->server_port;
+        p->ptrs.dp = flow->client_port;
+    }
+    return p;
+}
+
 void TcpReassembler::flush_queued_segments(Flow* flow, bool clear, Packet* p)
 {
+    bool data = p or seglist.head;
+
+    if ( !p )
+    {
+        // this packet is required if we call finish and/or final_flush
+        p = set_packet(flow, packet_dir, server_side);
+
+        if ( server_side )
+            tcpStats.s5tcp2++;
+        else
+            tcpStats.s5tcp1++;
+    }
+
     bool pending = clear and paf_initialized(&tracker->paf_state)
         and (!tracker->splitter or tracker->splitter->finish(flow) );
 
-    if ((pending and (p or seglist.head) and !(flow->ssn_state.ignore_direction & ignore_dir)))
+    if ( pending and data and !(flow->ssn_state.ignore_direction & ignore_dir) )
     {
-        if (server_side)
-            final_flush(p, tcpStats.s5tcp2, packet_dir);
-        else
-            final_flush(p, tcpStats.s5tcp1, packet_dir);
+        final_flush(p, packet_dir);
     }
 }
 
index 837fd1f4262f34e378616e573d494c053f88833e..0bd9d3d763f818c3f772327e6b9e1f78a1d659fa 100644 (file)
@@ -147,7 +147,7 @@ protected:
     int flush_to_seq(uint32_t bytes, Packet*, uint32_t pkt_flags);
     uint32_t get_q_footprint();
     uint32_t get_q_sequenced();
-    void final_flush(Packet*, PegCount&, uint32_t dir);
+    void final_flush(Packet*, uint32_t dir);
     uint32_t get_reverse_packet_dir(const Packet*);
     uint32_t get_forward_packet_dir(const Packet*);
     int32_t flush_pdu_ips(uint32_t*);
index d3ed70b9860e2f2eb7ee51954474b095e15fc66c..c4ec32dc88c3d139032411b3ab2947f55639b26c 100644 (file)
@@ -54,7 +54,7 @@ int TcpSession::process(Packet*){ return 0; }
 void TcpSession::restart(Packet*){ }
 void TcpSession::precheck(Packet*){ }
 void TcpSession::clear(){ }
-void TcpSession::cleanup(){ }
+void TcpSession::cleanup(Packet* = nullptr){ }
 bool TcpSession::add_alert(Packet*, unsigned int, unsigned int){ return true; }
 bool TcpSession::check_alerted(Packet*, unsigned int, unsigned int){ return true; }
 int TcpSession::update_alert(Packet*, unsigned int, unsigned int, unsigned int, unsigned int){ return 0; }
index 1ed38c2d81de869e367ff41e6b7bf966ac718700..74c7e5c202630f8caba4888ff9b5f25e4c2bdb48 100644 (file)
@@ -284,9 +284,6 @@ void DropStats()
 
     PacketManager::dump_stats();
 
-    // ensure proper counting of log_limit
-    DetectionEngine::reset_counts();
-
     LogLabel("Module Statistics");
     const char* exclude = "daq snort";
     ModuleManager::dump_stats(snort_conf, exclude);