]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1652 in SNORT/snort3 from ~SMULKA/snort3:clean_stale_flow to...
authorGeorge Koikara (gkoikara) <gkoikara@cisco.com>
Fri, 2 Aug 2019 07:31:53 +0000 (03:31 -0400)
committerGeorge Koikara (gkoikara) <gkoikara@cisco.com>
Fri, 2 Aug 2019 07:31:53 +0000 (03:31 -0400)
Squashed commit of the following:

commit 51287fcbe9cef0d1018d30adb8a30fb54b7cc614
Author: smulka <smulka@cisco.com>
Date:   Fri Jul 5 08:36:00 2019 -0400

    flow: delete stale flow on receiving NEW_FLOW flag

src/flow/flow_control.cc
src/flow/flow_control.h
src/flow/prune_stats.h
src/flow/test/CMakeLists.txt
src/flow/test/flow_control_test.cc [new file with mode: 0644]
src/protocols/packet.h

index 09c274db20202dae5b9a64e73aaa95afd2852479..8b0310580a8173f8fa43232adcd7e674242fdff1 100644 (file)
@@ -20,6 +20,8 @@
 #include "config.h"
 #endif
 
+#include <daq_common.h>
+
 #include "flow_control.h"
 
 #include "detection/detection_engine.h"
@@ -27,6 +29,7 @@
 #include "managers/inspector_manager.h"
 #include "memory/memory_cap.h"
 #include "packet_io/active.h"
+#include "packet_tracer/packet_tracer.h"
 #include "protocols/icmp4.h"
 #include "protocols/tcp.h"
 #include "protocols/udp.h"
@@ -164,6 +167,20 @@ void FlowControl::preemptive_cleanup()
     }
 }
 
+Flow* FlowControl::stale_flow_cleanup(FlowCache* cache, Flow* flow, Packet* p)
+{
+    if ( p->pkth->flags & DAQ_PKT_FLAG_NEW_FLOW )
+    {
+        if (PacketTracer::is_active())
+            PacketTracer::log("Session: deleting snort session, reason: stale and not cleaned \n");
+
+        cache->release(flow, PruneReason::STALE);
+        flow = nullptr;
+    }
+
+    return flow;
+}
+
 //-------------------------------------------------------------------------
 // packet foo
 //-------------------------------------------------------------------------
@@ -356,6 +373,10 @@ bool FlowControl::process(PktType type, Packet* p, bool* new_flow)
     FlowKey key;
     set_key(&key, p);
     Flow* flow = cache->find(&key);
+
+    if (flow)
+        flow = stale_flow_cleanup(cache, flow, p);
+
     if ( !flow )
     {
         flow = HighAvailabilityManager::import(*p, key);
index 2c29477e5eaf52598b034cf95babf3900ef60fbe..e6d954e57af242d24eed624bd47e3c03d722d2d7 100644 (file)
@@ -64,6 +64,7 @@ public:
     void delete_flow(snort::Flow*, PruneReason);
     void purge_flows();
     bool prune_one(PruneReason, bool do_cleanup);
+    snort::Flow* stale_flow_cleanup(FlowCache*, snort::Flow*, snort::Packet*);
 
     void timeout_flows(time_t cur_time);
 
index 6bbe3b21f6e84d66c622f7b1b85d970cdd1866ac..d31584b93080f1cfa5d8c05a1acd031b9bce71c0 100644 (file)
@@ -34,6 +34,7 @@ enum class PruneReason : uint8_t
     PREEMPTIVE,
     MEMCAP,
     HA,
+    STALE,
     NONE,
     MAX
 };
index d4c1284764f828c6a2707ac47c9046f8b3c0a52d..e98030b440cf54e2313a7477c333f9868ae464e8 100644 (file)
@@ -4,4 +4,8 @@ add_cpputest( flow_stash_test
     SOURCES ../flow_stash.cc
 )
 
+add_cpputest( flow_control_test
+    SOURCES ../flow_control.cc
+)
+
 add_cpputest( session_test )
