]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2298 in SNORT/snort3 from ~DAVMCPHE/snort3:host_attribute_thread_...
authorDavis McPherson (davmcphe) <davmcphe@cisco.com>
Sun, 26 Jul 2020 19:05:41 +0000 (19:05 +0000)
committerDavis McPherson (davmcphe) <davmcphe@cisco.com>
Sun, 26 Jul 2020 19:05:41 +0000 (19:05 +0000)
Squashed commit of the following:

commit 2806b18847f7ee0bf13cad7f4f4edbfc83b8b464
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Fri Jul 24 15:42:46 2020 -0400

    stream_tcp: only perform paws validation on real packets, skip this on meta-ack packets

commit 743e235cec999c7fe1fd2017f114bcc1f0ebafa2
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Fri Jul 24 12:44:35 2020 -0400

    target_based: streamline host attribute table activate and swap logic on startup and reload

commit 9fdfb1f8849320ec875a6e17976f0e4578784b0c
Author: davis mcpherson <davmcphe@cisco.com>
Date:   Fri Jun 26 14:39:01 2020 -0400

    target_based: refactor host attribute to use the LruCacheShared data store class to support thread safe access

    target_based: add mutex lock to ensure host service accesses are thread safe

    target_based: move host attribute peg counts from the process pegs to stats specific to host attribute operations"

22 files changed:
src/hash/lru_cache_shared.h
src/hash/test/ghash_test.cc
src/main.cc
src/main/analyzer.cc
src/main/analyzer_command.cc
src/main/analyzer_command.h
src/main/modules.cc
src/main/snort.cc
src/main/swapper.cc
src/main/swapper.h
src/main/test/stubs.h
src/network_inspectors/appid/appid_session.cc
src/network_inspectors/binder/binder.cc
src/stream/stream.cc
src/stream/stream.h
src/stream/tcp/tcp_session.cc
src/stream/tcp/tcp_state_handler.cc
src/target_based/host_attributes.cc
src/target_based/host_attributes.h
src/target_based/snort_protocols.cc
src/utils/stats.cc
src/utils/stats.h

index 024dbc4fb7dc034a1d40c0f6d6a2283536ce4b6c..e772548deb4d411ac52511375d4c1c359b397095 100644 (file)
@@ -63,6 +63,8 @@ public:
     LruCacheShared(const size_t initial_size) :
         max_size(initial_size), current_size(0) { }
 
+    virtual ~LruCacheShared() = default;
+
     using Data = std::shared_ptr<Value>;
     using ValueType = Value;
 
@@ -114,29 +116,21 @@ public:
     bool remove(const Key& key, Data& data);
 
     const PegInfo* get_pegs() const
-    {
-        return lru_cache_shared_peg_names;
-    }
+    { return lru_cache_shared_peg_names; }
 
     PegCount* get_counts()
-    {
-        return (PegCount*)&stats;
-    }
+    { return (PegCount*)&stats; }
 
     void lock()
-    {
-        cache_mutex.lock();
-    }
+    { cache_mutex.lock(); }
 
     void unlock()
-    {
-        cache_mutex.unlock();
-    }
+    { cache_mutex.unlock(); }
 
 protected:
-    using LruList = std::list<std::pair<Key, Data> >;
+    using LruList = std::list<std::pair<Key, Data>>;
     using LruListIter = typename LruList::iterator;
-    using LruMap  = std::unordered_map<Key, LruListIter, Hash>;
+    using LruMap = std::unordered_map<Key, LruListIter, Hash>;
     using LruMapIter = typename LruMap::iterator;
 
     static constexpr size_t mem_chunk = sizeof(Data) + sizeof(Value);
index 370c08f6c21e9f0d0435832567d268cac6eabacd..94a3fd288d0aef21ba5c98e73f2510e3bbf021b7 100644 (file)
@@ -107,8 +107,6 @@ TEST(ghash, collision_test)
     // Create a Hash Table with smaller entries
     GHash* t = new GHash(-10, 0, false, nullptr);
 
-    CHECK(t != nullptr);
-
     // Add Nodes to the Hash Table
     for (i=0; i<num; i++)
     {
index dff06ac125170287f53ef964fcc6978da7ce600a..fcb8696b6f3688188e41c01daabebc0e9828c7a8 100644 (file)
@@ -175,7 +175,7 @@ void Pig::start()
     assert(!athread);
     LogMessage("++ [%u] %s\n", idx, analyzer->get_source());
 
-    Swapper* ps = new Swapper(SnortConfig::get_main_conf(), HostAttributes::get_host_attributes_table());
+    Swapper* ps = new Swapper(SnortConfig::get_main_conf());
     athread = new std::thread(std::ref(*analyzer), ps, ++run_num);
 }
 
@@ -371,10 +371,16 @@ int main_reload_config(lua_State* L)
     }
 
     if ( !sc->attribute_hosts_file.empty() )
-        HostAttributes::load_hosts_file(sc, sc->attribute_hosts_file.c_str());
+    {
+        if ( !HostAttributesManager::load_hosts_file(sc, sc->attribute_hosts_file.c_str()) )
+            current_request->respond("== reload failed - host attributes file failed to load\n");
+    }
 
-    HostAttributesTable* old_tc = HostAttributes::get_host_attributes_table();
-    HostAttributesTable* tc = HostAttributes::activate();
+    int32_t num_hosts = HostAttributesManager::get_num_host_entries();
+    if ( num_hosts >= 0 )
+        LogMessage( "host attribute table: %d hosts loaded\n", num_hosts);
+    else
+        LogMessage("No host attribute table loaded\n");
 
     PluginManager::reload_so_plugins_cleanup(sc);
     SnortConfig::set_conf(sc);
@@ -383,7 +389,7 @@ int main_reload_config(lua_State* L)
 
     bool from_shell = ( L != nullptr );
     current_request->respond(".. swapping configuration\n", from_shell);
-    main_broadcast_command(new ACSwap(new Swapper(old, sc, old_tc, tc), current_request, from_shell), from_shell);
+    main_broadcast_command(new ACSwap(new Swapper(old, sc), current_request, from_shell), from_shell);
 
     return 0;
 }
@@ -498,24 +504,20 @@ int main_reload_hosts(lua_State* L)
         return 0;
     }
 
-    proc_stats.attribute_table_overflow = 0;
-    HostAttributes::load_hosts_file(SnortConfig::get_main_conf(), fname);
-
-    HostAttributesTable* old = HostAttributes::get_host_attributes_table();
-    HostAttributesTable* tc = HostAttributes::activate();
-
-    if ( !tc )
+    if ( !HostAttributesManager::load_hosts_file(SnortConfig::get_main_conf(), fname) )
     {
         current_request->respond("== reload failed\n");
         return 0;
     }
 
     proc_stats.attribute_table_reloads++;
