From: Michael Altizer (mialtize) Date: Thu, 23 Apr 2020 15:13:12 +0000 (+0000) Subject: Merge pull request #2140 in SNORT/snort3 from ~DAVMCPHE/snort3:reload_attribute_table... X-Git-Tag: 3.0.1-2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5362673bc678e75f173685b9a0be28d220d44bab;p=thirdparty%2Fsnort3.git Merge pull request #2140 in SNORT/snort3 from ~DAVMCPHE/snort3:reload_attribute_table to master Squashed commit of the following: commit ffb923e26e17961fac352b54357f9fd2707e0b73 Author: davis mcpherson Date: Wed Apr 8 11:11:59 2020 -0400 target_based: refactor to load host attribute table from file target_based: refactor host attribute table logic into a c++ class, eliminate dead code target_based: refactor to improve design of the host attribute classes --- diff --git a/src/main.cc b/src/main.cc index ef7309f36..566f32314 100644 --- a/src/main.cc +++ b/src/main.cc @@ -49,7 +49,7 @@ #include "packet_io/sfdaq_config.h" #include "packet_io/sfdaq_instance.h" #include "packet_io/trough.h" -#include "target_based/sftarget_reader.h" +#include "target_based/host_attributes.h" #include "time/periodic.h" #include "utils/util.h" #include "utils/safec.h" @@ -169,7 +169,7 @@ void Pig::start() assert(!athread); LogMessage("++ [%u] %s\n", idx, analyzer->get_source()); - Swapper* ps = new Swapper(SnortConfig::get_conf(), SFAT_GetConfig()); + Swapper* ps = new Swapper(SnortConfig::get_conf(), HostAttributes::get_host_attributes_table()); athread = new std::thread(std::ref(*analyzer), ps, ++run_num); } @@ -365,16 +365,12 @@ int main_reload_config(lua_State* L) return 0; } - tTargetBasedConfig* old_tc = SFAT_GetConfig(); - tTargetBasedConfig* tc = SFAT_Swap(); + if ( !sc->attribute_hosts_file.empty() ) + HostAttributes::load_hosts_file(sc, sc->attribute_hosts_file.c_str()); + + HostAttributesTable* old_tc = HostAttributes::get_host_attributes_table(); + HostAttributesTable* tc = HostAttributes::activate(); - if ( !tc ) - { - // FIXIT-L it does not seem a valid check, delete old config if come to it - current_request->respond("== reload failed - bad config\n"); - SnortConfig::set_parser_conf(nullptr); - return 0; - } PluginManager::reload_so_plugins_cleanup(sc); SnortConfig::set_conf(sc); proc_stats.conf_reloads++; @@ -497,11 +493,11 @@ int main_reload_hosts(lua_State* L) return 0; } - Shell sh = Shell(fname); - sh.configure(SnortConfig::get_conf(), false, true); + proc_stats.attribute_table_overflow = 0; + HostAttributes::load_hosts_file(SnortConfig::get_conf(), fname); - tTargetBasedConfig* old = SFAT_GetConfig(); - tTargetBasedConfig* tc = SFAT_Swap(); + HostAttributesTable* old = HostAttributes::get_host_attributes_table(); + HostAttributesTable* tc = HostAttributes::activate(); if ( !tc ) { @@ -509,6 +505,9 @@ int main_reload_hosts(lua_State* L) return 0; } + proc_stats.attribute_table_reloads++; + LogMessage(STDu64 " hosts loaded\n", proc_stats.attribute_table_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); diff --git a/src/main/modules.cc b/src/main/modules.cc index 81861f332..bae2a1b5c 100644 --- a/src/main/modules.cc +++ b/src/main/modules.cc @@ -56,7 +56,7 @@ #include "side_channel/side_channel_module.h" #include "sfip/sf_ipvar.h" #include "stream/stream.h" -#include "target_based/sftarget_data.h" +#include "target_based/host_attributes.h" #include "target_based/snort_protocols.h" #include "trace/trace_module.h" @@ -944,6 +944,9 @@ bool PacketsModule::set(const char*, Value& v, SnortConfig* sc) static const Parameter attribute_table_params[] = { + { "hosts_file", Parameter::PT_STRING, nullptr, nullptr, + "filename to load attribute host table from" }, + { "max_hosts", Parameter::PT_INT, "32:max53", "1024", "maximum number of hosts in attribute table" }, @@ -972,7 +975,10 @@ public: bool AttributeTableModule::set(const char*, Value& v, SnortConfig* sc) { - if ( v.is("max_hosts") ) + if ( v.is("hosts_file") ) + sc->attribute_hosts_file = std::string(v.get_string()); + + else if ( v.is("max_hosts") ) sc->max_attribute_hosts = v.get_uint32(); else if ( v.is("max_services_per_host") ) @@ -1909,24 +1915,24 @@ 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 = SFAT_CreateApplicationEntry(); - + app = new ApplicationEntry; else if ( idx && !strcmp(fqn, "hosts") ) - host = SFAT_CreateHostEntry(); + host = new HostAttributeEntry; return true; } -bool HostsModule::end(const char* fqn, int idx, SnortConfig*) +bool HostsModule::end(const char* fqn, int idx, SnortConfig* sc) { if ( idx && !strcmp(fqn, "hosts.services") ) { - SFAT_AddService(host, app); + host->add_service(app); app = nullptr; } else if ( idx && !strcmp(fqn, "hosts") ) { - SFAT_AddHost(host); + if ( !HostAttributes::add_host(host, sc) ) + delete host; host = nullptr; } diff --git a/src/main/snort.cc b/src/main/snort.cc index 184713ad8..b26265a45 100644 --- a/src/main/snort.cc +++ b/src/main/snort.cc @@ -65,7 +65,7 @@ #include "service_inspectors/service_inspectors.h" #include "side_channel/side_channel.h" #include "stream/stream_inspectors.h" -#include "target_based/sftarget_reader.h" +#include "target_based/host_attributes.h" #include "time/periodic.h" #include "trace/trace_log_api.h" #include "utils/util.h" @@ -107,7 +107,6 @@ void Snort::init(int argc, char** argv) #endif InitProtoNames(); - SFAT_Init(); load_actions(); load_codecs(); @@ -180,6 +179,9 @@ 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()); + // Must be after CodecManager::instantiate() if ( !InspectorManager::configure(sc) ) ParseError("can't initialize inspectors"); @@ -209,7 +211,7 @@ 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); - SFAT_Start(); + HostAttributes::activate(); #ifdef PIGLET if ( !Piglet::piglet_mode() ) @@ -310,7 +312,7 @@ void Snort::term() term_signals(); IpsManager::global_term(SnortConfig::get_conf()); - SFAT_Cleanup(); + HostAttributes::cleanup(); #ifdef PIGLET if ( !Piglet::piglet_mode() ) diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index c3edd8c74..7e3bb90fd 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -57,7 +57,7 @@ #include "profiler/profiler.h" #include "protocols/packet.h" #include "sfip/sf_ip.h" -#include "target_based/sftarget_reader.h" +#include "target_based/host_attributes.h" #include "target_based/snort_protocols.h" #include "trace/trace_config.h" #include "utils/dnet_header.h" diff --git a/src/main/snort_config.h b/src/main/snort_config.h index b52c15b52..a6abd4dc8 100644 --- a/src/main/snort_config.h +++ b/src/main/snort_config.h @@ -157,7 +157,6 @@ class GHash; class ProtocolReference; class XHash; struct ProfilerConfig; -struct SnortConfig; class ReloadResourceTuner { @@ -297,6 +296,7 @@ public: //------------------------------------------------------ // attribute tables stuff + std::string attribute_hosts_file; uint32_t max_attribute_hosts = 0; uint32_t max_attribute_services_per_host = 0; uint32_t max_metadata_services = 0; diff --git a/src/main/swapper.cc b/src/main/swapper.cc index 6fa90f3f3..0bd66a70e 100644 --- a/src/main/swapper.cc +++ b/src/main/swapper.cc @@ -23,7 +23,7 @@ #include "swapper.h" -#include "target_based/sftarget_reader.h" +#include "target_based/host_attributes.h" #include "analyzer.h" #include "snort.h" @@ -33,7 +33,7 @@ using namespace snort; bool Swapper::reload_in_progress = false; -Swapper::Swapper(SnortConfig* s, tTargetBasedConfig* t) +Swapper::Swapper(SnortConfig* s, HostAttributesTable* t) { old_conf = nullptr; new_conf = s; @@ -51,7 +51,7 @@ Swapper::Swapper(SnortConfig* sold, SnortConfig* snew) new_attribs = nullptr; } -Swapper::Swapper(SnortConfig* sold, SnortConfig* snew, tTargetBasedConfig* told, tTargetBasedConfig* tnew) +Swapper::Swapper(SnortConfig* sold, SnortConfig* snew, HostAttributesTable* told, HostAttributesTable* tnew) { old_conf = sold; new_conf = snew; @@ -60,7 +60,7 @@ Swapper::Swapper(SnortConfig* sold, SnortConfig* snew, tTargetBasedConfig* told, new_attribs = tnew; } -Swapper::Swapper(tTargetBasedConfig* told, tTargetBasedConfig* tnew) +Swapper::Swapper(HostAttributesTable* told, HostAttributesTable* tnew) { old_conf = nullptr; new_conf = nullptr; @@ -75,7 +75,7 @@ Swapper::~Swapper() delete old_conf; if ( old_attribs ) - SFAT_Free(old_attribs); + delete old_attribs; } void Swapper::apply(Analyzer& analyzer) @@ -85,10 +85,10 @@ void Swapper::apply(Analyzer& analyzer) const bool reload = (SnortConfig::get_conf() != nullptr); SnortConfig::set_conf(new_conf); // FIXIT-M Determine whether we really want to do this before or after the set_conf - if (reload) + if ( reload ) analyzer.reinit(new_conf); } if ( new_attribs ) - SFAT_SetConfig(new_attribs); + HostAttributes::set_host_attributes_table(new_attribs); } diff --git a/src/main/swapper.h b/src/main/swapper.h index 3a3a0879d..a91d98fa2 100644 --- a/src/main/swapper.h +++ b/src/main/swapper.h @@ -28,15 +28,15 @@ struct SnortConfig; } class Analyzer; -struct tTargetBasedConfig; +struct HostAttributesTable; class Swapper { public: - Swapper(snort::SnortConfig*, tTargetBasedConfig*); + Swapper(snort::SnortConfig*, HostAttributesTable*); Swapper(snort::SnortConfig*, snort::SnortConfig*); - Swapper(snort::SnortConfig*, snort::SnortConfig*, tTargetBasedConfig*, tTargetBasedConfig*); - Swapper(tTargetBasedConfig*, tTargetBasedConfig*); + Swapper(snort::SnortConfig*, snort::SnortConfig*, HostAttributesTable*, HostAttributesTable*); + Swapper(HostAttributesTable*, HostAttributesTable*); ~Swapper(); void apply(Analyzer&); @@ -49,8 +49,8 @@ private: snort::SnortConfig* old_conf; snort::SnortConfig* new_conf; - tTargetBasedConfig* old_attribs; - tTargetBasedConfig* new_attribs; + HostAttributesTable* old_attribs; + HostAttributesTable* new_attribs; static bool reload_in_progress; }; diff --git a/src/network_inspectors/binder/binder.cc b/src/network_inspectors/binder/binder.cc index 3e0348cf7..e4636621e 100644 --- a/src/network_inspectors/binder/binder.cc +++ b/src/network_inspectors/binder/binder.cc @@ -35,7 +35,7 @@ #include "pub_sub/assistant_gadget_event.h" #include "stream/stream.h" #include "stream/stream_splitter.h" -#include "target_based/sftarget_reader.h" +#include "target_based/host_attributes.h" #include "target_based/snort_protocols.h" #include "bind_module.h" @@ -994,7 +994,7 @@ void Binder::apply(Flow* flow, Stuff& stuff) if ( !stuff.apply_action(flow) ) return; - const HostAttributeEntry* host = SFAT_LookupHostEntryByIP(&flow->server_ip); + const HostAttributeEntry* host = HostAttributes::find_host(&flow->server_ip); // setup session stuff.apply_session(flow, host); diff --git a/src/stream/stream.cc b/src/stream/stream.cc index c3ef74196..d8c131715 100644 --- a/src/stream/stream.cc +++ b/src/stream/stream.cc @@ -35,7 +35,7 @@ #include "packet_io/active.h" #include "protocols/vlan.h" #include "stream/base/stream_module.h" -#include "target_based/sftarget_hostentry.h" +#include "target_based/host_attributes.h" #include "target_based/snort_protocols.h" #include "utils/util.h" @@ -391,9 +391,8 @@ void Stream::set_snort_protocol_id( set_ip_protocol(flow); } - snort_protocol_id = get_snort_protocol_id_from_host_table( - host_entry, flow->ssn_state.ipprotocol, - flow->server_port, SFAT_SERVICE); + snort_protocol_id = host_entry->get_snort_protocol_id + (flow->ssn_state.ipprotocol, flow->server_port); #if 0 // FIXIT-M from client doesn't imply need to swap @@ -428,7 +427,7 @@ SnortProtocolId Stream::get_snort_protocol_id(Flow* flow) set_ip_protocol(flow); } - if ( HostAttributeEntry* host_entry = SFAT_LookupHostEntryByIP(&flow->server_ip) ) + if ( HostAttributeEntry* host_entry = HostAttributes::find_host(&flow->server_ip) ) { set_snort_protocol_id(flow, host_entry, FROM_SERVER); @@ -436,7 +435,7 @@ SnortProtocolId Stream::get_snort_protocol_id(Flow* flow) return flow->ssn_state.snort_protocol_id; } - if ( HostAttributeEntry* host_entry = SFAT_LookupHostEntryByIP(&flow->client_ip) ) + if ( HostAttributeEntry* host_entry = HostAttributes::find_host(&flow->client_ip) ) { set_snort_protocol_id(flow, host_entry, FROM_CLIENT); @@ -460,9 +459,8 @@ SnortProtocolId Stream::set_snort_protocol_id(Flow* flow, SnortProtocolId id) if ( !flow->is_proxied() ) { - SFAT_UpdateApplicationProtocol( - &flow->server_ip, flow->server_port, - flow->ssn_state.ipprotocol, id); + HostAttributes::update_service + (&flow->server_ip, flow->server_port, flow->ssn_state.ipprotocol, id); } return id; } diff --git a/src/stream/test/stream_splitter_test.cc b/src/stream/test/stream_splitter_test.cc index 55e991711..2937936f9 100644 --- a/src/stream/test/stream_splitter_test.cc +++ b/src/stream/test/stream_splitter_test.cc @@ -65,11 +65,9 @@ void Stream::flush_server(Packet*) { flushed = 2; } } - uint16_t FlushBucket::get_size() { return 1; } - //-------------------------------------------------------------------------- // atom splitter tests //-------------------------------------------------------------------------- diff --git a/src/target_based/CMakeLists.txt b/src/target_based/CMakeLists.txt index 6c5617c7b..f38dd713d 100644 --- a/src/target_based/CMakeLists.txt +++ b/src/target_based/CMakeLists.txt @@ -1,10 +1,7 @@ add_library( target_based OBJECT - sftarget_reader.cc - sftarget_reader.h - sftarget_hostentry.cc - sftarget_hostentry.h - sftarget_data.h + host_attributes.cc + host_attributes.h snort_protocols.cc ) diff --git a/src/target_based/host_attributes.cc b/src/target_based/host_attributes.cc new file mode 100644 index 000000000..9cc37a7b8 --- /dev/null +++ b/src/target_based/host_attributes.cc @@ -0,0 +1,215 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved. +// Copyright (C) 2006-2013 Sourcefire, Inc. +// +// 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. +//-------------------------------------------------------------------------- + +// host_attributes.cc Author: davis mcpherson + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "host_attributes.h" + +#include "log/messages.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" + +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) +{ + // 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() +{ + sfrt_cleanup(host_table, HostAttributesTable::free_host_entry); + sfrt_free(host_table); +} + +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); + + if ( ret == RT_SUCCESS ) + { + ++num_hosts; + return true; + } + + if ( ret == RT_POLICY_TABLE_EXCEEDED ) + { + if ( !sfat_insufficient_space_logged ) + { + 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; + } + + proc_stats.attribute_table_overflow++; + } + else if ( !sfat_grammar_error_printed ) + { + ParseWarning(WARN_HOSTS, "Attribute table insertion failed: %d '%s'\n", + ret, rt_error_messages[ret]); + sfat_grammar_error_printed = true; + } + + return false; +} + +HostAttributeEntry* HostAttributesTable::get_host(SfIp* ipAddr) +{ + HostAttributeEntry* host = (HostAttributeEntry*)sfrt_lookup(ipAddr, host_table); + if ( !host && !is_host_attribute_table_full() ) + { + host = new HostAttributeEntry; + host->ipAddr.set(*ipAddr); + if ( !curr_cfg->add_host(host) ) + { + delete host; + host = nullptr; + } + } + + return host; +} + +HostAttributeEntry* HostAttributesTable::find_host(const SfIp* ipAddr) +{ return (HostAttributeEntry*)sfrt_lookup(ipAddr, host_table); } + +HostAttributeEntry::~HostAttributeEntry() +{ + for ( auto app : services ) + delete app; +} + +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) +{ + 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++; + } + + // application service not found, add it + if ( service_count >= SnortConfig::get_max_services_per_host() ) + return; + + ApplicationEntry* app = new ApplicationEntry(port, protocol, snort_protocol_id); + host->add_service(app); +} +SnortProtocolId HostAttributeEntry::get_snort_protocol_id(int ipprotocol, uint16_t port) const +{ + for ( auto app : services ) + { + if ( (app->ipproto == ipprotocol) && (app->port == port) ) + return app->snort_protocol_id; + } + + return 0; +} + +void HostAttributes::load_hosts_file(SnortConfig* sc, const char* fname) +{ + delete next_cfg; + next_cfg = new HostAttributesTable(sc->max_attribute_hosts); + + Shell sh = Shell(fname); + if ( !sh.configure(sc, false, true) ) + { + delete next_cfg; + next_cfg = nullptr; + } +} + +HostAttributesTable* HostAttributes::activate() +{ + curr_cfg = next_cfg; + next_cfg = nullptr; + + if ( curr_cfg ) + proc_stats.attribute_table_hosts = curr_cfg->get_num_hosts(); + else + proc_stats.attribute_table_hosts = 0; + + return curr_cfg; +} + +void HostAttributes::set_host_attributes_table(HostAttributesTable* p) +{ curr_cfg = p; } + +HostAttributesTable* HostAttributes::get_host_attributes_table() +{ return curr_cfg; } + +bool HostAttributes::add_host(HostAttributeEntry* host, snort::SnortConfig* sc) +{ + if ( !next_cfg ) + next_cfg = new HostAttributesTable(sc->max_attribute_hosts); + + return next_cfg->add_host(host); +} + +HostAttributeEntry* HostAttributes::find_host(const SfIp* ipAddr) +{ + if ( !curr_cfg ) + return nullptr; + + return curr_cfg->find_host(ipAddr); +} + +void HostAttributes::update_service(SfIp* ipAddr, uint16_t port, uint16_t protocol, SnortProtocolId snort_protocol_id) +{ + if ( curr_cfg ) + { + HostAttributeEntry* host = curr_cfg->get_host(ipAddr); + if ( host ) + host->update_service(host, port, protocol, snort_protocol_id); + } +} + +void HostAttributes::cleanup() +{ delete curr_cfg; } diff --git a/src/target_based/host_attributes.h b/src/target_based/host_attributes.h new file mode 100644 index 000000000..7cea901a4 --- /dev/null +++ b/src/target_based/host_attributes.h @@ -0,0 +1,118 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved. +// Copyright (C) 2006-2013 Sourcefire, Inc. +// +// 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. +//-------------------------------------------------------------------------- + +// host_attributes.h author davis mcpherson + +#ifndef HOST_ATTRIBUTES_H +#define HOST_ATTRIBUTES_H + +// Provides attribute table initialization, lookup, swap, and releasing. + +#include + +#include "sfip/sf_cidr.h" +#include "sfrt/sfrt.h" +#include "target_based/snort_protocols.h" + +struct ApplicationEntry +{ + ApplicationEntry() = default; + ApplicationEntry(uint16_t port, uint16_t protocol, SnortProtocolId spi) + : port(port), ipproto(protocol), snort_protocol_id(spi) + { } + ~ApplicationEntry() = default; + + uint16_t port = 0; + uint16_t ipproto = 0; + SnortProtocolId snort_protocol_id = 0; +}; + +struct HostInfo +{ + uint8_t streamPolicy = 0; + uint8_t fragPolicy = 0; +}; + +struct HostAttributeEntry +{ + HostAttributeEntry() = default; + ~HostAttributeEntry(); + + void add_service(ApplicationEntry*); + void update_service(HostAttributeEntry*, uint16_t port, uint16_t protocol, SnortProtocolId); + SnortProtocolId get_snort_protocol_id(int ipprotocol, uint16_t port) const; + + snort::SfCidr ipAddr; + HostInfo hostInfo; + std::vector services; +}; + +#define DEFAULT_MAX_ATTRIBUTE_HOSTS 10000 +#define DEFAULT_MAX_ATTRIBUTE_SERVICES_PER_HOST 100 +#define DEFAULT_MAX_METADATA_SERVICES 9 + +namespace snort +{ +struct SfIp; +struct SnortConfig; +} + +struct HostAttributesTable +{ + HostAttributesTable(uint32_t max_hosts); + ~HostAttributesTable(); + + bool add_host(HostAttributeEntry*); + HostAttributeEntry* get_host(snort::SfIp*); + HostAttributeEntry* find_host(const snort::SfIp*); + void add_service(HostAttributeEntry*, ApplicationEntry*); + + bool is_host_attribute_table_full() + { return num_hosts >= max_hosts; } + + uint32_t get_num_hosts () const + { return num_hosts; } + +private: + table_t* host_table; + uint32_t max_hosts; + uint32_t num_hosts = 0; + + bool sfat_grammar_error_printed = false; + bool sfat_insufficient_space_logged = false; + + static void free_host_entry(void* host); +}; + +class HostAttributes +{ +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(); +}; + + +#endif + diff --git a/src/target_based/sftarget_data.h b/src/target_based/sftarget_data.h deleted file mode 100644 index 025770809..000000000 --- a/src/target_based/sftarget_data.h +++ /dev/null @@ -1,86 +0,0 @@ -//-------------------------------------------------------------------------- -// Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved. -// Copyright (C) 2006-2013 Sourcefire, Inc. -// -// 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. -//-------------------------------------------------------------------------- - -// sftarget_data.c author Steven Sturges - -#ifndef SFTARGET_DATA_H -#define SFTARGET_DATA_H - -#include "sfip/sf_cidr.h" -#include "target_based/snort_protocols.h" - -#define SFAT_OK 0 -#define SFAT_ERROR (-1) -#define SFAT_BUFSZ 1024 - -enum ServiceClient -{ - ATTRIBUTE_SERVICE, - ATTRIBUTE_CLIENT -}; - -#define APPLICATION_ENTRY_PORT 0x01 -#define APPLICATION_ENTRY_IPPROTO 0x02 -#define APPLICATION_ENTRY_PROTO 0x04 -#define APPLICATION_ENTRY_APPLICATION 0x08 -#define APPLICATION_ENTRY_VERSION 0x10 - -struct ApplicationEntry -{ - ApplicationEntry* next; - - uint16_t port; - uint16_t ipproto; - SnortProtocolId snort_protocol_id; - - uint8_t fields; -}; - -#define HOST_INFO_OS 1 -#define HOST_INFO_VENDOR 2 -#define HOST_INFO_VERSION 3 -#define HOST_INFO_FRAG_POLICY 4 -#define HOST_INFO_STREAM_POLICY 5 - -struct HostInfo -{ - uint8_t streamPolicy; - uint8_t fragPolicy; -}; - -#define SFAT_SERVICE 1 -#define SFAT_CLIENT 2 - -struct HostAttributeEntry -{ - snort::SfCidr ipAddr; - HostInfo hostInfo; - ApplicationEntry* services; - ApplicationEntry* clients; -}; - -int SFAT_AddHost(HostAttributeEntry*); -int SFAT_AddService(HostAttributeEntry*, ApplicationEntry*); -int SFAT_AddHostEntryToMap(HostAttributeEntry*); - -HostAttributeEntry* SFAT_CreateHostEntry(); -ApplicationEntry* SFAT_CreateApplicationEntry(); - -#endif - diff --git a/src/target_based/sftarget_hostentry.cc b/src/target_based/sftarget_hostentry.cc deleted file mode 100644 index 3fbb7ca01..000000000 --- a/src/target_based/sftarget_hostentry.cc +++ /dev/null @@ -1,132 +0,0 @@ -//-------------------------------------------------------------------------- -// Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved. -// Copyright (C) 2006-2013 Sourcefire, Inc. -// -// 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. -//-------------------------------------------------------------------------- - -// sftarget_hostentry.c author Steven Sturges - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "sftarget_hostentry.h" - -#if 0 -static bool hasService(const HostAttributeEntry* host_entry, - int ipprotocol, int protocol, int application) -{ - ApplicationEntry* service; - - if (!host_entry) - return false; - - for (service = host_entry->services; service; service = service->next) - { - if (ipprotocol && (service->ipproto == ipprotocol)) - { - if (protocol && (service->protocol == protocol)) - { - if (!application) - { - /* match of ipproto, proto. application not specified */ - return true; - } - } - else if (!protocol) - { - /* match of ipproto. protocol not specified */ - return true; - } - } - /* No ipprotocol specified, huh? */ - } - - return false; -} - -static bool hasClient(const HostAttributeEntry* host_entry, - int ipprotocol, int protocol, int application) -{ - ApplicationEntry* client; - - if (!host_entry) - return false; - - for (client = host_entry->clients; client; client = client->next) - { - if (ipprotocol && (client->ipproto == ipprotocol)) - { - if (protocol && (client->protocol == protocol)) - { - if (!application) - { - /* match of ipproto, proto. application not specified */ - return true; - } - } - else if (!protocol) - { - /* match of ipproto. protocol not specified */ - return true; - } - } - /* No ipprotocol specified, huh? */ - } - - return false; -} - -bool hasProtocol(const HostAttributeEntry* host_entry, - int ipprotocol, int protocol, int application) -{ - if ( hasService(host_entry, ipprotocol, protocol, application) ) - return true; - - if ( hasClient(host_entry, ipprotocol, protocol, application) ) - return true; - - return false; -} -#endif - -SnortProtocolId get_snort_protocol_id_from_host_table(const HostAttributeEntry* host_entry, - int ipprotocol, - uint16_t port, - char direction) -{ - ApplicationEntry* application; - - if (!host_entry) - return 0; - - if (direction == SFAT_SERVICE) - { - for (application = host_entry->services; application; application = application->next) - { - if (application->ipproto == ipprotocol) - { - if ((uint16_t)application->port == port) - { - return application->snort_protocol_id; - } - } - } - } - - return 0; -} - diff --git a/src/target_based/sftarget_hostentry.h b/src/target_based/sftarget_hostentry.h deleted file mode 100644 index 01cbd7f66..000000000 --- a/src/target_based/sftarget_hostentry.h +++ /dev/null @@ -1,37 +0,0 @@ -//-------------------------------------------------------------------------- -// Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved. -// Copyright (C) 2006-2013 Sourcefire, Inc. -// -// 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. -//-------------------------------------------------------------------------- - -// sftarget_hostentry.h author Steven Sturges - -#ifndef SFTARGET_HOSTENTRY_H -#define SFTARGET_HOSTENTRY_H - -#include "target_based/sftarget_reader.h" - -/* API for HostAttributeEntry 'class' */ - -#if 0 -bool hasProtocol(const HostAttributeEntry*, int ipprotocol, int protocol, int application); -#endif - -SnortProtocolId get_snort_protocol_id_from_host_table( - const HostAttributeEntry*, int ipprotocol, uint16_t port, char direction); - -#endif - diff --git a/src/target_based/sftarget_reader.cc b/src/target_based/sftarget_reader.cc deleted file mode 100644 index eacd039af..000000000 --- a/src/target_based/sftarget_reader.cc +++ /dev/null @@ -1,351 +0,0 @@ -//-------------------------------------------------------------------------- -// Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved. -// Copyright (C) 2006-2013 Sourcefire, Inc. -// -// 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. -//-------------------------------------------------------------------------- - -/* - * Author: Steven Sturges - * sftarget_reader.c - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "sftarget_reader.h" - -#include "log/messages.h" -#include "main/snort_config.h" -#include "protocols/packet.h" -#include "sfrt/sfrt.h" -#include "utils/stats.h" -#include "utils/util.h" - -using namespace snort; - -#define ATTRIBUTE_MAP_MAX_ROWS 1024 - -struct tTargetBasedConfig -{ - table_t* lookupTable; - - tTargetBasedConfig(); - ~tTargetBasedConfig(); -}; - -static void SFAT_CleanupCallback(void* host_attr_ent) -{ - HostAttributeEntry* host_entry = (HostAttributeEntry*)host_attr_ent; - FreeHostEntry(host_entry); -} - -tTargetBasedConfig::tTargetBasedConfig() -{ - /* 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 - // FIXIT-M init before snort_conf; move to filename and load separately - // this is a hack to get it going - uint32_t max = SnortConfig::get_conf() ? - SnortConfig::get_max_attribute_hosts() : DEFAULT_MAX_ATTRIBUTE_HOSTS; - lookupTable = sfrt_new(DIR_8x16, IPv6, max + 1, (max>>6) + 1); -} - -tTargetBasedConfig::~tTargetBasedConfig() -{ - sfrt_cleanup(lookupTable, SFAT_CleanupCallback); - sfrt_free(lookupTable); -} - -static THREAD_LOCAL tTargetBasedConfig* curr_cfg = nullptr; -static tTargetBasedConfig* next_cfg = nullptr; - -static bool sfat_grammar_error_printed = false; -static bool sfat_insufficient_space_logged = false; - -/*****TODO: cleanup to use config directive *******/ -uint32_t SFAT_NumberOfHosts() -{ - if ( curr_cfg && curr_cfg->lookupTable ) - { - return sfrt_num_entries(curr_cfg->lookupTable); - } - - return 0; -} - -static void FreeApplicationEntry(ApplicationEntry* app) -{ - snort_free(app); -} - -ApplicationEntry* SFAT_CreateApplicationEntry() -{ - return (ApplicationEntry*)snort_calloc(sizeof(ApplicationEntry)); -} - -HostAttributeEntry* SFAT_CreateHostEntry() -{ - return (HostAttributeEntry*)snort_calloc(sizeof(HostAttributeEntry)); -} - -void FreeHostEntry(HostAttributeEntry* host) -{ - ApplicationEntry* app = nullptr, * tmp_app; - - if (!host) - return; - - - /* Free the service list */ - if (host->services) - { - do - { - tmp_app = host->services; - app = tmp_app->next; - FreeApplicationEntry(tmp_app); - host->services = app; - } - while (app); - } - - /* Free the client list */ - if (host->clients) - { - do - { - tmp_app = host->clients; - app = tmp_app->next; - FreeApplicationEntry(tmp_app); - host->clients = app; - } - while (app); - } - - snort_free(host); -} - -static void AppendApplicationData(ApplicationEntry** list, ApplicationEntry* app) -{ - if (!list) - return; - - if (*list) - { - app->next = *list; - } - *list = app; -} - -int SFAT_AddService(HostAttributeEntry* host, ApplicationEntry* app) -{ - AppendApplicationData(&host->services, app); - return SFAT_OK; -} - -#if 0 -int SFAT_AddApplicationData(HostAttributeEntry* host, ApplicationEntry* app) -{ - uint8_t required_fields = - (APPLICATION_ENTRY_PORT | - APPLICATION_ENTRY_IPPROTO | - APPLICATION_ENTRY_PROTO); - - if ((app->fields & required_fields) != required_fields) - { - ParseError("Missing required field in Service attribute table for host %s", - host->ipAddr.ntoa()); - } - AppendApplicationData(&host->services, app); - - return SFAT_OK; -} - -#endif - - -int SFAT_AddHost(HostAttributeEntry* host) -{ - return SFAT_AddHostEntryToMap(host); -} - -int SFAT_AddHostEntryToMap(HostAttributeEntry* host) -{ - int ret; - SfCidr* ipAddr; - - ipAddr = &host->ipAddr; - assert(ipAddr); - - ret = sfrt_insert(ipAddr, (unsigned char)ipAddr->get_bits(), host, - RT_FAVOR_SPECIFIC, next_cfg->lookupTable); - - if (ret != RT_SUCCESS) - { - if (ret == RT_POLICY_TABLE_EXCEEDED) - { - if ( !sfat_insufficient_space_logged ) - { - ParseWarning(WARN_HOSTS, - "AttributeTable insertion failed: %d Insufficient " - "space in attribute table, only configured to store %u hosts\n", - ret, SnortConfig::get_max_attribute_hosts()); - sfat_insufficient_space_logged = true; - } - /* Reset return value and continue w/ only SnortConfig::get_conf()->max_attribute_hosts */ - ret = RT_SUCCESS; - } - else if ( !sfat_grammar_error_printed ) - { - ParseWarning(WARN_HOSTS, - "AttributeTable insertion failed: %d '%s'\n", - ret, rt_error_messages[ret]); - sfat_grammar_error_printed = true; - } - - FreeHostEntry(host); - } - - return ret == RT_SUCCESS ? SFAT_OK : SFAT_ERROR; -} - -HostAttributeEntry* SFAT_LookupHostEntryByIP(const SfIp* ipAddr) -{ - if ( !curr_cfg ) - return nullptr; - - return (HostAttributeEntry*)sfrt_lookup((const SfIp*)ipAddr, curr_cfg->lookupTable); -} - -HostAttributeEntry* SFAT_LookupHostEntryBySrc(Packet* p) -{ - if (!p || !p->ptrs.ip_api.is_ip()) - return nullptr; - - return SFAT_LookupHostEntryByIP(p->ptrs.ip_api.get_src()); -} - -HostAttributeEntry* SFAT_LookupHostEntryByDst(Packet* p) -{ - if (!p || !p->ptrs.ip_api.is_ip()) - return nullptr; - - return SFAT_LookupHostEntryByIP(p->ptrs.ip_api.get_dst()); -} - -void SFAT_Cleanup() -{ - delete curr_cfg; - delete next_cfg; -} - -void SFAT_SetConfig(tTargetBasedConfig* p) -{ - curr_cfg = p; -} - -tTargetBasedConfig* SFAT_GetConfig() -{ - return curr_cfg; -} - -void SFAT_Free(tTargetBasedConfig* p) -{ - delete p; -} - -void SFAT_Init() -{ - curr_cfg = nullptr; - next_cfg = new tTargetBasedConfig; -} - -void SFAT_Start() -{ - curr_cfg = next_cfg; - next_cfg = new tTargetBasedConfig; - proc_stats.attribute_table_hosts = SFAT_NumberOfHosts(); -} - -tTargetBasedConfig* SFAT_Swap() -{ - curr_cfg = next_cfg; - next_cfg = new tTargetBasedConfig; - - proc_stats.attribute_table_hosts = SFAT_NumberOfHosts(); - proc_stats.attribute_table_reloads++; - - LogMessage(STDu64 " hosts loaded\n", proc_stats.attribute_table_hosts); - return curr_cfg; -} - -void SFAT_UpdateApplicationProtocol(SfIp* ipAddr, uint16_t port, uint16_t protocol, SnortProtocolId snort_protocol_id) -{ - HostAttributeEntry* host_entry; - ApplicationEntry* service; - unsigned service_count = 0; - - host_entry = (HostAttributeEntry*)sfrt_lookup(ipAddr, curr_cfg->lookupTable); - - if (!host_entry) - { - if (sfrt_num_entries(curr_cfg->lookupTable) >= SnortConfig::get_max_attribute_hosts()) - return; - - host_entry = (HostAttributeEntry*)snort_calloc(sizeof(*host_entry)); - host_entry->ipAddr.set(*ipAddr); - - int rval = sfrt_insert(&host_entry->ipAddr, (unsigned char)host_entry->ipAddr.get_bits(), - host_entry, RT_FAVOR_SPECIFIC, curr_cfg->lookupTable); - - if ( rval != RT_SUCCESS) - { - FreeHostEntry(host_entry); - return; - } - service = nullptr; - } - else - { - for (service = host_entry->services; service; service = service->next) - { - if (service->ipproto == protocol && (uint16_t)service->port == port) - { - break; - } - service_count++; - } - } - if (!service) - { - if ( service_count >= SnortConfig::get_max_services_per_host() ) - return; - - service = (ApplicationEntry*)snort_calloc(sizeof(*service)); - service->port = port; - service->ipproto = protocol; - service->next = host_entry->services; - host_entry->services = service; - service->snort_protocol_id = snort_protocol_id; - } - else if (service->snort_protocol_id != snort_protocol_id) - { - service->snort_protocol_id = snort_protocol_id; - } -} - diff --git a/src/target_based/sftarget_reader.h b/src/target_based/sftarget_reader.h deleted file mode 100644 index c8b00598c..000000000 --- a/src/target_based/sftarget_reader.h +++ /dev/null @@ -1,72 +0,0 @@ -//-------------------------------------------------------------------------- -// Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved. -// Copyright (C) 2006-2013 Sourcefire, Inc. -// -// 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. -//-------------------------------------------------------------------------- - -// sftarget_reader.h author Steven Sturges - -#ifndef SFTARGET_READER_H -#define SFTARGET_READER_H - -// Provides attribute table initialization, lookup, swap, and releasing. - -#include "target_based/sftarget_data.h" - -#define DEFAULT_MAX_ATTRIBUTE_HOSTS 10000 -#define DEFAULT_MAX_ATTRIBUTE_SERVICES_PER_HOST 100 -#define DEFAULT_MAX_METADATA_SERVICES 9 - -#define MAX_MAX_ATTRIBUTE_HOSTS (512 * 1024) -#define MIN_MAX_ATTRIBUTE_HOSTS 32 -#define MAX_MAX_ATTRIBUTE_SERVICES_PER_HOST 65535 -#define MIN_MAX_ATTRIBUTE_SERVICES_PER_HOST 1 -#define MAX_MAX_METADATA_SERVICES 256 -#define MIN_MAX_METADATA_SERVICES 1 - -namespace snort -{ -struct Packet; -} - -/* main Functions, called by Snort shutdown */ -void SFAT_Init(); -void SFAT_Start(); -void SFAT_Cleanup(); -void FreeHostEntry(HostAttributeEntry* host); - -/* status functions */ -uint32_t SFAT_NumberOfHosts(); - -/* API Lookup functions, to be called by Stream & Frag */ -HostAttributeEntry* SFAT_LookupHostEntryByIP(const snort::SfIp* ipAddr); -HostAttributeEntry* SFAT_LookupHostEntryBySrc(snort::Packet* p); -HostAttributeEntry* SFAT_LookupHostEntryByDst(snort::Packet* p); - -#if 0 -int SFAT_AddApplicationData(HostAttributeEntry*, struct ApplicationEntry*); -#endif -void SFAT_UpdateApplicationProtocol(snort::SfIp*, uint16_t port, uint16_t protocol, uint16_t id); - -// reload functions -struct tTargetBasedConfig; -tTargetBasedConfig* SFAT_Swap(); -tTargetBasedConfig* SFAT_GetConfig(); -void SFAT_SetConfig(tTargetBasedConfig*); -void SFAT_Free(tTargetBasedConfig*); - -#endif - diff --git a/src/target_based/snort_protocols.cc b/src/target_based/snort_protocols.cc index c12a5fe49..ee9b061e5 100644 --- a/src/target_based/snort_protocols.cc +++ b/src/target_based/snort_protocols.cc @@ -32,8 +32,6 @@ #include "utils/util.h" #include "utils/util_cstring.h" -#include "sftarget_data.h" - using namespace snort; using namespace std; diff --git a/src/utils/stats.cc b/src/utils/stats.cc index c39c90e67..48a9ed2d1 100644 --- a/src/utils/stats.cc +++ b/src/utils/stats.cc @@ -213,8 +213,9 @@ const PegInfo proc_names[] = { CountType::SUM, "policy_reloads", "number of times policies were reloaded" }, { 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 table was reloaded" }, - { CountType::SUM, "attribute_table_hosts", "total number of hosts in table" }, + { 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 } }; diff --git a/src/utils/stats.h b/src/utils/stats.h index 29859e952..38a5b9eef 100644 --- a/src/utils/stats.h +++ b/src/utils/stats.h @@ -76,6 +76,7 @@ struct ProcessCount PegCount daq_reloads; PegCount attribute_table_reloads; PegCount attribute_table_hosts; + PegCount attribute_table_overflow; }; extern ProcessCount proc_stats;