From: George Koikara (gkoikara) Date: Fri, 2 Aug 2019 07:31:53 +0000 (-0400) Subject: Merge pull request #1652 in SNORT/snort3 from ~SMULKA/snort3:clean_stale_flow to... X-Git-Tag: 3.0.0-259~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e12667568074cf7c1762a702084df17505fae6ba;p=thirdparty%2Fsnort3.git Merge pull request #1652 in SNORT/snort3 from ~SMULKA/snort3:clean_stale_flow to master Squashed commit of the following: commit 51287fcbe9cef0d1018d30adb8a30fb54b7cc614 Author: smulka Date: Fri Jul 5 08:36:00 2019 -0400 flow: delete stale flow on receiving NEW_FLOW flag --- diff --git a/src/flow/flow_control.cc b/src/flow/flow_control.cc index 09c274db2..8b0310580 100644 --- a/src/flow/flow_control.cc +++ b/src/flow/flow_control.cc @@ -20,6 +20,8 @@ #include "config.h" #endif +#include + #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); diff --git a/src/flow/flow_control.h b/src/flow/flow_control.h index 2c29477e5..e6d954e57 100644 --- a/src/flow/flow_control.h +++ b/src/flow/flow_control.h @@ -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); diff --git a/src/flow/prune_stats.h b/src/flow/prune_stats.h index 6bbe3b21f..d31584b93 100644 --- a/src/flow/prune_stats.h +++ b/src/flow/prune_stats.h @@ -34,6 +34,7 @@ enum class PruneReason : uint8_t PREEMPTIVE, MEMCAP, HA, + STALE, NONE, MAX }; diff --git a/src/flow/test/CMakeLists.txt b/src/flow/test/CMakeLists.txt index d4c128476..e98030b44 100644 --- a/src/flow/test/CMakeLists.txt +++ b/src/flow/test/CMakeLists.txt @@ -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 index 000000000..2a4520a5f --- /dev/null +++ b/src/flow/test/flow_control_test.cc @@ -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 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#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 +#include + +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); +} diff --git a/src/protocols/packet.h b/src/protocols/packet.h index 4e25fc1d4..4901f5711 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -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; }