-    LogMessage(STDu64 " hosts loaded\n", proc_stats.attribute_table_hosts);
+    int32_t num_hosts = HostAttributesManager::get_num_host_entries();
+    assert( num_hosts >= 0 );
+    LogMessage( "host attribute table: %d hosts loaded\n", num_hosts);
 
     bool from_shell = ( L != nullptr );
     current_request->respond(".. swapping hosts table\n", from_shell);
-    main_broadcast_command(new ACSwap(new Swapper(old, tc), current_request, from_shell), from_shell);
+    main_broadcast_command(new ACHostAttributesSwap(current_request, from_shell), from_shell);
 
     return 0;
 }
index 152736503bf1249093df587ddb865a47f633789f..524c1160e40095520a55d43600d640a5854a5150 100644 (file)
@@ -62,6 +62,7 @@
 #include "pub_sub/finalize_packet_event.h"
 #include "side_channel/side_channel.h"
 #include "stream/stream.h"
+#include "target_based/host_attributes.h"
 #include "time/packet_time.h"
 #include "trace/trace_api.h"
 #include "utils/stats.h"
@@ -637,6 +638,7 @@ void Analyzer::init_unprivileged()
     HighAvailabilityManager::thread_init(); // must be before InspectorManager::thread_init();
     InspectorManager::thread_init(sc);
     PacketTracer::thread_init();
+    HostAttributesManager::initialize();
 
     // in case there are HA messages waiting, process them first
     HighAvailabilityManager::process_receive();
index 5528a3032ec22c4c106302f6e55af72c01de23e1..b381a9bd4ba008337b3ccaf4c9f697eb00fd7c8c 100644 (file)
@@ -28,6 +28,7 @@
 #include "framework/module.h"
 #include "log/messages.h"
 #include "managers/module_manager.h"
+#include "target_based/host_attributes.h"
 #include "utils/stats.h"
 
 #include "analyzer.h"
@@ -165,11 +166,34 @@ ACSwap::~ACSwap()
             sc->clear_reload_resource_tuner_list();
     }
     delete ps;
+    HostAttributesManager::swap_cleanup();
+
     Swapper::set_reload_in_progress(false);
     LogMessage("== reload complete\n");
     request->respond("== reload complete\n", from_shell, true);
 }
 
+ACHostAttributesSwap::ACHostAttributesSwap(Request* req, bool from_shell)
+    : request(req), from_shell(from_shell)
+{
+    assert(Swapper::get_reload_in_progress() == false);
+    Swapper::set_reload_in_progress(true);
+}
+
+bool ACHostAttributesSwap::execute(Analyzer&, void**)
+{
+    HostAttributesManager::initialize();
+    return true;
+}
+
+ACHostAttributesSwap::~ACHostAttributesSwap()
+{
+    HostAttributesManager::swap_cleanup();
+    Swapper::set_reload_in_progress(false);
+    LogMessage("== reload host attributes complete\n");
+    request->respond("== reload host attributes complete\n", from_shell, true);
+}
+
 bool ACDAQSwap::execute(Analyzer& analyzer, void**)
 {
     analyzer.reload_daq();
index c4ecc2637b721268de0d961facc811449b9ce0df..ee8c09831f932a3e59a49f92d3c1d68c178f8f83 100644 (file)
@@ -116,6 +116,19 @@ private:
     bool from_shell;
 };
 
