]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2640 in SNORT/snort3 from ~SMINUT/snort3:data_purge to master
authorMasud Hasan (mashasan) <mashasan@cisco.com>
Tue, 1 Dec 2020 21:12:37 +0000 (21:12 +0000)
committerMasud Hasan (mashasan) <mashasan@cisco.com>
Tue, 1 Dec 2020 21:12:37 +0000 (21:12 +0000)
Squashed commit of the following:

commit a6bd13f8bafcf6c639ca28303a97309d860b0079
Author: Silviu Minut <sminut@cisco.com>
Date:   Mon Nov 23 18:19:29 2020 -0500

    rna: support data purge command

17 files changed:
src/host_tracker/host_cache.h
src/host_tracker/host_tracker.cc
src/host_tracker/host_tracker.h
src/network_inspectors/rna/CMakeLists.txt
src/network_inspectors/rna/data_purge_cmd.cc [new file with mode: 0644]
src/network_inspectors/rna/data_purge_cmd.h [new file with mode: 0644]
src/network_inspectors/rna/rna_app_discovery.cc
src/network_inspectors/rna/rna_inspector.cc
src/network_inspectors/rna/rna_inspector.h
src/network_inspectors/rna/rna_mac_cache.cc
src/network_inspectors/rna/rna_mac_cache.h
src/network_inspectors/rna/rna_module.cc
src/network_inspectors/rna/rna_module.h
src/network_inspectors/rna/rna_pnd.cc
src/network_inspectors/rna/rna_pnd.h
src/network_inspectors/rna/test/CMakeLists.txt
src/network_inspectors/rna/test/rna_module_mock.h

index a18403874ec3fec1b5b0599ffbc2ad1c51f75c32..bd80e7abeeb0b31f5cf8b71a61be19abe3799a18 100644 (file)
@@ -78,7 +78,8 @@ public:
     LruCacheSharedMemcap(const LruCacheSharedMemcap& arg) = delete;
     LruCacheSharedMemcap& operator=(const LruCacheSharedMemcap& arg) = delete;
 
-    LruCacheSharedMemcap(const size_t initial_size) : LruCacheShared<Key, Value, Hash, Eq>(initial_size) {}
+    LruCacheSharedMemcap(const size_t initial_size) : LruCacheShared<Key, Value, Hash, Eq>(initial_size),
+        valid_id(invalid_id+1) {}
 
     size_t mem_size() override
     {
@@ -154,6 +155,20 @@ public:
         return false;
     }
 
+    bool is_valid(size_t id) const
+    {
+        return id == valid_id;
+    }
+
+    void invalidate()
+    {
+        valid_id++;
+    }
+
+    size_t get_valid_id() const { return valid_id; }
+
+    static constexpr size_t invalid_id = 0;
+
     template <class T>
     friend class HostCacheAllocIp;
 
@@ -205,6 +220,8 @@ private:
         current_size -= mem_chunk;
     }
 
+    std::atomic<size_t> valid_id;
+
     std::mutex reload_mutex;
     friend class TEST_host_cache_module_misc_Test; // for unit test
 };
index 478b2e01613b30245bc48e1c21c00606b7828301..181363cce1e9ecc6149a933285de644d7b6ea38c 100644 (file)
@@ -39,6 +39,14 @@ THREAD_LOCAL struct HostTrackerStats host_tracker_stats;
 
 const uint8_t snort::zero_mac[MAC_SIZE] = {0, 0, 0, 0, 0, 0};
 