diff --git a/src/flow/test/flow_control_test.cc b/src/flow/test/flow_control_test.cc
new file mode 100644 (file)
index 0000000..2a4520a
--- /dev/null
@@ -0,0 +1,181 @@
+
+// Copyright (C) 2019-2019 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// flow_control_test.cc author Shivakrishna Mulka <smulka@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <daq_common.h>
+
+#include "flow/flow_control.h"
+
+#include "detection/detection_engine.h"
+#include "main/snort_config.h"
+#include "managers/inspector_manager.h"
+#include "memory/memory_cap.h"
+#include "packet_io/active.h"
+#include "packet_tracer/packet_tracer.h"
+#include "protocols/icmp4.h"
+#include "protocols/packet.h"
+#include "protocols/tcp.h"
+#include "protocols/udp.h"
+#include "protocols/vlan.h"
+#include "stream/stream.h"
+#include "utils/util.h"
+#include "flow/expect_cache.h"
+#include "flow/flow_cache.h"
+#include "flow/ha.h"
+#include "flow/session.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
+
+using namespace snort;
+
+THREAD_LOCAL bool Active::s_suspend = false;
+
+THREAD_LOCAL PacketTracer* snort::s_pkt_trace = nullptr;
+
+PacketTracer::PacketTracer() { }
+PacketTracer::~PacketTracer() { }
+void PacketTracer::log(const char* format, ...) { }
+void PacketTracer::open_file() { }
+void PacketTracer::dump_to_daq(Packet* p) { }
+void PacketTracer::reset() { }
+Packet::Packet(bool) { }
+Packet::~Packet() { }
+FlowCache::FlowCache(const FlowCacheConfig& cfg) : config(cfg) { }
+FlowCache::~FlowCache() { }
+Flow::Flow() = default;
+Flow::~Flow() { }
+DetectionEngine::DetectionEngine() { }
+ExpectCache::~ExpectCache() { }
+DetectionEngine::~DetectionEngine() { }
+unsigned FlowCache::purge() { return 1; }
+Flow* FlowCache::find(const FlowKey* key) { return nullptr; }
+Flow* FlowCache::get(const FlowKey* key) { return nullptr; }
+void FlowCache::push(Flow* flow) { }
+bool FlowCache::prune_one(PruneReason reason, bool do_cleanup) { return true; }
+unsigned FlowCache::timeout(unsigned num_flows, time_t thetime) { return 1; }
+void Flow::init(PktType type) { }
+void set_network_policy(SnortConfig* sc, unsigned i) { } 
+void DataBus::publish(const char* key, const uint8_t* buf, unsigned len, Flow* f) { }
+void DataBus::publish(const char* key, Packet* p, Flow* f) { }
+SnortConfig* SnortConfig::get_conf() { return nullptr; }
+void FlowCache::unlink_uni(Flow* flow) { }
+void Flow::set_direction(Packet* p) { }
+void set_inspection_policy(SnortConfig* sc, unsigned i) { }
+void set_ips_policy(SnortConfig* sc, unsigned i) { }
+void Flow::set_mpls_layer_per_dir(Packet* p) { }
+void DetectionEngine::disable_all(Packet* p) { }
+void Stream::drop_traffic(const Packet* p, char dir) { }
+bool Stream::blocked_flow(Packet* p) { return true; }
+ExpectCache::ExpectCache(uint32_t max) { }
+bool ExpectCache::check(Packet* p, Flow* lws) { return true; }
+bool ExpectCache::is_expected(Packet* p) { return true; }
+Flow* HighAvailabilityManager::import(Packet& p, FlowKey& key) { }
+
+namespace memory 
+{
+bool MemoryCap::over_threshold() { return true; }
+}
+
+namespace snort
+{
+namespace layer
+{
+const vlan::VlanTagHdr* get_vlan_layer(const Packet* const p) { return nullptr; }
+}
+}
+
+namespace snort
+{
+namespace ip
+{
+uint32_t IpApi::id() const { return 0; }
+}
+}
+
+bool FlowKey::init(
+    PktType type, IpProtocol ip_proto,
+    const SfIp *srcIP, uint16_t srcPort,
+    const SfIp *dstIP, uint16_t dstPort,
+    uint16_t vlanId, uint32_t mplsId, uint16_t addrSpaceId)
+{
+   return true;
+}
+
+bool FlowKey::init(
+    PktType type, IpProtocol ip_proto,
+    const SfIp *srcIP, const SfIp *dstIP,
+    uint32_t id, uint16_t vlanId,
+    uint32_t mplsId, uint16_t addrSpaceId)
+{
+    return true;
+}
+
+void Stream::stop_inspection(
+    Flow* flow, Packet* p, char dir,
+    int32_t /*bytes*/, int /*response*/) { }
+
+
+int ExpectCache::add_flow(const Packet *ctrlPkt,
+    PktType type, IpProtocol ip_proto,
+    const SfIp* cliIP, uint16_t cliPort,
+    const SfIp* srvIP, uint16_t srvPort,
+    char direction, FlowData* fd, SnortProtocolId snort_protocol_id)
+{ 
+    return 1; 
+}
+
+int FlowCache::release(Flow* flow, PruneReason reason, bool do_cleanup) 
+{ 
+    return 1; 
+}
+
+TEST_GROUP(stale_flow) { };
+
+TEST(stale_flow, stale_flow)
+{
+    Packet* p = new Packet(false);
+    Flow* flow = new Flow;
+    FlowCacheConfig fcg;
+    FlowCache *cache = new FlowCache(fcg);
+    FlowControl *flow_con = new FlowControl(fcg);
+    DAQ_PktHdr_t dh = { };
+
+    dh.flags = DAQ_PKT_FLAG_NEW_FLOW;
+    p->pkth = &dh;
+    CHECK(flow_con->stale_flow_cleanup(cache, flow, p) == nullptr);
+
+    dh.flags &= ~DAQ_PKT_FLAG_NEW_FLOW;
+    CHECK(flow_con->stale_flow_cleanup(cache, flow, p) == flow);
+
+    p->pkth = nullptr;
+    delete flow;
+    delete p;
+    delete flow_con;
+    delete cache;
+}
+
+int main(int argc, char** argv)
+{
+    return CommandLineTestRunner::RunAllTests(argc, argv);
+} 
index 4e25fc1d4a3d88c4119fbe6aa5e7a4260cb6180b..4901f5711aa46c0f18e9ef9b0554755dd0debce9 100644 (file)
@@ -284,7 +284,7 @@ struct SO_PUBLIC Packet
 
     bool is_offloaded() const
     { return (ts_packet_flags & PKT_TS_OFFLOADED) != 0; }
-
     void set_offloaded()
     { ts_packet_flags |= PKT_TS_OFFLOADED; }