+class ACHostAttributesSwap : public snort::AnalyzerCommand
+{
+public:
+    ACHostAttributesSwap(Request* req, bool from_shell);
+    bool execute(Analyzer&, void**) override;
+    const char* stringify() override { return "HOST_ATTRIBUTES_SWAP"; }
+    ~ACHostAttributesSwap() override;
+
+private:
+    Request* request;
+    bool from_shell;
+};
+
 class ACDAQSwap : public snort::AnalyzerCommand
 {
 public:
index 4fa9bd0b5d7444e95007924e9b3ef5c38db8ed7d..b6732286734b3dcea994ebed63dae8c45c404c0a 100644 (file)
@@ -1899,6 +1899,24 @@ bool RuleStateModule::end(const char* fqn, int, SnortConfig* sc)
 // hosts module
 //-------------------------------------------------------------------------
 
+class HostAttributesReloadTuner : public snort::ReloadResourceTuner
+{
+public:
+    HostAttributesReloadTuner() = default;
+
+    bool tinit() override
+    {
+        HostAttributesManager::initialize();
+        return true;
+    }
+
+    bool tune_packet_context() override
+    { return true; }
+
+    bool tune_idle_context() override
+    { return true; }
+};
+
 static const Parameter service_params[] =
 {
     { "name", Parameter::PT_STRING, nullptr, nullptr,
@@ -1937,40 +1955,53 @@ class HostsModule : public Module
 {
 public:
     HostsModule() : Module("hosts", hosts_help, hosts_params, true)
-    { app = nullptr; host = nullptr; }
-    ~HostsModule() override { assert(!host && !app); }
+    { host = nullptr; }
+
+    ~HostsModule() override
+    { assert(!host); }
 
     bool set(const char*, Value&, SnortConfig*) override;
     bool begin(const char*, int, SnortConfig*) override;
     bool end(const char*, int, SnortConfig*) override;
 
+    const PegInfo* get_pegs() const override
+    { return HostAttributesManager::get_pegs(); }
+
+    PegCount* get_counts() const override
+    { return HostAttributesManager::get_peg_counts(); }
+
     Usage get_usage() const override
     { return GLOBAL; }
 
 private:
-    ApplicationEntry* app;
-    HostAttributeEntry* host;
+    HostServiceDescriptor service;
+    HostAttributesEntry host;
+    HostAttributesReloadTuner hart;
 };
 
 bool HostsModule::set(const char*, Value& v, SnortConfig* sc)
 {
     if ( host and v.is("ip") )
-        v.get_addr(host->ipAddr);
+    {
+        SfIp addr;
+        v.get_addr(addr);
+        host->set_ip_addr(addr);
+    }
 
     else if ( host and v.is("frag_policy") )
-        host->hostInfo.fragPolicy = v.get_uint8() + 1;
+        host->set_frag_policy(v.get_uint8() + 1);
 
     else if ( host and v.is("tcp_policy") )
-        host->hostInfo.streamPolicy = v.get_uint8();
+        host->set_stream_policy(v.get_uint8());
 
-    else if ( app and v.is("name") )
-        app->snort_protocol_id = sc->proto_ref->add(v.get_string());
+    else if ( v.is("name") )
+        service.snort_protocol_id = sc->proto_ref->add(v.get_string());
 
-    else if ( app and v.is("proto") )
-        app->ipproto = sc->proto_ref->add(v.get_string());
+    else if ( v.is("proto") )
+        service.ipproto = sc->proto_ref->add(v.get_string());
 
-    else if ( app and v.is("port") )
-        app->port = v.get_uint16();
+    else if ( v.is("port") )
+        service.port = v.get_uint16();
 
     else
         return false;
@@ -1981,9 +2012,9 @@ bool HostsModule::set(const char*, Value& v, SnortConfig* sc)
 bool HostsModule::begin(const char* fqn, int idx, SnortConfig*)
 {
     if ( idx && !strcmp(fqn, "hosts.services") )
-        app = new ApplicationEntry;
+        service.reset();
     else if ( idx && !strcmp(fqn, "hosts") )
-        host = new HostAttributeEntry;
+        host.reset(new HostAttributesDescriptor);
 
     return true;
 }
@@ -1992,15 +2023,24 @@ bool HostsModule::end(const char* fqn, int idx, SnortConfig* sc)
 {
     if ( idx && !strcmp(fqn, "hosts.services") )
     {
-        host->add_service(app);
-        app = nullptr;
+        bool updated = false;
+        host->update_service(service.port, service.ipproto, service.snort_protocol_id, updated);
+        service.reset();
     }
     else if ( idx && !strcmp(fqn, "hosts") )
     {
-        if ( !HostAttributes::add_host(host, sc) )
-            delete host;
+        if ( !HostAttributesManager::add_host(host, sc) )
+            host.reset();
         host = nullptr;
     }
+    else if ( !idx && !strcmp(fqn, "hosts"))
+    {
+        if ( HostAttributesManager::activate() )
+        {
+            if ( Snort::is_reloading() )
+                sc->register_reload_resource_tuner(hart);
+        }
+    }
 
     return true;
 }
index e3303a56e9940e8d91975405bf3195828246a016..432cbf5c510b29ceb44fe1848eba704f8808e331 100644 (file)
@@ -183,7 +183,10 @@ void Snort::init(int argc, char** argv)
     sc->setup();
 
     if ( !sc->attribute_hosts_file.empty() )
-        HostAttributes::load_hosts_file(sc, sc->attribute_hosts_file.c_str());
+    {
+        if ( !HostAttributesManager::load_hosts_file(sc, sc->attribute_hosts_file.c_str()) )
+            ParseError("host attributes file failed to load\n");
+    }
 
     // Must be after CodecManager::instantiate()
     if ( !InspectorManager::configure(sc) )
@@ -216,8 +219,6 @@ void Snort::init(int argc, char** argv)
     if ((offload_search_api != nullptr) and (offload_search_api != search_api))
         MpseManager::activate_search_engine(offload_search_api, sc);
 
-    HostAttributes::activate();
-
 #ifdef PIGLET
     if ( !Piglet::piglet_mode() )
 #endif
@@ -319,7 +320,7 @@ void Snort::term()
 
     term_signals();
     IpsManager::global_term(sc);
-    HostAttributes::cleanup();
+    HostAttributesManager::term();
 
 #ifdef PIGLET
     if ( !Piglet::piglet_mode() )
index cdbe3469bffad3bb0329d94f088822b0185148ee..39f6a09a7b9941999d470661bf397306d087298c 100644 (file)
@@ -23,8 +23,6 @@
 
 #include "swapper.h"
 
-#include "target_based/host_attributes.h"
-
 #include "analyzer.h"
 #include "snort.h"
 #include "snort_config.h"
@@ -33,51 +31,28 @@ using namespace snort;
 
 bool Swapper::reload_in_progress = false;
 
-Swapper::Swapper(SnortConfig* s, HostAttributesTable* t)
+Swapper::Swapper(SnortConfig* s)
 {
     old_conf = nullptr;
     new_conf = s;
-
-    old_attribs = nullptr;
-    new_attribs = t;
 }
 
 Swapper::Swapper(const SnortConfig* sold, SnortConfig* snew)
 {
     old_conf = sold;
     new_conf = snew;
-
-    old_attribs = nullptr;
-    new_attribs = nullptr;
-}
-
-Swapper::Swapper(
-    const SnortConfig* sold, SnortConfig* snew,
-    HostAttributesTable* told, HostAttributesTable* tnew)
-{
-    old_conf = sold;
-    new_conf = snew;
-
-    old_attribs = told;
-    new_attribs = tnew;
 }
 
-Swapper::Swapper(HostAttributesTable* told, HostAttributesTable* tnew)
+Swapper::Swapper()
 {
     old_conf = nullptr;
     new_conf = nullptr;
-
-    old_attribs = told;
-    new_attribs = tnew;
 }
 
 Swapper::~Swapper()
 {
     if ( old_conf )
         delete old_conf;
-
-    if ( old_attribs )
-        delete old_attribs;
 }
 
 void Swapper::apply(Analyzer& analyzer)
@@ -90,7 +65,4 @@ void Swapper::apply(Analyzer& analyzer)
         if ( reload )
             analyzer.reinit(new_conf);
     }
-
-    if ( new_attribs )
-        HostAttributes::set_host_attributes_table(new_attribs);
 }
index bc222d07c51cacce5d307ed8be6c721f2b7949a8..beca13f9dc595a1fdbe911191f9a5e68d3ad6589 100644 (file)
@@ -28,18 +28,13 @@ struct SnortConfig;
 }
 
 class Analyzer;
-struct HostAttributesTable;
 
 class Swapper
 {
 public:
-    Swapper(snort::SnortConfig*, HostAttributesTable*);
+    Swapper(snort::SnortConfig*);
     Swapper(const snort::SnortConfig* sold, snort::SnortConfig* snew);
-
-    Swapper(const snort::SnortConfig* sold, snort::SnortConfig* snew,
-        HostAttributesTable*, HostAttributesTable*);
-
-    Swapper(HostAttributesTable*, HostAttributesTable*);
+    Swapper();
     ~Swapper();
 
     void apply(Analyzer&);
@@ -52,9 +47,6 @@ private:
     const snort::SnortConfig* old_conf;
     snort::SnortConfig* new_conf;
 
-    HostAttributesTable* old_attribs;
-    HostAttributesTable* new_attribs;
-
     static bool reload_in_progress;
 };
 
index 7d46a49ed72c91a418f2fb57064203a73f76b527..5405b56ba05b0603dc56a28d93349d8d19de91e0 100644 (file)
@@ -56,6 +56,7 @@
 #include "protocols/packet_manager.h"
 #include "side_channel/side_channel.h"
 #include "stream/stream.h"
+#include "target_based/host_attributes.h"
 #include "time/packet_time.h"
 #include "trace/trace_api.h"
 #include "utils/dnet_header.h"
@@ -113,6 +114,7 @@ ssize_t ip_send(ip_t*, const void*, size_t) { return -1; }
 eth_t* eth_open(const char*) { return nullptr; }
 eth_t* eth_close(eth_t*) { return nullptr; }
 ssize_t eth_send(eth_t*, const void*, size_t) { return -1; }
+void HostAttributesManager::initialize() { }
 
 namespace snort
 {
index a73567f5aa43f70701fc38622a62727ca2d101c5..cd1b7e9c405f8fd39267a6515dc1f25d9abe6f0e 100644 (file)
@@ -346,7 +346,7 @@ void AppIdSession::sync_with_snort_protocol_id(AppId newAppId, Packet* p)
     if (tmp_snort_protocol_id != snort_protocol_id)
     {
         snort_protocol_id = tmp_snort_protocol_id;
-        p->flow->ssn_state.snort_protocol_id = tmp_snort_protocol_id;
+        Stream::set_snort_protocol_id(p->flow, tmp_snort_protocol_id);
     }
 }
 
index f4d85f2d48ecf256cda130b9292500be0d18fdf0..01ef05ace7e9849c485b868a96b4c6afff7938e8 100644 (file)
@@ -436,7 +436,7 @@ static void set_session(Flow* flow)
     flow->clouseau = nullptr;
 }
 