+
+HostTracker::HostTracker() : hops(-1)
+{
+    last_seen = nat_count_start = (uint32_t) packet_time();
+    last_event = -1;
+    visibility = host_cache.get_valid_id();
+}
+
 void HostTracker::update_last_seen()
 {
     lock_guard<mutex> lck(host_tracker_lock);
@@ -573,7 +581,7 @@ HostApplication* HostTracker::find_and_add_service_no_lock(Port port, IpProtocol
         return available;
     }
 
-    if ( max_services == 0 or num_visible_services < max_services ) 
+    if ( max_services == 0 or num_visible_services < max_services )
     {
         services.emplace_back(port, proto, appid, false, 1, lseen);
         return &services.back();
@@ -778,12 +786,15 @@ bool HostTracker::add_udp_fingerprint(uint32_t fpid)
 
 bool HostTracker::set_visibility(bool v)
 {
+    // get_valid_id may use its own lock, so get this outside our lock
+    size_t container_id = host_cache.get_valid_id();
+
     std::lock_guard<std::mutex> lck(host_tracker_lock);
-    bool old_visibility = visibility;
+    size_t old_visibility = visibility;
 
-    visibility = v;
+    visibility = v ? container_id : HostCacheIp::invalid_id;
 
-    if ( visibility == false )
+    if (visibility == HostCacheIp::invalid_id)
     {
         for (auto& proto : network_protos)
             proto.second = false;
@@ -802,14 +813,14 @@ bool HostTracker::set_visibility(bool v)
             for (auto& info : s.info)
                 info.visibility = false;
             s.user[0] = '\0';
-            set_payload_visibility_no_lock(s.payloads, v, s.num_visible_payloads);
+            set_payload_visibility_no_lock(s.payloads, false, s.num_visible_payloads);
         }
         num_visible_services = 0;
 
         for ( auto& c : clients )
         {
             c.visibility = false;
-            set_payload_visibility_no_lock(c.payloads, v, c.num_visible_payloads);
+            set_payload_visibility_no_lock(c.payloads, false, c.num_visible_payloads);
         }
         num_visible_clients = 0;
 
@@ -817,9 +828,16 @@ bool HostTracker::set_visibility(bool v)
         ua_fps.clear();
     }
 
-    return old_visibility;
+    return old_visibility == visibility;
+}
+
+bool HostTracker::is_visible() const
+{
+    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    return visibility == host_cache.get_valid_id();
 }
 
+
 bool HostTracker::set_network_proto_visibility(uint16_t proto, bool v)
 {
     std::lock_guard<std::mutex> lck(host_tracker_lock);
index ea8f8793454bb800b7a625bbd7ad201890425568..026f6308095e5ca57897fe251471cac88df7b47c 100644 (file)
@@ -75,9 +75,11 @@ struct HostApplicationInfo
     HostApplicationInfo(const char *ver, const char *ven);
     char vendor[INFO_SIZE] = { '\0' };
     char version[INFO_SIZE] = { '\0' };
-    bool visibility = true;
 
     friend class HostTracker;
+private:
+    bool visibility = true;
+
 };
 
 typedef HostCacheAllocIp<HostApplicationInfo> HostAppInfoAllocator;
@@ -207,11 +209,7 @@ public:
     typedef std::pair<uint16_t, bool> NetProto_t;
     typedef std::pair<uint8_t, bool> XProto_t;
 
-    HostTracker() : hops(-1)
-    {
-        last_seen = nat_count_start = (uint32_t) packet_time();
-        last_event = -1;
-    }
+    HostTracker();
 
     void update_last_seen();
     uint32_t get_last_seen() const
@@ -384,11 +382,7 @@ public:
 
     bool set_visibility(bool v = true);
 
-    bool is_visible() const
-    {
-        std::lock_guard<std::mutex> lck(host_tracker_lock);
-        return visibility;
-    }
+    bool is_visible() const;
 
     // the control delete commands do not actually remove objects from
     // the host tracker, but just mark them as invisible, until rediscovered.
@@ -436,7 +430,7 @@ private:
     uint32_t nat_count = 0;
     uint32_t nat_count_start;     // the time nat counting starts for this host
 
-    bool visibility = true;
+    size_t visibility;
 
     uint32_t num_visible_services = 0;
     uint32_t num_visible_clients = 0;
@@ -448,7 +442,7 @@ private:
     bool add_payload_no_lock(const AppId, HostApplication*, size_t);
     HostApplication* find_service_no_lock(Port, IpProtocol, AppId);
     void update_ha_no_lock(HostApplication& dst, HostApplication& src);
-    
+
     HostApplication* find_and_add_service_no_lock(Port, IpProtocol, uint32_t lseen,
         bool& is_new, AppId, uint16_t max_services = 0);
 
index 7cd8fc478b0f3f2ac40188833a0e9c4197af89ec..85bae0cb37f8a1ceb0c6b25887e6a85a89ed6e28 100644 (file)
@@ -10,6 +10,8 @@ set (RNA_INCLUDES
 
 set ( RNA_SOURCES
     ${RNA_INCLUDES}
+    data_purge_cmd.cc
+    data_purge_cmd.h
     rna_app_discovery.cc
     rna_app_discovery.h
     rna_event_handler.cc
diff --git a/src/network_inspectors/rna/data_purge_cmd.cc b/src/network_inspectors/rna/data_purge_cmd.cc
new file mode 100644 (file)
index 0000000..67b05ad
--- /dev/null
@@ -0,0 +1,49 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+
+// data_purge_cmd.cc author Silviu Minut <sminut@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "data_purge_cmd.h"
+
+#include "managers/inspector_manager.h"
+
+#include "rna_inspector.h"
+#include "rna_name.h"
+#include "rna_pnd.h"
+
+using namespace snort;
+
+DataPurgeAC::~DataPurgeAC()
+{
+    auto rna_ins = (RnaInspector*) InspectorManager::get_inspector(RNA_NAME, true);
+    RnaPnd* pnd = rna_ins->get_pnd();
+    delete pnd->host_cache_mac_ptr;
+    pnd->host_cache_mac_ptr = host_cache_mac;
+    set_host_cache_mac(host_cache_mac);
+}
+
+bool DataPurgeAC::execute(Analyzer&, void**)
+{
+    set_host_cache_mac(host_cache_mac);
+    return true;
+}
+
diff --git a/src/network_inspectors/rna/data_purge_cmd.h b/src/network_inspectors/rna/data_purge_cmd.h
new file mode 100644 (file)
index 0000000..dfca23a
--- /dev/null
@@ -0,0 +1,43 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 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.
+//--------------------------------------------------------------------------
+
+// data_purge_cmd.h author Silviu Minut <sminut@cisco.com>
+
+#ifndef DATA_PURGE_CMD_H
+#define DATA_PURGE_CMD_H
+
+#include "main/analyzer_command.h"
+
+#include "rna_mac_cache.h"
+
+class DataPurgeAC : public snort::AnalyzerCommand
+{
+public:
+
+    DataPurgeAC(HostCacheMac* hcm) : host_cache_mac(hcm) { }
+    ~DataPurgeAC() override;
+
+    bool execute(Analyzer&, void**) override;
+
+    const char* stringify() override { return "DATA_PURGE"; }
+
+private:
+    HostCacheMac* host_cache_mac;
+};
+
+#endif
index fd8a17a7e741a48334243d30439fa61669a0adc2..19abe060fe6b3962031706d438e8b66270e30b05 100644 (file)
@@ -50,7 +50,7 @@ void RnaAppDiscovery::process(AppidEvent* appid_event, DiscoveryFilter& filter,
 
     const auto& src_ip = p->ptrs.ip_api.get_src();
     auto ht = host_cache.find(*src_ip);
-    if ( !ht )
+    if ( !ht || !ht->is_visible() )
         return; // should not happen as rna would get new flow event before appid event
 
     const uint8_t* src_mac;
@@ -84,7 +84,7 @@ void RnaAppDiscovery::process(AppidEvent* appid_event, DiscoveryFilter& filter,
             if ( p->packet_flags & PKT_FROM_SERVER )
             {
                 auto cht = host_cache.find(p->flow->client_ip);
-                if ( cht )
+                if ( cht && cht->is_visible() )
                     discover_client(p, cht, (const struct in6_addr*) &p->flow->client_ip,
                         layer::get_eth_layer(p)->ether_dst, conf, logger, version, client,
                         service);
@@ -168,7 +168,7 @@ bool RnaAppDiscovery::discover_service(const Packet* p, IpProtocol proto, RnaTra
     if ( p->is_from_client() )
     {
         htp = host_cache.find(ip);
-        if ( !htp )
+        if ( !htp || !htp->is_visible() )
             return false;
 
         if ( layer::get_eth_layer(p) )
@@ -238,7 +238,7 @@ void RnaAppDiscovery::discover_payload(const Packet* p, IpProtocol proto, RnaTra
     bool new_client_payload = false;
     auto client_ht = host_cache.find(p->flow->client_ip);
 
-    if (!client_ht)
+    if (!client_ht || !client_ht->is_visible())
         return;
 
     HostClient hc(client, nullptr, service);
@@ -259,7 +259,7 @@ void RnaAppDiscovery::update_service_info(const Packet* p, IpProtocol proto, con
     if ( p->is_from_client() )
     {
         htp = host_cache.find(ip);
-        if ( !htp )
+        if ( !htp || !htp->is_visible() )
             return;
 
         if ( layer::get_eth_layer(p) )
index 4fbab04cefd136419053d3b495ff7b86d452562a..6c6fe299168d9199ed94e36a6e26b569c4f80760 100644 (file)
@@ -102,7 +102,7 @@ bool RnaInspector::configure(SnortConfig* sc)
 
     // tinit is not called during reload, so pass processor pointers to threads via reload tuner
     if ( Snort::is_reloading() && InspectorManager::get_inspector(RNA_NAME, true) )
-        sc->register_reload_resource_tuner(new FpProcReloadTuner(*mod_conf));
+        sc->register_reload_resource_tuner(new FpProcReloadTuner(*mod_conf, pnd->host_cache_mac_ptr));
 
     return true;
 }
@@ -145,6 +145,7 @@ void RnaInspector::tinit()
     set_tcp_fp_processor(mod_conf->tcp_processor);
     set_ua_fp_processor(mod_conf->ua_processor);
     set_udp_fp_processor(mod_conf->udp_processor);
+    set_host_cache_mac(pnd->host_cache_mac_ptr);
 }
 
 void RnaInspector::tterm()
index 227e34419096ff36dcecd6bdde48eeae16438f7b..5001294d3b6dfeffc8af68b25d1ff09eddf9f663 100644 (file)
@@ -54,6 +54,8 @@ public:
         snort::UdpFpProcessor*&);
     void set_fp_processor(snort::TcpFpProcessor*, snort::UaFpProcessor*, snort::UdpFpProcessor*);
 
+    RnaPnd* get_pnd() const { return pnd; }
+
 private:
     void load_rna_conf();
     RnaModuleConfig* mod_conf = nullptr;
index 2195fd512920a415ad3ff7926ed98450b1e30b67..d6294d11ed9369a4f6f8a1a7a1b968ba878f65bb 100644 (file)
@@ -30,8 +30,6 @@
 using namespace snort;
 using namespace std;
 
-HostCacheMac host_cache_mac(MAC_CACHE_INITIAL_SIZE);
-
 bool HostTrackerMac::add_network_proto(const uint16_t type)
 {
     lock_guard<mutex> lck(host_tracker_mac_lock);
@@ -97,6 +95,7 @@ void HostTrackerMac::stringify(string& str)
 TEST_CASE("RNA Mac Cache", "[rna_mac_cache]")
 {
     uint8_t a_mac[6] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6};
+    HostCacheMac mac_cache(MAC_CACHE_INITIAL_SIZE);
 
     SECTION("HostCacheMac: store, retrieve")
     {
@@ -112,28 +111,28 @@ TEST_CASE("RNA Mac Cache", "[rna_mac_cache]")
 
         bool new_host_mac = false;
 
-        auto a_ptr = host_cache_mac.find_else_create(a, &new_host_mac);
+        auto a_ptr = mac_cache.find_else_create(a, &new_host_mac);
         CHECK(new_host_mac == true);
         CHECK(a_ptr != nullptr);
 
         new_host_mac = false;
-        auto b_ptr = host_cache_mac.find_else_create(b, &new_host_mac);
+        auto b_ptr = mac_cache.find_else_create(b, &new_host_mac);
         CHECK(new_host_mac == true);
         CHECK(b_ptr != nullptr);
 
         new_host_mac = false;
-        auto c_ptr = host_cache_mac.find_else_create(c, &new_host_mac);
+        auto c_ptr = mac_cache.find_else_create(c, &new_host_mac);
         CHECK(new_host_mac == true);
         CHECK(c_ptr != nullptr);
 
         // Try to add one of the previous macs again
         new_host_mac = false;
-        auto test_ptr = host_cache_mac.find_else_create(test, &new_host_mac);
+        auto test_ptr = mac_cache.find_else_create(test, &new_host_mac);
         CHECK(new_host_mac == false);
         CHECK(test_ptr != nullptr);
 
         // Verify macs in cache in LRU order, where test mac (i.e., b) is the most recent
-        const auto&& lru_data = host_cache_mac.get_all_data();
+        const auto&& lru_data = mac_cache.get_all_data();
         CHECK(lru_data.size() == 3);
         CHECK(lru_data[2].first == a);
         CHECK(lru_data[1].first == c);
@@ -149,7 +148,7 @@ TEST_CASE("RNA Mac Cache", "[rna_mac_cache]")
     SECTION("HostCacheMac: VLAN Tag Details")
     {
         MacKey a(a_mac);
-        auto a_ptr = host_cache_mac.find_else_create(a, nullptr);
+        auto a_ptr = mac_cache.find_else_create(a, nullptr);
 
         a_ptr->update_vlan(12345, 54321);
         uint8_t cfi, priority;
index 90d6ded603753914bf71cab4b6aa1f1061ee41a2..853c27d468f10b244ee847bb470567db77d20f09 100644 (file)
@@ -138,11 +138,12 @@ struct HashMac
 };
 
 typedef LruCacheSharedMemcap<MacKey, HostTrackerMac, HashMac> HostCacheMac;
-extern HostCacheMac host_cache_mac;
+
+extern HostCacheMac* get_host_cache_mac();
 
 template <class T>
 HostCacheAllocMac<T>::HostCacheAllocMac()
 {
-    lru = &host_cache_mac;
+    lru = get_host_cache_mac();
 }
 #endif
index 7f000ebf1bb56b32d3a9b4c10b5d381bde0b54c9..e3adcdf77611294d6ac5fb0e6e76262a5eeab78a 100644 (file)
 #include <string.h>
 #include <sys/stat.h>
 
+#include "host_tracker/host_cache.h"
 #include "log/messages.h"
 #include "lua/lua.h"
+#include "main/request.h"
 #include "main/snort_config.h"
+#include "managers/inspector_manager.h"
 #include "managers/module_manager.h"
 #include "utils/util.h"
 
+#include "data_purge_cmd.h"
 #include "rna_fingerprint_tcp.h"
 #include "rna_fingerprint_ua.h"
 #include "rna_fingerprint_udp.h"
 #include "rna_mac_cache.h"
+#include "rna_pnd.h"
 
 #ifdef UNIT_TEST
 #include "catch/snort_catch.h"
@@ -79,11 +84,30 @@ static inline string format_dump_mac(const uint8_t mac[MAC_SIZE])
     return ss.str();
 }
 
+static int purge_data(lua_State* L)
+{
+    RnaModule* mod = (RnaModule*) ModuleManager::get_module(RNA_NAME);
+    if ( mod )
+    {
+        HostCacheMac* mac_cache = new HostCacheMac(MAC_CACHE_INITIAL_SIZE);
+        main_broadcast_command(new DataPurgeAC(mac_cache), (L != nullptr));
+
+        host_cache.invalidate();
+
+        auto& request = get_dispatched_request();
+        request.respond("data purge done\n", false, true);
+        LogMessage("data purge done\n");
+    }
+
+    return 0;
+}
+
 bool FpProcReloadTuner::tinit()
 {
     set_tcp_fp_processor(mod_conf.tcp_processor);
     set_ua_fp_processor(mod_conf.ua_processor);
     set_udp_fp_processor(mod_conf.udp_processor);
+    set_host_cache_mac(host_cache_mac_ptr);
     return false;  // no work to do after this
 }
 
@@ -155,7 +179,10 @@ static int delete_mac_host(lua_State* L)
             return 0;
 
         MacKey search_mk(mac);
-        bool success = host_cache_mac.remove((const uint8_t*) &search_mk);
+        HostCacheMac* mac_cache = get_host_cache_mac();
+        assert(mac_cache);
+
+        bool success = mac_cache->remove((const uint8_t*) &search_mk);
 
         if (!success)
         {
@@ -188,7 +215,10 @@ static int delete_mac_host_proto(lua_State* L)
             return 0;
 
         MacKey search_mk(mac);
-        auto htm = host_cache_mac.find((const uint8_t*) &search_mk);
+        HostCacheMac* mac_cache = get_host_cache_mac();
+        assert(mac_cache);
+
+        auto htm = mac_cache->find((const uint8_t*) &search_mk);
 
         if (!htm)
         {
@@ -234,6 +264,8 @@ static const Command rna_cmds[] =
         "delete a MAC from rna's MAC cache"},
     { "delete_mac_host_proto", delete_mac_host_proto, mac_delete_proto_params,
         "delete a protocol associated with a MAC host"},
+    { "purge_data", purge_data, nullptr,
+        "purge all host cache and mac cache data"},
     { nullptr, nullptr, nullptr, nullptr }
 };
 
@@ -553,8 +585,10 @@ bool RnaModule::log_mac_cache(const char* outfile)
     }
 
     string str;
-    const auto&& lru_data = host_cache_mac.get_all_data();
-    out_stream << "Current mac cache size: " << host_cache_mac.mem_size() << " bytes, "
+    HostCacheMac* host_cache_mac = get_host_cache_mac();
+    assert(host_cache_mac);
+    const auto&& lru_data = host_cache_mac->get_all_data();
+    out_stream << "Current mac cache size: " << host_cache_mac->mem_size() << " bytes, "
         << lru_data.size() << " trackers" << endl << endl;
     for ( const auto& elem : lru_data )
     {
index a3638b8f10f6739621f3553e740ee49f79a9765a..581084179ae3835ca6a0d2f9eb9e3deaaa99cf71 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "rna_config.h"
 #include "rna_fingerprint.h"
+#include "rna_mac_cache.h"
 #include "rna_name.h"
 
 struct RnaStats
@@ -57,7 +58,8 @@ extern THREAD_LOCAL const snort::Trace* rna_trace;
 class FpProcReloadTuner : public snort::ReloadResourceTuner
 {
 public:
-    explicit FpProcReloadTuner(RnaModuleConfig& mod_conf) : mod_conf(mod_conf) { }
+    explicit FpProcReloadTuner(RnaModuleConfig& mod_conf, HostCacheMac* ptr = nullptr)
+       : mod_conf(mod_conf), host_cache_mac_ptr(ptr) { }
     ~FpProcReloadTuner() override = default;
 
     bool tinit() override;
@@ -70,6 +72,7 @@ public:
 
 private:
     RnaModuleConfig& mod_conf;
+    HostCacheMac* host_cache_mac_ptr = nullptr;
 };
 
 class RnaModule : public snort::Module
index 3ba5302372da6989dc1603da1acfa66a6973d910..577bc2436c50daf4c06cb9263ce7b8391f24ac20 100644 (file)
@@ -53,6 +53,47 @@ using namespace std;
 #define RNA_NAT_COUNT_THRESHOLD 10
 #define RNA_NAT_TIMEOUT_THRESHOLD 10    // timeout in seconds
 
+static THREAD_LOCAL HostCacheMac* local_mac_cache_ptr = nullptr;
+
+HostCacheMac* get_host_cache_mac()
+{
+    return local_mac_cache_ptr;
+}
+
+void set_host_cache_mac(HostCacheMac* mac_host)
+{
+    local_mac_cache_ptr = mac_host;
+}
+
+HostCacheIp::Data RnaPnd::find_or_create_host_tracker(const SfIp& ip, bool& new_host)
+{
+    auto ht = host_cache.find_else_create(ip, &new_host);
+
+    // If it's a new host, it's automatically visible, so we don't do anything.
+    // If it's not a new host, we're rediscovering it, so make it visible.
+    // Also if it was not new (we had it in the cache) and it went from
+    // not visible to visible, then it's as good as new.
+    if (!new_host and !ht->set_visibility(true))
+        new_host = true;
+
+    return ht;
+}
+
+RnaPnd::RnaPnd(const bool en, const std::string& cp, RnaConfig* rc) :
+    logger(RnaLogger(en)), filter(DiscoveryFilter(cp)), conf(rc)
+{
+    update_timeout = (rc ? rc->update_timeout : 0);
+    host_cache_mac_ptr = new HostCacheMac(MAC_CACHE_INITIAL_SIZE);
+    set_host_cache_mac(host_cache_mac_ptr);
+}
+
+RnaPnd::~RnaPnd()
+{
+    delete host_cache_mac_ptr;
+    host_cache_mac_ptr = nullptr;
+    set_host_cache_mac(nullptr);
+}
+
 void RnaPnd::analyze_appid_changes(DataEvent& event)
 {
     RnaAppDiscovery::process(static_cast<AppidEvent*>(&event), filter, conf, logger);
@@ -140,14 +181,7 @@ void RnaPnd::discover_network(const Packet* p, uint8_t ttl)
     const auto& src_ip = p->ptrs.ip_api.get_src();
     const auto& src_ip_ptr = (const struct in6_addr*) src_ip->get_ip6_ptr();
 
-    auto ht = host_cache.find_else_create(*src_ip, &new_host);
-
-    // If it's a new host, it's automatically visible, so we don't do anything.
-    // If it's not a new host, we're rediscovering it, so make it visible.
-    // Also if it was not new (we had it in the cache) and it went from
-    // not visible to visible, then it's as good as new.
-    if (!new_host and !ht->set_visibility(true))
-        new_host = true;
+    auto ht = find_or_create_host_tracker(*src_ip, new_host);
 
     uint32_t last_seen = ht->get_last_seen();
     if ( !new_host )
@@ -225,12 +259,12 @@ void RnaPnd::analyze_dhcp_fingerprint(DataEvent& event)
     bool new_host = false;
     bool new_mac = false;
     const auto& src_ip = p->ptrs.ip_api.get_src();
-    auto ht = host_cache.find_else_create(*src_ip, &new_host);
+    auto ht = find_or_create_host_tracker(*src_ip, new_host);
     if (!new_host)
         ht->update_last_seen();
 
     MacKey mk(src_mac);
-    auto hm_ptr = host_cache_mac.find_else_create(mk, &new_mac);
+    auto hm_ptr = local_mac_cache_ptr->find_else_create(mk, &new_mac);
     if (new_mac)
     {
         ht->add_mac(mk.mac_addr, p->ptrs.ip_api.ttl(), 0);
@@ -274,12 +308,12 @@ void RnaPnd::add_dhcp_info(DataEvent& event)
     SfIp router_ip = {(void*)&router, AF_INET};
     bool new_host = false;
     bool new_mac = false;
-    auto ht = host_cache.find_else_create(leased_ip, &new_host);
+    auto ht = find_or_create_host_tracker(leased_ip, new_host);
     if (!new_host)
         ht->update_last_seen();
 
     MacKey mk(src_mac);
-    auto hm_ptr = host_cache_mac.find_else_create(mk, &new_mac);
+    auto hm_ptr = local_mac_cache_ptr->find_else_create(mk, &new_mac);
     if (new_mac)
     {
         ht->add_mac(mk.mac_addr, p->ptrs.ip_api.ttl(), 0);
@@ -396,7 +430,7 @@ void RnaPnd::generate_change_host_update()
         return;
 
     auto hosts = host_cache.get_all_data();
-    auto mac_hosts = host_cache_mac.get_all_data();
+    auto mac_hosts = local_mac_cache_ptr->get_all_data();
     auto sec = time(nullptr);
 
     for ( auto & h : hosts )
@@ -416,7 +450,7 @@ void RnaPnd::generate_new_host_mac(const Packet* p, RnaTracker ht, bool discover
     bool new_host_mac = false;
     MacKey mk(layer::get_eth_layer(p)->ether_src);
 
-    auto hm_ptr = host_cache_mac.find_else_create(mk, &new_host_mac);
+    auto hm_ptr = local_mac_cache_ptr->find_else_create(mk, &new_host_mac);
 
     if ( new_host_mac )
     {
@@ -550,8 +584,9 @@ int RnaPnd::discover_network_arp(const Packet* p, RnaTracker* ht_ref)
 
     bool new_host = false;
     bool new_host_mac = false;
-    auto ht = host_cache.find_else_create(spa, &new_host);
-    auto hm_ptr = host_cache_mac.find_else_create(mk, &new_host_mac);
+    auto ht = find_or_create_host_tracker(spa, new_host);
+
+    auto hm_ptr = local_mac_cache_ptr->find_else_create(mk, &new_host_mac);
 
     if ( !new_host_mac )
         hm_ptr->update_last_seen(p->pkth->ts.tv_sec);
@@ -634,7 +669,7 @@ int RnaPnd::discover_switch(const Packet* p, RnaTracker ht_ref)
     bool new_host_mac = false;
     MacKey mk(layer::get_eth_layer(p)->ether_src);
 
-    auto hm_ptr = host_cache_mac.find_else_create(mk, &new_host_mac);
+    auto hm_ptr = local_mac_cache_ptr->find_else_create(mk, &new_host_mac);
 
     if ( new_host_mac )
     {
index c85d5b2271b211bdbaa124bbc61bf981885e7876..c4d8caf5f1aa550dff26140bf37ab035510e0e8a 100644 (file)
@@ -117,9 +117,8 @@ class RnaPnd
 {
 public:
 
-    RnaPnd(const bool en, const std::string& cp, RnaConfig* rc = nullptr) :
-        logger(RnaLogger(en)), filter(DiscoveryFilter(cp)), conf(rc)
-        { update_timeout = (rc ? rc->update_timeout : 0); }
+    RnaPnd(const bool en, const std::string& cp, RnaConfig* rc = nullptr);
+    ~RnaPnd();
 
     void analyze_appid_changes(snort::DataEvent&);
     void analyze_flow_icmp(const snort::Packet*);
@@ -133,6 +132,10 @@ public:
     // generate change event for all hosts in the ip cache
     void generate_change_host_update();
 
+    static HostCacheIp::Data find_or_create_host_tracker(const snort::SfIp&, bool&);
+
+    HostCacheMac* host_cache_mac_ptr = nullptr;
+
 private:
     // generate change event for single host
     void generate_change_host_update(RnaTracker*, const snort::Packet*,
@@ -177,4 +180,7 @@ private:
     time_t update_timeout;
 };
 
+HostCacheMac* get_host_cache_mac();
+void set_host_cache_mac(HostCacheMac* mac_host);
+
 #endif
index 9cdb23b5028789a92700350d8ce295259954a552..080de0cc034353be50c1f969262d5da482c285ab 100644 (file)
@@ -1,6 +1,7 @@
 add_cpputest( rna_module_test
     SOURCES
         ../../../framework/parameter.cc
+        ../../../host_tracker/host_cache.cc
         ../rna_fingerprint.cc
         $<TARGET_OBJECTS:catch_tests>
     LIBS
index 2bf28df521c1214b37a052d05ef9b0ea3f94307b..6b95de8949cbf8729d8d76eb246a19bbc80f2f18 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef RNA_MODULE_MOCK_H
 #define RNA_MODULE_MOCK_H
 
+#include "main/request.h"
+
 #include "../rna_mac_cache.cc"
 
 THREAD_LOCAL RnaStats rna_stats;
@@ -108,4 +110,17 @@ private:
 
 } // end of namespace snort
 
+static Request mock_request;
+void Request::respond(const char*, bool, bool) { }
+Request& get_dispatched_request() { return mock_request; }
+
+HostCacheMac* get_host_cache_mac() { return nullptr; }
+
+DataPurgeAC::~DataPurgeAC() { }
+bool DataPurgeAC::execute(Analyzer&, void**) { return true;}
+
+void snort::main_broadcast_command(AnalyzerCommand*, bool) { }
+void set_host_cache_mac(HostCacheMac*) { }
+
+
 #endif