-static void set_service(Flow* flow, const HostAttributeEntry* host)
+static void set_service(Flow* flow, const HostAttributesEntry host)
 {
     Stream::set_snort_protocol_id(flow, host, FROM_SERVER);
 }
@@ -671,8 +671,8 @@ struct Stuff
     bool update(Binding*);
 
     bool apply_action(Flow*);
-    void apply_session(Flow*, const HostAttributeEntry*);
-    void apply_service(Flow*, const HostAttributeEntry*);
+    void apply_session(Flow*, const HostAttributesEntry);
+    void apply_service(Flow*, const HostAttributesEntry);
     void apply_assistant(Flow*, const char*);
 };
 
@@ -735,7 +735,7 @@ bool Stuff::apply_action(Flow* flow)
     return true;
 }
 
-void Stuff::apply_session(Flow* flow, const HostAttributeEntry* host)
+void Stuff::apply_session(Flow* flow, const HostAttributesEntry host)
 {
     if ( server )
     {
@@ -753,7 +753,7 @@ void Stuff::apply_session(Flow* flow, const HostAttributeEntry* host)
     {
     case PktType::IP:
         set_session(flow, INS_IP);
-        flow->ssn_policy = host ? host->hostInfo.fragPolicy : 0;
+        flow->ssn_policy = host ? host->get_frag_policy() : 0;
         break;
 
     case PktType::ICMP:
@@ -762,7 +762,7 @@ void Stuff::apply_session(Flow* flow, const HostAttributeEntry* host)
 
     case PktType::TCP:
         set_session(flow, INS_TCP);
-        flow->ssn_policy = host ? host->hostInfo.streamPolicy : 0;
+        flow->ssn_policy = host ? host->get_stream_policy() : 0;
         break;
 
     case PktType::UDP:
@@ -782,7 +782,7 @@ void Stuff::apply_session(Flow* flow, const HostAttributeEntry* host)
     }
 }
 
-void Stuff::apply_service(Flow* flow, const HostAttributeEntry* host)
+void Stuff::apply_service(Flow* flow, const HostAttributesEntry host)
 {
     if ( data )
         flow->set_data(data);
@@ -1210,7 +1210,7 @@ void Binder::apply(Flow* flow, Stuff& stuff)
     if ( !stuff.apply_action(flow) )
         return;
 
-    const HostAttributeEntry* host = HostAttributes::find_host(&flow->server_ip);
+    const HostAttributesEntry host = HostAttributesManager::find_host(flow->server_ip);
 
     // setup session
     stuff.apply_session(flow, host);
index 06bace61095a91748067ed14bbc92ed037f38e5d..03ab41e36a4edbb5bfc2e24afc05228ac28a47e1 100644 (file)
@@ -397,11 +397,11 @@ int Stream::set_snort_protocol_id_expected(
 }
 
 void Stream::set_snort_protocol_id(
-    Flow* flow, const HostAttributeEntry* host_entry, int /*direction*/)
+    Flow* flow, const HostAttributesEntry& host, int /*direction*/)
 {
     SnortProtocolId snort_protocol_id;
 
-    if (!flow || !host_entry)
+    if (!flow )
         return;
 
     /* Cool, its already set! */
@@ -413,7 +413,7 @@ void Stream::set_snort_protocol_id(
         set_ip_protocol(flow);
     }
 
-    snort_protocol_id = host_entry->get_snort_protocol_id
+    snort_protocol_id = host->get_snort_protocol_id
         (flow->ssn_state.ipprotocol, flow->server_port);
 
 #if 0
@@ -445,21 +445,19 @@ SnortProtocolId Stream::get_snort_protocol_id(Flow* flow)
         return flow->ssn_state.snort_protocol_id;
 
     if (flow->ssn_state.ipprotocol == 0)
-    {
         set_ip_protocol(flow);
-    }
 
-    if ( HostAttributeEntry* host_entry = HostAttributes::find_host(&flow->server_ip) )
+    if ( HostAttributesEntry host = HostAttributesManager::find_host(flow->server_ip) )
     {
-        set_snort_protocol_id(flow, host_entry, FROM_SERVER);
+        set_snort_protocol_id(flow, host, FROM_SERVER);
 
         if (flow->ssn_state.snort_protocol_id != UNKNOWN_PROTOCOL_ID)
             return flow->ssn_state.snort_protocol_id;
     }
 
-    if ( HostAttributeEntry* host_entry = HostAttributes::find_host(&flow->client_ip) )
+    if ( HostAttributesEntry host = HostAttributesManager::find_host(flow->client_ip) )
     {
-        set_snort_protocol_id(flow, host_entry, FROM_CLIENT);
+        set_snort_protocol_id(flow, host, FROM_CLIENT);
 
         if (flow->ssn_state.snort_protocol_id != UNKNOWN_PROTOCOL_ID)
             return flow->ssn_state.snort_protocol_id;
@@ -481,9 +479,10 @@ SnortProtocolId Stream::set_snort_protocol_id(Flow* flow, SnortProtocolId id)
 
     if ( !flow->is_proxied() )
     {
-        HostAttributes::update_service
-            (&flow->server_ip, flow->server_port, flow->ssn_state.ipprotocol, id);
+        HostAttributesManager::update_service
+            (flow->server_ip, flow->server_port, flow->ssn_state.ipprotocol, id);
     }
+
     return id;
 }
 
index 1c89fcbca7d10eb6987dcb2b7fe4601d8445f498..c6ea2c62456b3e80864905626bba2b8239ec5ad2 100644 (file)
 
 // provides a common flow management interface
 
+#include <memory>
+
 #include "flow/flow.h"
 
-struct HostAttributeEntry;
+class HostAttributesDescriptor;
+typedef std::shared_ptr<HostAttributesDescriptor> HostAttributesEntry;
 
 namespace snort
 {
@@ -204,7 +207,7 @@ public:
     static void populate_flow_key(Packet*, FlowKey*);
 
     static void set_snort_protocol_id(
-        Flow*, const HostAttributeEntry*, int direction);
+        Flow*, const HostAttributesEntry&, int direction);
 
     static bool is_midstream(Flow* flow)
     { return ((flow->ssn_state.session_flags & SSNFLAG_MIDSTREAM) != 0); }
index 6124519b94938c76dd41b7bcc69e905daca19df8..5f9a9fe5a83638dcbc721911908c49643c1e1f69 100644 (file)
@@ -1054,12 +1054,13 @@ bool TcpSession::validate_packet_established_session(TcpSegmentDescriptor& tsd)
 {
     TcpStreamTracker* listener = tsd.get_listener();
 
-    pkt_action_mask |= listener->normalizer.handle_paws(tsd);
-
     if ( tsd.is_policy_inline() )
        if ( tsd.get_tcph()->is_ack() && !listener->is_ack_valid(tsd.get_ack()) )
            pkt_action_mask |= ACTION_BAD_PKT;
 
+    if ( !tsd.is_meta_ack_packet() )
+        pkt_action_mask |= listener->normalizer.handle_paws(tsd);
+
     return ( pkt_action_mask & ACTION_BAD_PKT ) ? false : true;
 }
 
index 7aa331d48c5d9888e1f0c949b34172b700f65b25..d0e83344bf74b6eae4208866f5a6024cc785824f 100644 (file)
@@ -118,7 +118,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         WHEN("SYN is sent")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             client_tracker->set_tcp_event(TcpStreamTracker::TCP_SYN_SENT_EVENT);
             tsh->eval(*tsd, *client_tracker);
             THEN("Event should be TCP_SYN_SENT_EVENT")
@@ -131,7 +130,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("SYN is received")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             server_tracker->set_tcp_event(TcpStreamTracker::TCP_SYN_RECV_EVENT);
             tsh->eval(*tsd, *server_tracker);
             CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
@@ -149,7 +147,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("syn_ack_sent")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             client_tracker->set_tcp_event(TcpStreamTracker::TCP_SYN_ACK_SENT_EVENT);
             tsh->eval(*tsd, *client_tracker);
             CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
@@ -159,7 +156,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("syn_ack_recv")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             server_tracker->set_tcp_event(TcpStreamTracker::TCP_SYN_ACK_RECV_EVENT);
             tsh->eval(*tsd, *server_tracker);
             CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
@@ -177,7 +173,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("ack_sent")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             client_tracker->set_tcp_event(TcpStreamTracker::TCP_ACK_SENT_EVENT);
             tsh->eval(*tsd, *client_tracker);
             CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
@@ -187,7 +182,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("ack_recv")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             server_tracker->set_tcp_event(TcpStreamTracker::TCP_ACK_RECV_EVENT);
             tsh->eval(*tsd, *server_tracker);
             CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
@@ -205,7 +199,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("data_seg_sent")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             client_tracker->set_tcp_event(TcpStreamTracker::TCP_DATA_SEG_SENT_EVENT);
             tsh->eval(*tsd, *client_tracker);
             CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
@@ -215,7 +208,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("data_seg_recv")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             server_tracker->set_tcp_event(TcpStreamTracker::TCP_DATA_SEG_RECV_EVENT);
             tsh->eval(*tsd, *server_tracker);
             CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
@@ -233,7 +225,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("fin_sent")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             client_tracker->set_tcp_event(TcpStreamTracker::TCP_FIN_SENT_EVENT);
             tsh->eval(*tsd, *client_tracker);
             CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
@@ -243,7 +234,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("fin_recv")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             server_tracker->set_tcp_event(TcpStreamTracker::TCP_FIN_RECV_EVENT);
             tsh->eval(*tsd, *server_tracker);
             CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
@@ -261,7 +251,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("rst_sent")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             client_tracker->set_tcp_event(TcpStreamTracker::TCP_RST_SENT_EVENT);
             tsh->eval(*tsd, *client_tracker);
             CHECK( ( tsh->get_tcp_event() == client_tracker->get_tcp_event() ) );
@@ -271,7 +260,6 @@ SCENARIO("TCP State Handler Base Class", "[state_handlers][stream_tcp]")
         SECTION("rst_recv")
         {
             TcpSegmentDescriptor* tsd = new TcpSegmentDescriptor(flow, pkt, tel);
-            REQUIRE( ( tsd != nullptr ) );
             server_tracker->set_tcp_event(TcpStreamTracker::TCP_RST_RECV_EVENT);
             tsh->eval(*tsd, *server_tracker);
             CHECK( ( tsh->get_tcp_event() == server_tracker->get_tcp_event() ) );
index 855bc8578a692a884e725923da5b15aeca1975bb..fc1c1600d5463690234a3b1363d1aa910c8c21be 100644 (file)
@@ -17,7 +17,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
 
-// host_attributes.cc  Author: davis mcpherson
+// host_attributes.cc  author davis mcpherson <davmcphe@cisco.com>
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 
 #include "host_attributes.h"
 
-#include "log/messages.h"
+#include "hash/lru_cache_shared.h"
 #include "main/shell.h"
 #include "main/snort_config.h"
-#include "protocols/packet.h"
-#include "sfrt/sfrt.h"
-#include "utils/stats.h"
-#include "utils/util.h"
+#include "main/thread.h"
 
 using namespace snort;
 
-static THREAD_LOCAL HostAttributesTable* curr_cfg = nullptr;
-static HostAttributesTable* next_cfg = nullptr;
-
-void HostAttributesTable::free_host_entry(void* host)
-{ delete (HostAttributeEntry*)host; }
-
-HostAttributesTable::HostAttributesTable(uint32_t max_hosts)
-    : max_hosts(max_hosts)
+static const PegInfo host_attribute_pegs[] =
 {
-    // Add 1 to max for table purposes
-    // We use max_hosts to limit memcap, assume 16k per entry costs
-    // FIXIT-M 16k per host is no longer true
-    host_table = sfrt_new(DIR_8x16, IPv6, max_hosts + 1, (max_hosts >> 6) + 1);
-}
-
-HostAttributesTable::~HostAttributesTable()
+    { CountType::MAX, "total_hosts", "maximum number of entries in the host attribute table" },
+    { CountType::SUM, "hosts_pruned", "number of LRU hosts pruned due to configured resource limits" },
+    { CountType::SUM, "dynamic_host_adds", "number of host additions after initial host file load" },
+    { CountType::SUM, "dynamic_service_adds", "number of service additions after initial host file load" },
+    { CountType::SUM, "dynamic_service_updates", "number of service updates after initial host file load" },
+    { CountType::SUM, "service_list_overflows", "number of service additions that failed due to configured resource limits" },
+    { CountType::END, nullptr, nullptr }
+};
+
+template<typename Key, typename Value, typename Hash>
+class HostLruSharedCache : public LruCacheShared<Key, Value, Hash>
 {
-    sfrt_cleanup(host_table, HostAttributesTable::free_host_entry);
-    sfrt_free(host_table);
-}
+public:
+    HostLruSharedCache(const size_t initial_size) : LruCacheShared<Key, Value, Hash>(initial_size)
+    { }
+};
 
-bool HostAttributesTable::add_host(HostAttributeEntry* host)
-{
-    SfCidr* ipAddr = &host->ipAddr;
-    int ret = sfrt_insert(ipAddr, (unsigned char)ipAddr->get_bits(), host,
-                          RT_FAVOR_SPECIFIC, host_table);
+typedef HostLruSharedCache<snort::SfIp, HostAttributesDescriptor, HostAttributesCacheKey> HostAttributesSharedCache;
 
-    if ( ret == RT_SUCCESS )
-    {
-        ++num_hosts;
-        return true;
-    }
+static THREAD_LOCAL HostAttributesSharedCache* active_cache = nullptr;
+static HostAttributesSharedCache* swap_cache = nullptr;
+static HostAttributesSharedCache* next_cache = nullptr;
+static HostAttributesSharedCache* old_cache = nullptr;
+static THREAD_LOCAL HostAttributeStats host_attribute_stats;
+
+bool HostAttributesDescriptor::update_service
+    (uint16_t port, uint16_t protocol, SnortProtocolId snort_protocol_id, bool& updated)
+{
+    std::lock_guard<std::mutex> lck(host_attributes_lock);
 
-    if ( ret == RT_POLICY_TABLE_EXCEEDED )
+    for ( auto& s : services)
     {
-        if ( !sfat_insufficient_space_logged )
+        if ( s.ipproto == protocol && (uint16_t)s.port == port )
         {
-            ParseWarning(WARN_HOSTS, "Attribute table insertion failed: %d Insufficient "
-                         "space in attribute table, only configured to store %u hosts\n",
-                         ret, max_hosts);
-            sfat_insufficient_space_logged = true;
+            s.snort_protocol_id = snort_protocol_id;
+            updated = true;
+            return true;
         }
-
-        proc_stats.attribute_table_overflow++;
     }
-    else if ( !sfat_grammar_error_printed )
+
+    // service not found, add it
+    if ( services.size() < SnortConfig::get_conf()->get_max_services_per_host() )
     {
-        ParseWarning(WARN_HOSTS, "Attribute table insertion failed: %d '%s'\n",
-                     ret, rt_error_messages[ret]);
-        sfat_grammar_error_printed = true;
+        updated = false;
+        services.emplace_back(HostServiceDescriptor(port, protocol, snort_protocol_id));
+        return true;
     }
 
     return false;
 }
 
-HostAttributeEntry* HostAttributesTable::get_host(SfIp* ipAddr)
+SnortProtocolId HostAttributesDescriptor::get_snort_protocol_id(int ipprotocol, uint16_t port) const
 {
-    HostAttributeEntry* host = (HostAttributeEntry*)sfrt_lookup(ipAddr, host_table);
-    if ( !host && !is_host_attribute_table_full() )
+    std::lock_guard<std::mutex> lck(host_attributes_lock);
+
+    for ( auto& s : services )
     {
-        host = new HostAttributeEntry;
-        host->ipAddr.set(*ipAddr);
-        if ( !curr_cfg->add_host(host) )
-        {
-            delete host;
-            host = nullptr;
-        }
+        if ( (s.ipproto == ipprotocol) && (s.port == port) )
+            return s.snort_protocol_id;
     }
 
-    return host;
-}
-
-HostAttributeEntry* HostAttributesTable::find_host(const SfIp* ipAddr)
-{ return (HostAttributeEntry*)sfrt_lookup(ipAddr, host_table); }
-
-HostAttributeEntry::~HostAttributeEntry()
-{
-   for ( auto app : services )
-       delete app;
+    return UNKNOWN_PROTOCOL_ID;
 }
 
-void HostAttributeEntry::add_service(ApplicationEntry* app)
-{ services.push_back(app); }
-
-void HostAttributeEntry::update_service
-    (HostAttributeEntry* host, uint16_t port, uint16_t protocol, SnortProtocolId snort_protocol_id)
+bool HostAttributesManager::load_hosts_file(snort::SnortConfig* sc, const char* fname)
 {
-    unsigned service_count = 0;
-
-    for ( auto app : services)
-    {
-        if ( app->ipproto == protocol && (uint16_t)app->port == port )
-        {
-            app->snort_protocol_id = snort_protocol_id;
-            return;
-        }
-
-        service_count++;
-    }
+    delete next_cache;
+    next_cache = new HostAttributesSharedCache(sc->max_attribute_hosts);
 
-    // application service not found, add it
-    if ( service_count >= SnortConfig::get_conf()->get_max_services_per_host() )
-        return;
+    Shell sh(fname);
+    if ( sh.configure(sc, false, true) )
+        return true;
 
-    ApplicationEntry* app = new ApplicationEntry(port, protocol, snort_protocol_id);
-    host->add_service(app);
+    // loading of host file failed...
+    delete next_cache;
+    next_cache = nullptr;
+    return false;
 }
 
-SnortProtocolId HostAttributeEntry::get_snort_protocol_id(int ipprotocol, uint16_t port) const
+bool HostAttributesManager::add_host(HostAttributesEntry host, snort::SnortConfig* sc)
 {
-    for ( auto app : services )
-    {
-        if ( (app->ipproto == ipprotocol) && (app->port == port) )
-            return app->snort_protocol_id;
-    }
+    if ( !next_cache )
+        next_cache = new HostAttributesSharedCache(sc->max_attribute_hosts);
 
-    return 0;
+    return next_cache->find_else_insert(host->get_ip_addr(), host, true);
 }
 
-void HostAttributes::load_hosts_file(SnortConfig* sc, const char* fname)
+bool HostAttributesManager::activate()
 {
-    delete next_cfg;
-    next_cfg = new HostAttributesTable(sc->max_attribute_hosts);
-
-    Shell sh(fname);
+    old_cache = active_cache;
+    active_cache = next_cache;
+    swap_cache = next_cache;
+    next_cache = nullptr;
 
-    if ( !sh.configure(sc, false, true) )
-    {
-        delete next_cfg;
-        next_cfg = nullptr;
-    }
+    return ( active_cache != old_cache ) ? true : false;
 }
 
-HostAttributesTable* HostAttributes::activate()
-{
-    curr_cfg = next_cfg;
-    next_cfg = nullptr;
+void HostAttributesManager::initialize()
+{ active_cache = swap_cache; }
 
-    if ( curr_cfg )
-        proc_stats.attribute_table_hosts = curr_cfg->get_num_hosts();
-    else
-        proc_stats.attribute_table_hosts = 0;
+void HostAttributesManager::swap_cleanup()
+{ delete old_cache; }
 
-    return curr_cfg;
-}
+void HostAttributesManager::term()
+{ delete active_cache; }
 
-void HostAttributes::set_host_attributes_table(HostAttributesTable* p)
-{ curr_cfg = p; }
+HostAttributesEntry HostAttributesManager::find_host(const snort::SfIp& host_ip)
+{
+    if ( active_cache )
+        return active_cache->find(host_ip);
 
-HostAttributesTable* HostAttributes::get_host_attributes_table()
-{ return curr_cfg; }
+    return nullptr;
+}
 
-bool HostAttributes::add_host(HostAttributeEntry* host, snort::SnortConfig* sc)
+void HostAttributesManager::update_service(const snort::SfIp& host_ip, uint16_t port, uint16_t protocol, SnortProtocolId snort_protocol_id)
 {
-    if ( !next_cfg )
-        next_cfg = new HostAttributesTable(sc->max_attribute_hosts);
-
-    return next_cfg->add_host(host);
+    if ( active_cache )
+    {
+        bool created = false;
+        HostAttributesEntry host = active_cache->find_else_create(host_ip, &created);
+        if ( host )
+        {
+            if ( created )
+            {
+                host->set_ip_addr(host_ip);
+                host_attribute_stats.dynamic_host_adds++;
+            }
+
+            bool updated = false;
+            if ( host->update_service(port, protocol, snort_protocol_id, updated) )
+            {
+                if ( updated )
+                    host_attribute_stats.dynamic_service_updates++;
+                else
+                    host_attribute_stats.dynamic_service_adds++;
+            }
+            else
+                host_attribute_stats.service_list_overflows++;
+        }
+    }
 }
 
-HostAttributeEntry* HostAttributes::find_host(const SfIp* ipAddr)
+int32_t HostAttributesManager::get_num_host_entries()
 {
-    if ( !curr_cfg )
-        return nullptr;
+    if ( active_cache )
+        return active_cache->size();
 
-    return curr_cfg->find_host(ipAddr);
+    return -1;
 }
 
-void HostAttributes::update_service(SfIp* ipAddr, uint16_t port, uint16_t protocol, SnortProtocolId snort_protocol_id)
+const PegInfo* HostAttributesManager::get_pegs()
+{ return (const PegInfo*)&host_attribute_pegs; }
+
+PegCount* HostAttributesManager::get_peg_counts()
 {
-    if ( curr_cfg )
+    if ( active_cache )
     {
-        HostAttributeEntry* host = curr_cfg->get_host(ipAddr);
-        if ( host )
-            host->update_service(host, port, protocol, snort_protocol_id);
+        LruCacheSharedStats* cache_stats = (LruCacheSharedStats*) active_cache->get_counts();
+        host_attribute_stats.hosts_pruned = cache_stats->alloc_prunes;
+        host_attribute_stats.total_hosts = active_cache->size();
     }
+
+    return (PegCount*)&host_attribute_stats;
 }
 
-void HostAttributes::cleanup()
-{ delete curr_cfg; }
index 7cea901a41ef21079b96639e82ebe5fd030d429c..d5bb913ceca9b5ada414eecde17bf914cc09a4e9 100644 (file)
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
 
-// host_attributes.h author davis mcpherson
+// host_attributes.h author davis mcpherson <davmcphe@cisco.com>
 
 #ifndef HOST_ATTRIBUTES_H
 #define HOST_ATTRIBUTES_H
 
 // Provides attribute table initialization, lookup, swap, and releasing.
 
+#include <functional>
+#include <memory>
+#include <mutex>
 #include <vector>
 
-#include "sfip/sf_cidr.h"
-#include "sfrt/sfrt.h"
+#include "framework/counts.h"
+#include "sfip/sf_ip.h"
 #include "target_based/snort_protocols.h"
 
-struct ApplicationEntry
+namespace snort
+{
+struct SnortConfig;
+}
+
+struct HostAttributeStats
+{
+    PegCount total_hosts = 0;
+    PegCount hosts_pruned = 0;
+    PegCount dynamic_host_adds = 0;
+    PegCount dynamic_service_adds = 0;
+    PegCount dynamic_service_updates = 0;
+    PegCount service_list_overflows = 0;
+};
+
+class HostServiceDescriptor
 {
-    ApplicationEntry() = default;
-    ApplicationEntry(uint16_t port, uint16_t protocol, SnortProtocolId spi)
+public:
+    HostServiceDescriptor() = default;
+    HostServiceDescriptor(uint16_t port, uint16_t protocol, SnortProtocolId spi)
         : port(port), ipproto(protocol), snort_protocol_id(spi)
     { }
-    ~ApplicationEntry() = default;
+
+    ~HostServiceDescriptor() = default;
+
+    void reset()
+    {
+        port = 0;
+        ipproto = 0;
+        snort_protocol_id = UNKNOWN_PROTOCOL_ID;
+    }
 
     uint16_t port = 0;
     uint16_t ipproto = 0;
-    SnortProtocolId snort_protocol_id = 0;
+    SnortProtocolId snort_protocol_id = UNKNOWN_PROTOCOL_ID;
 };
 
-struct HostInfo
+struct HostPolicyDescriptor
 {
     uint8_t streamPolicy = 0;
     uint8_t fragPolicy = 0;
 };
 
-struct HostAttributeEntry
+class HostAttributesDescriptor
 {
-    HostAttributeEntry() = default;
-    ~HostAttributeEntry();
+public:
+    HostAttributesDescriptor() = default;
+    ~HostAttributesDescriptor() = default;
 
-    void add_service(ApplicationEntry*);
-    void update_service(HostAttributeEntry*, uint16_t port, uint16_t protocol, SnortProtocolId);
+    bool update_service(uint16_t port, uint16_t protocol, SnortProtocolId, bool& updated);
     SnortProtocolId get_snort_protocol_id(int ipprotocol, uint16_t port) const;
 
-    snort::SfCidr ipAddr;
-    HostInfo hostInfo;
-    std::vector<ApplicationEntry*> services;
-};
-
-#define DEFAULT_MAX_ATTRIBUTE_HOSTS 10000
-#define DEFAULT_MAX_ATTRIBUTE_SERVICES_PER_HOST 100
-#define DEFAULT_MAX_METADATA_SERVICES 9
+    const snort::SfIp& get_ip_addr() const
+    { return ip_address; }
 
-namespace snort
-{
-struct SfIp;
-struct SnortConfig;
-}
+    void set_ip_addr(const snort::SfIp& host_ip_addr)
+    {
+        std::lock_guard<std::mutex> lck(host_attributes_lock);
+        ip_address = host_ip_addr;
+    }
 
-struct HostAttributesTable
-{
-    HostAttributesTable(uint32_t max_hosts);
-    ~HostAttributesTable();
+    uint8_t get_frag_policy() const
+    { return policies.fragPolicy; }
 
-    bool add_host(HostAttributeEntry*);
-    HostAttributeEntry* get_host(snort::SfIp*);
-    HostAttributeEntry* find_host(const snort::SfIp*);
-    void add_service(HostAttributeEntry*, ApplicationEntry*);
+    void set_frag_policy(const uint8_t frag_policy)
+    {
+        std::lock_guard<std::mutex> lck(host_attributes_lock);
+        policies.fragPolicy = frag_policy;
+    }
 
-    bool is_host_attribute_table_full()
-    { return num_hosts >= max_hosts; }
+    uint8_t get_stream_policy() const
+    { return policies.streamPolicy; }
 
-    uint32_t get_num_hosts () const
-    { return num_hosts; }
+    void set_stream_policy(uint8_t stream_policy)
+    {
+        std::lock_guard<std::mutex> lck(host_attributes_lock);
+        policies.streamPolicy = stream_policy;
+    }
 
 private:
-    table_t* host_table;
-    uint32_t max_hosts;
-    uint32_t num_hosts = 0;
+    mutable std::mutex host_attributes_lock; // ensure updates to this shared object are safe
+    snort::SfIp ip_address;
+    HostPolicyDescriptor policies;
+    std::vector<HostServiceDescriptor> services;
+};
 
-    bool sfat_grammar_error_printed = false;
-    bool sfat_insufficient_space_logged = false;
+typedef std::shared_ptr<HostAttributesDescriptor> HostAttributesEntry;
 
-    static void free_host_entry(void* host);
+#define DEFAULT_MAX_ATTRIBUTE_HOSTS 10000
+#define DEFAULT_MAX_ATTRIBUTE_SERVICES_PER_HOST 100
+#define DEFAULT_MAX_METADATA_SERVICES 9
+
+// Create a hash key from an IP address stored in a SfIp object.
+struct HostAttributesCacheKey
+{
+    size_t operator()(const snort::SfIp& ip) const
+    {
+        const uint64_t* ip64 = (const uint64_t*) ip.get_ip6_ptr();
+        return std::hash<uint64_t>() (ip64[0]) ^
+               std::hash<uint64_t>() (ip64[1]);
+    }
 };
 
-class HostAttributes
+class HostAttributesManager
 {
 public:
-    static void load_hosts_file(snort::SnortConfig*, const char* fname);
-    static HostAttributesTable* activate();
-    static HostAttributesTable* get_host_attributes_table();
-    static void set_host_attributes_table(HostAttributesTable*);
-    static bool add_host(HostAttributeEntry*, snort::SnortConfig*);
-    static HostAttributeEntry* find_host(const snort::SfIp* ipAddr);
-    static void update_service(snort::SfIp*, uint16_t port, uint16_t protocol, uint16_t id);
-    static void cleanup();
+    static bool load_hosts_file(snort::SnortConfig*, const char* fname);
+    static bool activate();
+    static void initialize();
+    static void swap_cleanup();
+    static void term();
+
+    static bool add_host(HostAttributesEntry, snort::SnortConfig*);
+    static HostAttributesEntry find_host(const snort::SfIp&);
+    static void update_service(const snort::SfIp&, uint16_t port, uint16_t protocol, SnortProtocolId);
+    static int32_t get_num_host_entries();
+    static const PegInfo* get_pegs();
+    static PegCount* get_peg_counts();
 };
 
-
 #endif
-
index ee9b061e5737a6e388c2deae03851434c2129371..6b120188ca5b20bed69ac3d7ace2aaadc5fce3e0 100644 (file)
@@ -36,9 +36,7 @@ using namespace snort;
 using namespace std;
 
 SnortProtocolId ProtocolReference::get_count()
-{
-    return protocol_number;
-}
+{ return protocol_number; }
 
 const char* ProtocolReference::get_name(SnortProtocolId id)
 {
@@ -74,14 +72,12 @@ const char* ProtocolReference::get_name_sorted(SnortProtocolId id)
 
 SnortProtocolId ProtocolReference::add(const char* protocol)
 {
-    if (!protocol)
+    if ( !protocol )
         return UNKNOWN_PROTOCOL_ID;
 
     auto protocol_ref = ref_table.find(protocol);
     if ( protocol_ref != ref_table.end() )
-    {
         return protocol_ref->second;
-    }
 
     SnortProtocolId snort_protocol_id = protocol_number++;
     id_map.emplace_back(protocol);
@@ -94,16 +90,14 @@ SnortProtocolId ProtocolReference::find(const char* protocol)
 {
     auto protocol_ref = ref_table.find(protocol);
     if ( protocol_ref != ref_table.end() )
-    {
         return protocol_ref->second;
-    }
 
     return UNKNOWN_PROTOCOL_ID;
 }
 
 void ProtocolReference::init(ProtocolReference* old_proto_ref)
 {
-    if(!old_proto_ref)
+    if ( !old_proto_ref )
     {
         bool ok = ( add("unknown") == UNKNOWN_PROTOCOL_ID );
         ok = ( add("ip") == SNORT_PROTO_IP ) and ok;
@@ -115,26 +109,17 @@ void ProtocolReference::init(ProtocolReference* old_proto_ref)
     }
     else
     {
-        // Copy old ProtocolReference ID/name pairs to new ProtocolReference
         for(SnortProtocolId id = 0; id < old_proto_ref->get_count(); id++)
-        {
             add(old_proto_ref->get_name(id));
-        }
     }
 }
 
 ProtocolReference::ProtocolReference()
-{
-    init(nullptr);
-}
+{ init(nullptr); }
 
 ProtocolReference::ProtocolReference(ProtocolReference* old_proto_ref)
-{
-    init(old_proto_ref);
-}
+{ init(old_proto_ref); }
 
 ProtocolReference::~ProtocolReference()
-{
-    ref_table.clear();
-}
+{ ref_table.clear(); }
 
index f5bd5a76749e65e3a0020100398116fc914e64ea..71fc19bb750af45aa827693810c6b4c2163d3800 100644 (file)
@@ -220,8 +220,6 @@ const PegInfo proc_names[] =
     { CountType::SUM, "inspector_deletions", "number of times inspectors were deleted" },
     { CountType::SUM, "daq_reloads", "number of times daq configuration was reloaded" },
     { CountType::SUM, "attribute_table_reloads", "number of times hosts attribute table was reloaded" },
-    { CountType::SUM, "attribute_table_hosts", "number of hosts added to the attribute table" },
-    { CountType::SUM, "attribute_table_overflow", "number of host additions that failed due to attribute table full" },
     { CountType::END, nullptr, nullptr }
 };
 
@@ -241,7 +239,6 @@ void DropStats()
 
     LogLabel("Summary Statistics");
     show_stats((PegCount*)&proc_stats, proc_names, array_size(proc_names)-1, "process");
-
 }
 
 //-------------------------------------------------------------------------
index a541fd70a2f7701c77770f1df3680eda011d7806..2c492989d91622671f06e36445c50d741344154e 100644 (file)
@@ -81,8 +81,6 @@ struct ProcessCount
     PegCount inspector_deletions;
     PegCount daq_reloads;
     PegCount attribute_table_reloads;
-    PegCount attribute_table_hosts;
-    PegCount attribute_table_overflow;
 };
 
 extern ProcessCount proc_stats;