add_subdirectory(ips_options)
add_subdirectory(loggers)
add_subdirectory(network_inspectors)
+add_subdirectory(policy_selectors)
add_subdirectory(search_engines)
add_subdirectory(side_channel)
add_subdirectory(connectors)
$<TARGET_OBJECTS:memory>
$<TARGET_OBJECTS:mime>
$<TARGET_OBJECTS:network_inspectors>
+ $<TARGET_OBJECTS:policy_selectors>
$<TARGET_OBJECTS:packet_io>
$<TARGET_OBJECTS:parser>
$<TARGET_OBJECTS:payload_injector>
${STATIC_CODEC_PLUGINS}
${STATIC_NETWORK_INSPECTOR_PLUGINS}
${STATIC_SERVICE_INSPECTOR_PLUGINS}
+ ${STATIC_POLICY_SELECTOR_PLUGINS}
${UNIT_TESTS_LIBRARIES}
)
return bytes_to_copy;
}
-
+
void OleFile :: get_file_data(char* file, uint8_t*& file_data, uint32_t& data_len)
{
- FileProperty* node;
- uint16_t sector_size,mini_sector_size;
- node = dir_list->get_file_node(file);
+ FileProperty* node = dir_list->get_file_node(file);
data_len = 0;
- sector_size = header->get_sector_size();
- mini_sector_size = header->get_mini_sector_size();
if (node)
{
int32_t starting_sector;
if (is_fat == FAT_SECTOR)
{
- int32_t current_sector;
- current_sector = starting_sector;
+ int32_t current_sector = starting_sector;
+ uint16_t sector_size = header->get_sector_size();
while (current_sector > INVALID_SECTOR)
{
byte_offset = get_fat_offset(current_sector);
bytes_to_copy = find_bytes_to_copy(byte_offset, data_len,
stream_size, sector_size);
-
+
memcpy(temp_data, (file_buf + byte_offset), bytes_to_copy);
temp_data += sector_size;
data_len += bytes_to_copy;
}
else
{
- int32_t mini_sector;
- mini_sector = node->get_starting_sector();
+ int32_t mini_sector = node->get_starting_sector();
+ uint16_t mini_sector_size = header->get_mini_sector_size();
while (mini_sector > INVALID_SECTOR)
{
byte_offset = get_mini_fat_offset(mini_sector);
while (it != dir_list->oleentry.end())
{
- FileProperty* node;
- uint8_t* data = nullptr;
- uint32_t data_len;
- node = it->second;
+ FileProperty* node = it->second;
++it;
if (node->get_file_type() == STREAM)
{
+ uint8_t* data = nullptr;
+ uint32_t data_len;
get_file_data(node->get_name(), data, data_len);
uint8_t* data1 = data;
int32_t offset = get_file_offset(data, data_len);
#include <condition_variable>
#include <list>
-#include <mutex>
#include <thread>
namespace snort
unsigned inspection_policy_id;
unsigned ips_policy_id;
- unsigned network_policy_id;
unsigned reload_id;
uint32_t iplist_monitor_id;
+ uint32_t tenant;
+
uint32_t default_session_timeout;
int32_t client_intf;
flow->server_group = p->pkth->egress_group;
}
+ flow->tenant = p->get_flow_geneve_vni();
+
flow->flags.app_direction_swapped = false;
if ( flow->ssn_state.direction == FROM_CLIENT )
p->packet_flags |= PKT_FROM_CLIENT;
const SnortConfig* sc = SnortConfig::get_conf();
set_inspection_policy(sc, flow->inspection_policy_id);
set_ips_policy(sc, flow->ips_policy_id);
- set_network_policy(sc, flow->network_policy_id);
p->filtering_state = flow->filtering_state;
}
void Active::set_drop_reason(char const*) { }
Packet::Packet(bool) { }
Packet::~Packet() = default;
+uint32_t Packet::get_flow_geneve_vni() const { return 0; }
Flow::Flow() { memset(this, 0, sizeof(*this)); }
Flow::~Flow() = default;
DetectionEngine::DetectionEngine() = default;
void Active::set_drop_reason(char const*) { }
Packet::Packet(bool) { }
Packet::~Packet() = default;
+uint32_t Packet::get_flow_geneve_vni() const { return 0; }
FlowCache::FlowCache(const FlowCacheConfig& cfg) : config(cfg) { }
FlowCache::~FlowCache() = default;
Flow::Flow() = default;
{
DB->_subscribe(key, h);
}
-void DataBus::subscribe_global(const char* key, DataHandler* h, SnortConfig*)
+void DataBus::subscribe_network(const char* key, DataHandler* h)
{
DB->_subscribe(key, h);
}
void DataBus::unsubscribe(const char*, DataHandler*) {}
-void DataBus::unsubscribe_global(const char*, DataHandler*, SnortConfig*) {}
+void DataBus::unsubscribe_network(const char*, DataHandler*) {}
void DataBus::publish(const char* key, DataEvent& e, Flow* f)
{
namespace snort
{
-SnortConfig::SnortConfig(const SnortConfig* const) { }
+SnortConfig::SnortConfig(const SnortConfig* const, const char*) { }
SnortConfig::~SnortConfig() = default;
const SnortConfig* SnortConfig::get_conf() { return &snort_conf; }
mpse_batch.h
packet_constraints.h
parameter.h
+ policy_selector.h
range.h
so_rule.h
value.h
// this is the current version of the base api
// must be prefixed to subtype version
-#define BASE_API_VERSION 9
+#define BASE_API_VERSION 10
// set options to API_OPTIONS to ensure compatibility
#ifndef API_OPTIONS
PT_SO_RULE,
PT_LOGGER,
PT_CONNECTOR,
+ PT_POLICY_SELECTOR,
#ifdef PIGLET
PT_PIGLET,
#endif
static DataBus& get_data_bus()
{ return get_inspection_policy()->dbus; }
+static DataBus& get_network_data_bus()
+{ return get_network_policy()->dbus; }
class BufferEvent : public DataEvent
{
}
// for subscribers that need to receive events regardless of active inspection policy
-void DataBus::subscribe_global(const char* key, DataHandler* h, SnortConfig* sc)
+void DataBus::subscribe_network(const char* key, DataHandler* h)
{
- assert(sc);
- sc->global_dbus->_subscribe(key, h);
+ get_network_data_bus()._subscribe(key, h);
}
void DataBus::unsubscribe(const char* key, DataHandler* h)
get_data_bus()._unsubscribe(key, h);
}
-void DataBus::unsubscribe_global(const char* key, DataHandler* h, SnortConfig* sc)
+void DataBus::unsubscribe_network(const char* key, DataHandler* h)
{
- assert(sc);
- sc->global_dbus->_unsubscribe(key, h);
+ get_network_data_bus()._unsubscribe(key, h);
}
// notify subscribers of event
void DataBus::publish(const char* key, DataEvent& e, Flow* f)
{
+ NetworkPolicy* ni = get_network_policy();
+ ni->dbus._publish(key, e, f);
+
InspectionPolicy* pi = get_inspection_policy();
pi->dbus._publish(key, e, f);
-
- SnortConfig::get_conf()->global_dbus->_publish(key, e, f);
}
void DataBus::publish(const char* key, const uint8_t* buf, unsigned len, Flow* f)
{
class Flow;
struct Packet;
-struct SnortConfig;
class DataEvent
{
// FIXIT-L ideally these would not be static or would take an inspection policy*
static void subscribe(const char* key, DataHandler*);
- static void subscribe_global(const char* key, DataHandler*, SnortConfig*);
+ static void subscribe_network(const char* key, DataHandler*);
// FIXIT-L these should be called during cleanup
static void unsubscribe(const char* key, DataHandler*);
- static void unsubscribe_global(const char* key, DataHandler*, SnortConfig*);
+ static void unsubscribe_network(const char* key, DataHandler*);
// runtime methods
static void publish(const char* key, DataEvent&, Flow* = nullptr);
"network",
"service",
"control",
- "probe"
+ "probe",
};
const char* InspectApi::get_type(InspectorType type)
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// policy_selector.h author Ron Dempster <rdempste@cisco.com>
+
+#ifndef POLICY_SELECTOR_H
+#define POLICY_SELECTOR_H
+
+// Policy selectors provide a method to select the network policy and default inspection
+// and IPS policies for a given packet
+
+#include <string>
+
+#include "framework/base_api.h"
+#include "framework/counts.h"
+#include "main/snort_types.h"
+
+struct _daq_pkt_hdr;
+
+namespace snort
+{
+#define POLICY_SELECTOR_API_VERSION ((BASE_API_VERSION << 16) | 0)
+
+struct Packet;
+class PolicySelector;
+struct PolicySelectorApi;
+struct SnortConfig;
+
+struct PolicySelectStats
+{
+ PegCount packets;
+ PegCount no_match;
+};
+
+struct PolicySelectUse
+{
+ std::string stringify() const
+ { return "file = " + name; }
+
+ std::string name;
+ unsigned network_index;
+ unsigned inspection_index;
+ unsigned ips_index;
+};
+
+typedef PolicySelector* (*SelectorNewFunc)(Module*);
+typedef void (*SelectorDeleteFunc)(PolicySelector*);
+
+struct PolicySelectorApi
+{
+ BaseApi base;
+ SelectorNewFunc ctor;
+ SelectorDeleteFunc dtor;
+};
+
+class SO_PUBLIC PolicySelector
+{
+public:
+ PolicySelector() = delete;
+ PolicySelector(const PolicySelector&) = delete;
+ virtual ~PolicySelector() = default;
+
+ static void free_policy_selector(PolicySelector* ps)
+ {
+ if (ps)
+ ps->get_api()->dtor(ps);
+ }
+ const PolicySelectorApi* get_api()
+ { return api; }
+ virtual bool select_default_policies(const _daq_pkt_hdr*, const SnortConfig*) = 0;
+ virtual void show() const = 0;
+
+protected:
+ explicit PolicySelector(const PolicySelectorApi* api) : api(api)
+ { }
+ const PolicySelectorApi* api;
+};
+}
+#endif
+
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness.h>
+#include <CppUTestExt/MockSupport.h>
using namespace snort;
//--------------------------------------------------------------------------
InspectionPolicy::InspectionPolicy(unsigned int) {}
InspectionPolicy::~InspectionPolicy() = default;
+NetworkPolicy::NetworkPolicy(unsigned int, unsigned int) {}
+NetworkPolicy::~NetworkPolicy() = default;
namespace snort
{
-SnortConfig::SnortConfig(snort::SnortConfig const*)
-{ global_dbus = new DataBus(); }
-
-THREAD_LOCAL const SnortConfig* snort_conf = nullptr;
+SnortConfig::SnortConfig(snort::SnortConfig const*, const char*)
+{ }
const SnortConfig* SnortConfig::get_conf()
-{ return snort_conf; }
+{
+ const SnortConfig* snort_conf =
+ (const SnortConfig*)mock().getData("snort_conf").getObjectPointer();
+ return snort_conf;
+}
SnortConfig* SnortConfig::get_main_conf()
-{ return const_cast<SnortConfig*>(snort_conf); }
+{
+ SnortConfig* snort_conf =
+ (SnortConfig*)mock().getData("snort_conf").getObjectPointer();
+ return snort_conf;
+}
SnortConfig::~SnortConfig()
-{ delete global_dbus; }
+{ }
-static InspectionPolicy* my_inspection_policy = nullptr;
+NetworkPolicy* get_network_policy()
+{
+ NetworkPolicy* my_network_policy =
+ (NetworkPolicy*)mock().getData("my_network_policy").getObjectPointer();
+ return my_network_policy;
+}
InspectionPolicy* get_inspection_policy()
-{ return my_inspection_policy; }
+{
+ InspectionPolicy* my_inspection_policy =
+ (InspectionPolicy*)mock().getData("my_inspection_policy").getObjectPointer();
+ return my_inspection_policy;
}
+
+}
+
//--------------------------------------------------------------------------
class UTestEvent : public DataEvent
{
TEST_GROUP(data_bus)
{
- void setup() override
- {
- snort_conf = new SnortConfig();
- my_inspection_policy = new InspectionPolicy();
- }
-
- void teardown() override
- {
- delete my_inspection_policy;
- delete snort_conf;
- }
+ SnortConfig snort_conf;
+ InspectionPolicy my_inspection_policy;
+ NetworkPolicy my_network_policy;
+
+ void setup() override
+ {
+ mock().setDataObject("snort_conf", "SnortConfig", &snort_conf);
+ mock().setDataObject("my_network_policy", "NetworkPolicy", &my_network_policy);
+ mock().setDataObject("my_inspection_policy", "InspectionPolicy", &my_inspection_policy);
+ }
+
+ void teardown() override
+ {
+ mock().clear();
+ }
};
-TEST(data_bus, subscribe_global)
+TEST(data_bus, subscribe_network)
{
- SnortConfig* sc = SnortConfig::get_main_conf();
UTestHandler* h = new UTestHandler();
- DataBus::subscribe_global(DB_UTEST_EVENT, h, sc);
+ DataBus::subscribe_network(DB_UTEST_EVENT, h);
UTestEvent event(100);
DataBus::publish(DB_UTEST_EVENT, event);
DataBus::publish(DB_UTEST_EVENT, event1);
CHECK(200 == h->evt_msg);
- DataBus::unsubscribe_global(DB_UTEST_EVENT, h, sc);
+ DataBus::unsubscribe_network(DB_UTEST_EVENT, h);
UTestEvent event2(300);
DataBus::publish(DB_UTEST_EVENT, event2);
THREAD_LOCAL SnortConfig* snort_conf = &my_config;
// run_flags is used indirectly from HashFnc class by calling SnortConfig::static_hash()
-SnortConfig::SnortConfig(const SnortConfig* const)
+SnortConfig::SnortConfig(const SnortConfig* const, const char*)
{ snort_conf->run_flags = 0;}
SnortConfig::~SnortConfig() = default;
THREAD_LOCAL SnortConfig* snort_conf = &my_config;
// run_flags is used indirectly from HashFnc class by calling SnortConfig::static_hash()
-SnortConfig::SnortConfig(const SnortConfig* const)
+SnortConfig::SnortConfig(const SnortConfig* const, const char*)
{ snort_conf->run_flags = 0;}
SnortConfig::~SnortConfig() = default;
THREAD_LOCAL SnortConfig *snort_conf = &my_config;
// run_flags is used indirectly from HashFnc class by calling SnortConfig::static_hash()
-SnortConfig::SnortConfig(const SnortConfig* const)
+SnortConfig::SnortConfig(const SnortConfig* const, const char*)
{ snort_conf->run_flags = 0;}
SnortConfig::~SnortConfig() = default;
static unsigned s_parse_errors = 0;
-SnortConfig::SnortConfig(const SnortConfig* const)
+SnortConfig::SnortConfig(const SnortConfig* const, const char*)
{
state = &s_state;
num_slots = 1;
static std::vector<void *> s_state;
static ScratchAllocator* scratcher = nullptr;
-SnortConfig::SnortConfig(const SnortConfig* const)
+SnortConfig::SnortConfig(const SnortConfig* const, const char*)
{
state = &s_state;
num_slots = 1;
PacketTracer::activate(*p);
- // FIXIT-M should not need to set policies here
- set_default_policy(p->context->conf);
p->user_inspection_policy_id = get_inspection_policy()->user_policy_id;
p->user_ips_policy_id = get_ips_policy()->user_policy_id;
p->user_network_policy_id = get_network_policy()->user_policy_id;
Packet* p = switcher->get_context()->packet;
p->context->wire_packet = p;
p->context->packet_number = get_packet_number();
- set_default_policy(p->context->conf);
+ select_default_policy(pkthdr, p->context->conf);
DetectionEngine::reset();
sfthreshold_reset();
return main_hook(p);
}
-bool Analyzer::process_rebuilt_packet(Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt, uint32_t pktlen)
+bool Analyzer::process_rebuilt_packet(Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt,
+ uint32_t pktlen)
{
PacketManager::decode(p, pkthdr, pkt, pktlen, true);
#include "policy.h"
+#include "daq_common.h"
+
#include "actions/actions.h"
#include "detection/detection_engine.h"
+#include "framework/policy_selector.h"
#include "log/messages.h"
#include "managers/inspector_manager.h"
#include "parser/parse_conf.h"
// traffic policy
//-------------------------------------------------------------------------
-NetworkPolicy::NetworkPolicy(PolicyId id)
+NetworkPolicy::NetworkPolicy(PolicyId id, PolicyId default_inspection_id)
+ : policy_id(id), default_inspection_policy_id(default_inspection_id)
+{ init(nullptr, nullptr); }
+
+NetworkPolicy::NetworkPolicy(NetworkPolicy* other_network_policy, const char* exclude_name)
+{ init(other_network_policy, exclude_name); }
+
+NetworkPolicy::~NetworkPolicy()
+{ InspectorManager::delete_policy(this, cloned); }
+
+void NetworkPolicy::init(NetworkPolicy* other_network_policy, const char* exclude_name)
{
- policy_id = id;
- user_policy_id = 0;
+ if (other_network_policy)
+ {
+ dbus.clone(other_network_policy->dbus, exclude_name);
+ policy_id = other_network_policy->policy_id;
+ default_inspection_policy_id = other_network_policy->default_inspection_policy_id;
+ user_policy_id = other_network_policy->user_policy_id;
- // minimum possible (allows all but errors to pass by default)
- min_ttl = 1;
- new_ttl = 5;
+ min_ttl = other_network_policy->min_ttl;
+ new_ttl = other_network_policy->new_ttl;
- checksum_eval = CHECKSUM_FLAG__ALL | CHECKSUM_FLAG__DEF;
- checksum_drop = CHECKSUM_FLAG__DEF;
+ checksum_eval = other_network_policy->checksum_eval;
+ checksum_drop = other_network_policy->checksum_drop;
+ normal_mask = other_network_policy->normal_mask;
+ }
+ InspectorManager::new_policy(this, other_network_policy);
}
-
//-------------------------------------------------------------------------
// inspection policy
//-------------------------------------------------------------------------
// policy map
//-------------------------------------------------------------------------
-PolicyMap::PolicyMap(PolicyMap* other_map)
+PolicyMap::PolicyMap(PolicyMap* other_map, const char* exclude_name)
{
if ( other_map )
- clone(other_map);
+ clone(other_map, exclude_name);
else
{
- add_shell(new Shell(nullptr, true));
+ add_shell(new Shell(nullptr, true), true);
empty_ips_policy = new IpsPolicy(ips_policy.size());
ips_policy.push_back(empty_ips_policy);
}
+ set_network_policy(network_policy[0]);
set_inspection_policy(inspection_policy[0]);
set_ips_policy(ips_policy[0]);
- set_network_policy(network_policy[0]);
}
PolicyMap::~PolicyMap()
default_policy->cloned = true;
delete default_policy;
}
+ if ( !network_policy.empty() )
+ {
+ NetworkPolicy* default_policy = network_policy[0];
+ default_policy->cloned = true;
+ delete default_policy;
+ }
}
else
{
shell_map.clear();
}
-void PolicyMap::clone(PolicyMap *other_map)
+void PolicyMap::clone(PolicyMap *other_map, const char* exclude_name)
{
shells = other_map->shells;
ips_policy = other_map->ips_policy;
- network_policy = other_map->network_policy;
empty_ips_policy = other_map->empty_ips_policy;
+ for ( unsigned i = 0; i < (other_map->network_policy.size()); i++)
+ {
+ if ( i == 0 )
+ network_policy.emplace_back(new NetworkPolicy(other_map->network_policy[i],
+ exclude_name));
+ else
+ network_policy.emplace_back(other_map->network_policy[i]);
+ }
+
for ( unsigned i = 0; i < (other_map->inspection_policy.size()); i++)
{
if ( i == 0 )
- {
inspection_policy.emplace_back(new InspectionPolicy(other_map->inspection_policy[i]));
- }
else
inspection_policy.emplace_back(other_map->inspection_policy[i]);
}
shell_map = other_map->shell_map;
-
- // Fix references to inspection_policy[0]
+ // Fix references to network_policy[0] and inspection_policy[0]
for ( auto p : other_map->shell_map )
{
+ if ( p.second->network == other_map->network_policy[0] )
+ shell_map[p.first]->network = network_policy[0];
if ( p.second->inspection == other_map->inspection_policy[0] )
shell_map[p.first] = std::make_shared<PolicyTuple>(inspection_policy[0], p.second->ips,
p.second->network);
}
- user_inspection = other_map->user_inspection;
+ user_network = other_map->user_network;
+ // Fix references to network_policy[0]
+ for ( auto p : other_map->user_network )
+ {
+ if ( p.second == other_map->network_policy[0] )
+ user_network[p.first] = network_policy[0];
+ }
+ user_inspection = other_map->user_inspection;
// Fix references to inspection_policy[0]
for ( auto p : other_map->user_inspection )
{
}
user_ips = other_map->user_ips;
- user_network = other_map->user_network;
}
InspectionPolicy* PolicyMap::add_inspection_shell(Shell* sh)
return p;
}
-std::shared_ptr<PolicyTuple> PolicyMap::add_shell(Shell* sh)
+std::shared_ptr<PolicyTuple> PolicyMap::add_shell(Shell* sh, bool include_network)
{
shells.push_back(sh);
inspection_policy.push_back(new InspectionPolicy(inspection_policy.size()));
+ InspectionPolicy* ip = inspection_policy.back();
+ NetworkPolicy* new_network_policy = nullptr;
+ if (include_network)
+ {
+ new_network_policy = new NetworkPolicy(network_policy.size(), ip->policy_id);
+ network_policy.push_back(new_network_policy);
+ }
ips_policy.push_back(new IpsPolicy(ips_policy.size()));
- network_policy.push_back(new NetworkPolicy(network_policy.size()));
-
- return shell_map[sh] = std::make_shared<PolicyTuple>(inspection_policy.back(),
- ips_policy.back(), network_policy.back());
+ return shell_map[sh] = std::make_shared<PolicyTuple>(ip,
+ ips_policy.back(), new_network_policy);
}
std::shared_ptr<PolicyTuple> PolicyMap::get_policies(Shell* sh)
void set_ips_policy(IpsPolicy* p)
{ s_detection_policy = p; }
-NetworkPolicy* get_user_network_policy(const SnortConfig* sc, unsigned policy_id)
-{
- return sc->policy_map->get_user_network(policy_id);
-}
-
InspectionPolicy* get_user_inspection_policy(const SnortConfig* sc, unsigned policy_id)
{
return sc->policy_map->get_user_inspection(policy_id);
}
+NetworkPolicy* get_default_network_policy(const SnortConfig* sc)
+{ return sc->policy_map->get_network_policy(0); }
+
InspectionPolicy* get_default_inspection_policy(const SnortConfig* sc)
-{ return sc->policy_map->get_inspection_policy(0); }
+{
+ return
+ sc->policy_map->get_inspection_policy(get_network_policy()->default_inspection_policy_id);
+}
IpsPolicy* get_ips_policy(const SnortConfig* sc, unsigned i)
{
set_ips_policy(sc->policy_map->get_ips_policy(0));
}
-bool only_network_policy()
-{ return get_network_policy() && !get_ips_policy() && !get_inspection_policy(); }
+void select_default_policy(const _daq_pkt_hdr* pkthdr, const SnortConfig* sc)
+{
+ if (!sc->global_selector || !sc->global_selector->select_default_policies(pkthdr, sc))
+ {
+ set_network_policy(sc->policy_map->get_network_policy(0));
+ set_inspection_policy(sc->policy_map->get_inspection_policy(0));
+ set_ips_policy(sc->policy_map->get_ips_policy(0));
+ }
+}
bool only_inspection_policy()
{ return get_inspection_policy() && !get_ips_policy() && !get_network_policy(); }
bool only_ips_policy()
{ return get_ips_policy() && !get_inspection_policy() && !get_network_policy(); }
-bool default_inspection_policy()
-{
- if ( !get_inspection_policy() )
- return false;
-
- if ( get_inspection_policy()->policy_id != 0 )
- return false;
-
- return true;
-}
-
namespace snort
{
class GHash;
-struct SnortConfig;
class IpsAction;
+struct SnortConfig;
}
+struct _daq_pkt_hdr;
struct PortTable;
struct vartable_t;
struct sfip_var_t;
// Snort ac-split creates the nap (network analysis policy)
// Snort++ breaks the nap into network and inspection
+
struct NetworkPolicy
{
public:
- NetworkPolicy(PolicyId = 0);
+ NetworkPolicy(PolicyId = 0, PolicyId default_inspection_id = 0);
+ NetworkPolicy(NetworkPolicy*, const char*);
+ ~NetworkPolicy();
bool checksum_drops(uint16_t codec_cksum_err_flag)
{ return (checksum_drop & codec_cksum_err_flag) != 0; }
{ return (checksum_eval & CHECKSUM_FLAG__ICMP) != 0; }
public:
- PolicyId policy_id;
+ struct TrafficPolicy* traffic_policy;
+ snort::DataBus dbus;
+
+ PolicyId policy_id = 0;
uint32_t user_policy_id = 0;
+ PolicyId default_inspection_policy_id = 0;
- uint8_t min_ttl;
- uint8_t new_ttl;
+ // minimum possible (allows all but errors to pass by default)
+ uint8_t min_ttl = 1;
+ uint8_t new_ttl = 5;
- uint32_t checksum_eval;
- uint32_t checksum_drop;
- uint32_t normal_mask;
+ uint32_t checksum_eval = CHECKSUM_FLAG__ALL | CHECKSUM_FLAG__DEF;
+ uint32_t checksum_drop = CHECKSUM_FLAG__DEF;
+ uint32_t normal_mask = 0;
+ bool cloned = false;
+
+private:
+ void init(NetworkPolicy*, const char*);
};
//-------------------------------------------------------------------------
class PolicyMap
{
public:
- PolicyMap(PolicyMap* old_map = nullptr);
+ PolicyMap(PolicyMap* old_map = nullptr, const char* exclude_name = nullptr);
~PolicyMap();
InspectionPolicy* add_inspection_shell(Shell*);
IpsPolicy* add_ips_shell(Shell*);
- std::shared_ptr<PolicyTuple> add_shell(Shell*);
+ std::shared_ptr<PolicyTuple> add_shell(Shell*, bool include_network);
std::shared_ptr<PolicyTuple> get_policies(Shell* sh);
- void clone(PolicyMap *old_map);
+ void clone(PolicyMap *old_map, const char* exclude_name);
Shell* get_shell(unsigned i = 0)
{ return i < shells.size() ? shells[i] : nullptr; }
SO_PUBLIC void set_inspection_policy(InspectionPolicy*);
SO_PUBLIC void set_ips_policy(IpsPolicy*);
-SO_PUBLIC NetworkPolicy* get_user_network_policy(const snort::SnortConfig*, unsigned policy_id);
+SO_PUBLIC NetworkPolicy* get_default_network_policy(const snort::SnortConfig*);
SO_PUBLIC InspectionPolicy* get_user_inspection_policy(const snort::SnortConfig*, unsigned policy_id);
SO_PUBLIC InspectionPolicy* get_default_inspection_policy(const snort::SnortConfig*);
void set_policies(const snort::SnortConfig*, Shell*);
void set_default_policy(const snort::SnortConfig*);
+void select_default_policy(const _daq_pkt_hdr*, const snort::SnortConfig*);
-bool only_network_policy();
bool only_inspection_policy();
bool only_ips_policy();
-bool default_inspection_policy();
#endif
#include "managers/module_manager.h"
#include "managers/mpse_manager.h"
#include "managers/plugin_manager.h"
+#include "managers/policy_selector_manager.h"
#include "managers/script_manager.h"
#include "memory/memory_cap.h"
#include "network_inspectors/network_inspectors.h"
#include "packet_io/trough.h"
#include "parser/cmd_line.h"
#include "parser/parser.h"
+#include "policy_selectors/policy_selectors.h"
#include "profiler/profiler.h"
#include "search_engines/search_engines.h"
#include "service_inspectors/service_inspectors.h"
load_piglets();
#endif
load_search_engines();
+ load_policy_selectors();
load_stream_inspectors();
load_network_inspectors();
load_service_inspectors();
}
HostAttributesManager::activate(sc);
+ if ( SnortConfig::log_verbose() )
+ PolicySelectorManager::print_config(sc);
+
// Must be after CodecManager::instantiate()
if ( !InspectorManager::configure(sc) )
ParseError("can't initialize inspectors");
}
if ( SnortConfig::log_verbose() )
+ {
+ PolicySelectorManager::print_config(sc);
InspectorManager::print_config(sc);
+ }
// FIXIT-L is this still needed?
/* Transfer any user defined rule type outputs to the new rule list */
reloading = true;
reset_parse_errors();
- SnortConfig* sc = new SnortConfig(other_conf);
- sc->global_dbus->clone(*other_conf->global_dbus, iname);
+ SnortConfig* sc = new SnortConfig(other_conf, iname);
if ( fname )
{
{
reloading = true;
- SnortConfig* sc = new SnortConfig(other_conf);
- sc->global_dbus->clone(*other_conf->global_dbus, name);
+ SnortConfig* sc = new SnortConfig(other_conf, name);
if ( name )
{
#include "filters/sfrf.h"
#include "filters/sfthreshold.h"
#include "flow/ha_module.h"
+#include "framework/policy_selector.h"
#include "hash/xhash.h"
#include "helpers/process.h"
#include "latency/latency_config.h"
}
}
-void SnortConfig::init(const SnortConfig* const other_conf, ProtocolReference* protocol_reference)
+void SnortConfig::init(const SnortConfig* const other_conf, ProtocolReference* protocol_reference,
+ const char* exclude_name)
{
homenet.clear();
obfuscation_net.clear();
memory = new MemoryConfig();
policy_map = new PolicyMap;
thread_config = new ThreadConfig();
- global_dbus = new DataBus();
proto_ref = new ProtocolReference(protocol_reference);
so_rules = new SoRules;
else
{
clone(other_conf);
- policy_map = new PolicyMap(other_conf->policy_map);
+ policy_map = new PolicyMap(other_conf->policy_map, exclude_name);
}
}
* but the goal is to minimize config checks at run time when running in
* IDS mode so we keep things simple and enforce that the only difference
* among run_modes is how we handle packets via the log_func. */
-SnortConfig::SnortConfig(const SnortConfig* const other_conf)
+SnortConfig::SnortConfig(const SnortConfig* const other_conf, const char* exclude_name)
{
- init(other_conf, nullptr);
+ init(other_conf, nullptr, exclude_name);
}
// Copy the ProtocolReference data into the new SnortConfig.
SnortConfig::SnortConfig(ProtocolReference* protocol_reference)
{
- init(nullptr, protocol_reference);
+ init(nullptr, protocol_reference, nullptr);
}
SnortConfig::~SnortConfig()
{
if ( cloned )
{
- delete global_dbus;
policy_map->set_cloned(true);
delete policy_map;
return;
delete trace_config;
delete overlay_trace_config;
delete ha_config;
- delete global_dbus;
delete profiler;
delete latency;
if ( plugins )
delete plugins;
delete payload_injector_config;
+ InspectorManager::free_flow_tracking(flow_tracking);
+ PolicySelector::free_policy_selector(global_selector);
clear_reload_resource_tuner_list();
trim_heap();
void SnortConfig::clone(const SnortConfig* const conf)
{
*this = *conf;
- global_dbus = new DataBus();
if (conf->homenet.get_family() != 0)
memcpy(&homenet, &conf->homenet, sizeof(homenet));
struct LatencyConfig;
struct MemoryConfig;
struct PayloadInjectorConfig;
+struct PHInstance;
struct Plugins;
struct PORT_RULE_MAP;
struct RateFilterConfig;
namespace snort
{
class GHash;
+class PolicySelector;
class ProtocolReference;
class ThreadConfig;
class XHash;
struct SnortConfig
{
private:
- void init(const SnortConfig* const, ProtocolReference*);
+ void init(const SnortConfig* const, ProtocolReference*, const char* exclude_name);
public:
- SnortConfig(const SnortConfig* const other_conf = nullptr);
+ SnortConfig(const SnortConfig* const other_conf = nullptr, const char* exclude_name = nullptr);
SnortConfig(ProtocolReference* protocol_reference);
~SnortConfig();
PolicyMap* policy_map = nullptr;
std::string tweaks;
- DataBus* global_dbus = nullptr;
+ PolicySelector* global_selector = nullptr;
+ PHInstance* flow_tracking = nullptr;
+ PHInstance* removed_flow_tracking = nullptr;
uint16_t tunnel_mask = 0;
{ return logging_flags & LOGGING_FLAG__SYSLOG; }
static void set_log_quiet(bool enabled)
- {
+ {
if (enabled)
logging_flags |= LOGGING_FLAG__QUIET;
else
ThreadConfig::set_instance_max(new_max);
CHECK(ThreadConfig::get_instance_max() == new_max);
ThreadConfig::set_instance_max(0);
- CHECK(ThreadConfig::get_instance_max() == hwloc_bitmap_weight(process_cpuset));
+ CHECK(ThreadConfig::get_instance_max() == (unsigned)hwloc_bitmap_weight(process_cpuset));
}
TEST_CASE("Set and implement thread affinity", "[ThreadConfig]")
mpse_manager.h
plugin_manager.cc
plugin_manager.h
+ policy_selector_manager.cc
+ policy_selector_manager.h
script_manager.cc
script_manager.h
so_manager.cc
}
}
-struct FrameworkPolicy
+struct InspectorList
{
+ virtual ~InspectorList() = default;
+
PHInstanceList ilist; // List of inspector module instances
PHInstanceList removed_ilist; // List of removed inspector module instances
+ virtual void handle_new_reenabled(SnortConfig*, bool, bool) = 0;
+ virtual void vectorize(SnortConfig*) = 0;
+};
+
+struct TrafficPolicy : public InspectorList
+{
PHVector passive;
PHVector packet;
PHVector first;
+ PHVector control;
+
+ void handle_new_reenabled(SnortConfig*, bool, bool) override
+ { }
+ void vectorize(SnortConfig*) override;
+};
+
+void TrafficPolicy::vectorize(SnortConfig*)
+{
+ passive.alloc(ilist.size());
+ packet.alloc(ilist.size());
+ first.alloc(ilist.size());
+ control.alloc(ilist.size());
+
+ for ( auto* p : ilist )
+ {
+ switch ( p->pp_class.api.type )
+ {
+ case IT_PASSIVE:
+ passive.add(p);
+ break;
+
+ case IT_PACKET:
+ packet.add(p);
+ break;
+
+ case IT_FIRST:
+ first.add(p);
+ break;
+
+ case IT_CONTROL:
+ control.add_control(p);
+ break;
+
+ default:
+ ParseError("Network policy (context usage) does not handle %s inspector type\n",
+ InspectApi::get_type(p->pp_class.api.type));
+ break;
+ }
+ }
+}
+
+struct FrameworkPolicy : public InspectorList
+{
+ PHVector passive;
+ PHVector packet;
PHVector network;
- PHVector session;
PHVector service;
- PHVector control;
PHVector probe;
Inspector* binder;
bool default_binder;
- void vectorize(SnortConfig*);
+ void handle_new_reenabled(SnortConfig*, bool, bool) override;
+ void vectorize(SnortConfig*) override;
void add_inspector_to_cache(PHInstance*, SnortConfig*);
void remove_inspector_from_cache(Inspector*);
};
}
}
+static bool get_instance(InspectorList*, const char*,
+ std::vector<PHInstance*>::iterator&);
+
+void FrameworkPolicy::handle_new_reenabled(SnortConfig* sc, bool new_ins, bool reenabled_ins)
+{
+ std::vector<PHInstance*>::iterator old_binder;
+ if ( get_instance(this, bind_id, old_binder) )
+ {
+ if ( new_ins and default_binder )
+ {
+ if ( !((*old_binder)->is_reloaded()) )
+ {
+ (*old_binder)->set_reloaded(RELOAD_TYPE_REENABLED);
+ ilist.erase(old_binder);
+ }
+ default_binder = false;
+ }
+ else if ( reenabled_ins and !((*old_binder)->is_reloaded()) )
+ {
+ (*old_binder)->handler->configure(sc);
+ }
+ }
+}
+
+static void instantiate_default_binder(SnortConfig*, FrameworkPolicy*);
+
void FrameworkPolicy::vectorize(SnortConfig* sc)
{
passive.alloc(ilist.size());
packet.alloc(ilist.size());
- first.alloc(ilist.size());
network.alloc(ilist.size());
- session.alloc(ilist.size());
service.alloc(ilist.size());
- control.alloc(ilist.size());
probe.alloc(ilist.size());
for ( auto* p : ilist )
packet.add(p);
break;
- case IT_FIRST:
- first.add(p);
- break;
-
case IT_NETWORK:
network.add(p);
break;
case IT_STREAM:
- if ( !p->pp_class.api.ssn )
- session.add(p);
break;
case IT_SERVICE:
wizard = p->handler;
break;
- case IT_CONTROL:
- control.add_control(p);
- break;
-
case IT_PROBE:
{
// probes always run
break;
}
- case IT_MAX:
+ default:
+ ParseError("Inspection policy does not handle %s inspector type\n",
+ InspectApi::get_type(p->pp_class.api.type));
break;
}
}
+
+ // create cache
+ inspector_cache_by_id.clear();
+ inspector_cache_by_service.clear();
+ for ( auto* p : ilist )
+ add_inspector_to_cache(p, sc);
+
+ if ( !binder and (sc->flow_tracking or wizard) )
+ instantiate_default_binder(sc, this);
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
static bool get_instance(
- FrameworkPolicy* fp, const char* keyword,
+ InspectorList* il, const char* keyword,
std::vector<PHInstance*>::iterator& it)
{
- for ( it = fp->ilist.begin(); it != fp->ilist.end(); ++it )
+ for ( it = il->ilist.begin(); it != il->ilist.end(); ++it )
{
if ( (*it)->name == keyword )
return true;
return false;
}
-static PHInstance* get_instance(FrameworkPolicy* fp, const char* keyword)
+static PHInstance* get_instance(InspectorList* il, const char* keyword)
{
std::vector<PHInstance*>::iterator it;
- return get_instance(fp, keyword, it) ? *it : nullptr;
+ return get_instance(il, keyword, it) ? *it : nullptr;
}
static PHInstance* get_new(
- PHClass* ppc, FrameworkPolicy* fp, const char* keyword, Module* mod, SnortConfig* sc)
+ PHClass* ppc, InspectorList* il, const char* keyword, Module* mod, SnortConfig* sc)
{
PHInstance* p = nullptr;
bool reloaded = false;
std::vector<PHInstance*>::iterator old_it;
- if ( get_instance(fp, keyword, old_it) )
+ if ( get_instance(il, keyword, old_it) )
{
if ( Snort::is_reloading() )
{
(*old_it)->set_reloaded(RELOAD_TYPE_REENABLED);
- fp->ilist.erase(old_it);
+ il->ilist.erase(old_it);
reloaded = true;
}
else
else
p->set_reloaded(RELOAD_TYPE_NEW);
}
- fp->ilist.emplace_back(p);
+ il->ilist.emplace_back(p);
return p;
}
pi->framework_policy->wizard = nullptr;
}
+void InspectorManager::new_policy(NetworkPolicy* pi, NetworkPolicy* other_pi)
+{
+ pi->traffic_policy = new TrafficPolicy;
+
+ if ( other_pi )
+ pi->traffic_policy->ilist = other_pi->traffic_policy->ilist;
+}
+
void InspectorManager::delete_policy(InspectionPolicy* pi, bool cloned)
{
for ( auto* p : pi->framework_policy->ilist )
pi->framework_policy = nullptr;
}
+void InspectorManager::delete_policy(NetworkPolicy* pi, bool cloned)
+{
+ for ( auto* p : pi->traffic_policy->ilist )
+ {
+ if ( cloned and !(p->is_reloaded()) )
+ continue;
+
+ if ( p->handler->get_api()->type == IT_PASSIVE )
+ s_trash2.emplace_back(p->handler);
+ else
+ s_trash.emplace_back(p->handler);
+
+ delete p;
+ }
+ delete pi->traffic_policy;
+ pi->traffic_policy = nullptr;
+}
+
void InspectorManager::update_policy(SnortConfig* sc)
{
- InspectionPolicy* pi = sc->policy_map->get_inspection_policy();
- for ( auto* p : pi->framework_policy->ilist )
+ InspectionPolicy* ip = sc->policy_map->get_inspection_policy();
+ for ( auto* p : ip->framework_policy->ilist )
+ p->set_reloaded(RELOAD_TYPE_NONE);
+ NetworkPolicy* np = sc->policy_map->get_network_policy();
+ for ( auto* p : np->traffic_policy->ilist )
p->set_reloaded(RELOAD_TYPE_NONE);
}
void InspectorManager::clear_removed_inspectors(SnortConfig* sc)
{
+ if (sc->removed_flow_tracking)
+ {
+ sc->removed_flow_tracking->handler->rem_global_ref();
+ sc->removed_flow_tracking = nullptr;
+ }
+ TrafficPolicy* tp = sc->policy_map->get_network_policy()->traffic_policy;
+ for ( auto* p : tp->removed_ilist )
+ p->handler->rem_global_ref();
+ tp->removed_ilist.clear();
FrameworkPolicy* fp = sc->policy_map->get_inspection_policy()->framework_policy;
for ( auto* p : fp->removed_ilist )
p->handler->rem_global_ref();
void InspectorManager::tear_down_removed_inspectors(const SnortConfig* old, SnortConfig* sc)
{
+ if (old->flow_tracking && !sc->flow_tracking)
+ {
+ sc->removed_flow_tracking = old->flow_tracking;
+ sc->removed_flow_tracking->handler->add_global_ref();
+ sc->removed_flow_tracking->handler->tear_down(sc);
+ }
+
+ TrafficPolicy* tp = get_default_network_policy(sc)->traffic_policy;
+ TrafficPolicy* old_tp = get_default_network_policy(old)->traffic_policy;
+ for (auto it = old_tp->ilist.begin(); it != old_tp->ilist.end(); ++it)
+ {
+ PHInstance* instance = get_instance(tp, (*it)->name.c_str());
+ if (!instance)
+ {
+ tp->removed_ilist.emplace_back(*it);
+ (*it)->handler->add_global_ref();
+ (*it)->handler->tear_down(sc);
+ }
+ }
+
FrameworkPolicy* fp = get_default_inspection_policy(sc)->framework_policy;
- InspectionPolicy* old_p = get_default_inspection_policy(old);
- FrameworkPolicy* old_fp = old_p->framework_policy;
+ FrameworkPolicy* old_fp = get_default_inspection_policy(old)->framework_policy;
for (auto it = old_fp->ilist.begin(); it != old_fp->ilist.end(); ++it)
{
PHInstance* instance = get_instance(fp, (*it)->name.c_str());
Inspector* InspectorManager::get_inspector(const char* key, bool dflt_only, const SnortConfig* sc)
{
InspectionPolicy* pi;
+ NetworkPolicy* ni;
if ( dflt_only )
{
if ( !sc )
sc = SnortConfig::get_conf();
pi = get_default_inspection_policy(sc);
+ ni = get_default_network_policy(sc);
}
else
+ {
pi = get_inspection_policy();
+ ni = get_network_policy();
+ }
- if ( !pi || !pi->framework_policy )
- return nullptr;
-
- PHInstance* p = get_instance(pi->framework_policy, key);
-
- if ( !p )
- return nullptr;
+ if ( pi && pi->framework_policy )
+ {
+ PHInstance* p = get_instance(pi->framework_policy, key);
+ if ( p )
+ return p->handler;
+ }
- return p->handler;
+ if ( ni && ni->traffic_policy )
+ {
+ PHInstance* p = get_instance(ni->traffic_policy, key);
+ if ( p )
+ return p->handler;
+ }
+ return nullptr;
}
Inspector* InspectorManager::get_service_inspector_by_service(const char* key)
p->get_api()->dtor(p);
}
+void InspectorManager::free_flow_tracking(PHInstance* pi)
+{
+ if (pi)
+ {
+ Inspector* i = pi->handler;
+ delete pi;
+ free_inspector(i);
+ }
+}
+
InspectSsnFunc InspectorManager::get_session(uint16_t proto)
{
for ( auto* p : s_handlers )
// pin->tinit() only called for default policy
set_default_policy(sc);
- InspectionPolicy* pi = get_inspection_policy();
+ if (sc->flow_tracking)
+ {
+ PHGlobal& phg = get_thread_local_plugin(sc->flow_tracking->pp_class.api);
+ if ( !phg.instance_initialized )
+ {
+ sc->flow_tracking->handler->tinit();
+ phg.instance_initialized = true;
+ }
+ }
+ InspectionPolicy* pi = get_inspection_policy();
if ( pi && pi->framework_policy )
{
for ( auto* p : pi->framework_policy->ilist )
}
}
}
+
+ for ( unsigned i = 0; i < sc->policy_map->network_policy_count(); i++)
+ {
+ NetworkPolicy* npi = sc->policy_map->get_network_policy(i);
+ set_network_policy(npi);
+ for ( auto* p : npi->traffic_policy->ilist )
+ {
+ PHGlobal& phg = get_thread_local_plugin(p->pp_class.api);
+ if ( !phg.instance_initialized )
+ {
+ p->handler->tinit();
+ phg.instance_initialized = true;
+ }
+ }
+ }
}
void InspectorManager::thread_reinit(const SnortConfig* sc)
}
}
- // pin->tinit() only called for default policy
- InspectionPolicy* pi = get_default_inspection_policy(sc);
+ set_default_policy(sc);
+ if (sc->flow_tracking)
+ {
+ PHGlobal& phg = get_thread_local_plugin(sc->flow_tracking->pp_class.api);
+ if ( !phg.instance_initialized )
+ {
+ if (phg.api.tinit)
+ sc->flow_tracking->handler->tinit();
+ phg.instance_initialized = true;
+ }
+ }
- if ( pi && pi->framework_policy )
+ for ( unsigned i = 0; i < sc->policy_map->network_policy_count(); i++)
{
- // Call pin->tinit() for anything that hasn't yet
- for ( auto* p : pi->framework_policy->ilist )
+ NetworkPolicy* npi = sc->policy_map->get_network_policy(i);
+ set_network_policy(npi);
+
+ for ( auto* p : npi->traffic_policy->ilist )
{
PHGlobal& phg = get_thread_local_plugin(p->pp_class.api);
if ( !phg.instance_initialized )
phg.instance_initialized = true;
}
}
+
+ // pin->tinit() only called for default policy
+ InspectionPolicy* pi = get_default_inspection_policy(sc);
+ if ( pi && pi->framework_policy )
+ {
+ // Call pin->tinit() for anything that hasn't yet
+ for ( auto* p : pi->framework_policy->ilist )
+ {
+ PHGlobal& phg = get_thread_local_plugin(p->pp_class.api);
+ if ( !phg.instance_initialized )
+ {
+ p->handler->tinit();
+ phg.instance_initialized = true;
+ }
+ }
+ }
}
}
void InspectorManager::thread_stop_removed(const SnortConfig* sc)
{
+ if (sc->removed_flow_tracking)
+ {
+ PHGlobal& phg = get_thread_local_plugin(sc->removed_flow_tracking->pp_class.api);
+ if ( phg.instance_initialized )
+ {
+ sc->removed_flow_tracking->handler->tterm();
+ phg.instance_initialized = false;
+ }
+ }
+
+ // pin->tinit() only called for default policy
+ NetworkPolicy* npi = get_default_network_policy(sc);
+
+ if ( npi && npi->traffic_policy )
+ {
+ // Call pin->tterm() for anything that has been initialized and removed
+ for ( auto* p : npi->traffic_policy->removed_ilist )
+ {
+ PHGlobal& phg = get_thread_local_plugin(p->pp_class.api);
+ if ( phg.instance_initialized )
+ {
+ p->handler->tterm();
+ phg.instance_initialized = false;
+ }
+ }
+ }
+
// pin->tinit() only called for default policy
InspectionPolicy* pi = get_default_inspection_policy(sc);
// pin->tterm() only called for default policy
set_default_policy(sc);
- InspectionPolicy* pi = get_inspection_policy();
+ if (sc->flow_tracking)
+ {
+ PHGlobal& phg = get_thread_local_plugin(sc->flow_tracking->pp_class.api);
+ if ( phg.instance_initialized )
+ {
+ sc->flow_tracking->handler->tterm();
+ phg.instance_initialized = false;
+ }
+ }
+ InspectionPolicy* pi = get_inspection_policy();
if ( pi && pi->framework_policy )
{
for ( auto* p : pi->framework_policy->ilist )
}
}
}
+
+ for ( unsigned i = 0; i < sc->policy_map->network_policy_count(); i++)
+ {
+ NetworkPolicy* npi = sc->policy_map->get_network_policy(i);
+ set_network_policy(npi);
+ for ( auto* p : npi->traffic_policy->ilist )
+ {
+ PHGlobal& phg = get_thread_local_plugin(p->pp_class.api);
+ if ( phg.instance_initialized )
+ {
+ p->handler->tterm();
+ phg.instance_initialized = false;
+ }
+ }
+ }
}
void InspectorManager::thread_term()
{
assert(mod);
- FrameworkConfig* fc = sc->framework_config;
- FrameworkPolicy* fp = get_inspection_policy()->framework_policy;
-
// FIXIT-L should not need to lookup inspector etc
// since given api and mod
+ FrameworkConfig* fc = sc->framework_config;
const char* keyword = api->base.name;
PHClass* ppc = get_class(keyword, fc);
if ( !ppc )
ParseError("unknown inspector: '%s'.", keyword);
-
else
{
- if ( name )
- keyword = name;
+ PHInstance* ppi;
+ if (Module::GLOBAL == mod->get_usage() && IT_STREAM == api->type)
+ {
+ assert(sc);
+ if (sc->flow_tracking)
+ {
+ ParseError("Only one flow tracking inspector may be instantiated\n");
+ return;
+ }
+ ppi = new PHInstance(*ppc, sc, mod);
+ if ( ppi->handler )
+ sc->flow_tracking = ppi;
+ else
+ {
+ delete ppi;
+ ppi = nullptr;
+ }
+ }
+ else
+ {
+ InspectorList* il;
+ if (Module::CONTEXT == mod->get_usage())
+ il = get_network_policy()->traffic_policy;
+ else
+ il = get_inspection_policy()->framework_policy;
+ assert(il);
- PHInstance* ppi = get_new(ppc, fp, keyword, mod, sc);
+ if ( name )
+ keyword = name;
+
+ ppi = get_new(ppc, il, keyword, mod, sc);
+ }
if ( ppi )
ppi->set_name(keyword);
fp->default_binder = true;
}
-static bool configure(SnortConfig* sc, FrameworkPolicy* fp, bool cloned)
+static bool configure(SnortConfig* sc, InspectorList* il, bool cloned, bool& new_ins,
+ bool& reenabled_ins)
{
bool ok = true;
- bool new_ins = false;
- bool reenabled_ins = false;
- for ( auto* p : fp->ilist )
+ for ( auto* p : il->ilist )
{
ReloadType reload_type = p->get_reload_type();
}
if ( new_ins or reenabled_ins )
- {
- std::vector<PHInstance*>::iterator old_binder;
- if ( get_instance(fp, bind_id, old_binder) )
- {
- if ( new_ins and fp->default_binder )
- {
- if ( !((*old_binder)->is_reloaded()) )
- {
- (*old_binder)->set_reloaded(RELOAD_TYPE_REENABLED);
- fp->ilist.erase(old_binder);
- }
- fp->default_binder = false;
- }
- else if ( reenabled_ins and !((*old_binder)->is_reloaded()) )
- {
- (*old_binder)->handler->configure(sc);
- }
- }
- }
+ il->handle_new_reenabled(sc, new_ins, reenabled_ins);
- sort(fp->ilist.begin(), fp->ilist.end(), PHInstance::comp);
- fp->vectorize(sc);
-
- // create cache
- fp->inspector_cache_by_id.clear();
- fp->inspector_cache_by_service.clear();
- for ( auto* p : fp->ilist )
- fp->add_inspector_to_cache(p, sc);
-
- if ( !fp->binder and (fp->session.num or fp->wizard) )
- instantiate_default_binder(sc, fp);
+ sort(il->ilist.begin(), il->ilist.end(), PHInstance::comp);
+ il->vectorize(sc);
return ok;
}
SearchTool::set_conf(sc);
+ bool new_ins = false;
+ bool reenabled_ins = false;
+ for ( unsigned idx = 0; idx < sc->policy_map->network_policy_count(); ++idx )
+ {
+ if ( cloned and idx )
+ break;
+
+ ::set_network_policy(sc, idx);
+ NetworkPolicy* p = sc->policy_map->get_network_policy(idx);
+ ok = ::configure(sc, p->traffic_policy, cloned, new_ins, reenabled_ins) && ok;
+ }
+ ::set_network_policy(sc);
+
+ if (sc->flow_tracking)
+ ok = sc->flow_tracking->handler->configure(sc) && ok;
+
+ ::set_inspection_policy(sc);
for ( unsigned idx = 0; idx < sc->policy_map->inspection_policy_count(); ++idx )
{
if ( cloned and idx )
::set_inspection_policy(sc, idx);
InspectionPolicy* p = sc->policy_map->get_inspection_policy(idx);
p->configure();
- ok = ::configure(sc, p->framework_policy, cloned) && ok;
+ ok = ::configure(sc, p->framework_policy, cloned, new_ins, reenabled_ins) && ok;
}
::set_inspection_policy(sc);
// remove any disabled controls while retaining order
void InspectorManager::prepare_controls(SnortConfig* sc)
{
- InspectionPolicy* pi = get_default_inspection_policy(sc);
- assert(pi);
-
- FrameworkPolicy* fp = pi->framework_policy;
- assert(fp);
+ for ( unsigned idx = 0; idx < sc->policy_map->network_policy_count(); ++idx )
+ {
+ TrafficPolicy* tp = sc->policy_map->get_network_policy(idx)->traffic_policy;
+ unsigned c = 0;
+ for ( unsigned i = 0; i < tp->control.num; ++i )
+ {
+ if ( !tp->control.vec[i]->handler->disable(sc) )
+ tp->control.vec[c++] = tp->control.vec[i];
+ }
+ tp->control.num = c;
+ }
+}
- unsigned c = 0;
+std::string InspectorManager::generate_inspector_label(const PHInstance* p)
+{
+ std::string name(p->pp_class.api.base.name);
+ if ( p->name != name )
+ name += " (" + p->name + "):";
+ else
+ name += ":";
+ return name;
+}
- for ( unsigned i = 0; i < fp->control.num; ++i )
+void InspectorManager::sort_inspector_list(const InspectorList* il,
+ std::map<const std::string, const PHInstance*>& sorted_ilist)
+{
+ for ( const auto* p : il->ilist )
{
- if ( !fp->control.vec[i]->handler->disable(sc) )
- fp->control.vec[c++] = fp->control.vec[i];
+ std::string name = generate_inspector_label(p);
+ sorted_ilist.emplace(name, p);
}
- fp->control.num = c;
}
void InspectorManager::print_config(SnortConfig* sc)
{
+ if (sc->flow_tracking)
+ {
+ LogLabel("Flow Tracking");
+ const std::string name = generate_inspector_label(sc->flow_tracking);
+ LogLabel(name.c_str());
+ sc->flow_tracking->handler->show(sc);
+ }
+
const auto shell_number = sc->policy_map->shells_count();
for ( unsigned shell_id = 0; shell_id < shell_number; shell_id++ )
{
const auto shell = sc->policy_map->get_shell(shell_id);
const auto policies = sc->policy_map->get_policies(shell);
- const auto inspection = policies->inspection;
- if ( !(inspection and inspection->framework_policy) )
- continue;
-
- std::map<const std::string, const PHInstance*> sorted_ilist;
- for ( const auto* p : inspection->framework_policy->ilist )
+ const auto network = policies->network;
+ if ( network and network->traffic_policy )
{
- std::string inspector_name(p->pp_class.api.base.name);
- if ( p->name != inspector_name )
- inspector_name += " (" + p->name + "):";
- else
- inspector_name += ":";
- sorted_ilist.emplace(inspector_name, p);
+ const std::string label = "Network Policy : policy id " +
+ std::to_string(network->user_policy_id) + " : " +
+ shell->get_file();
+ LogLabel(label.c_str());
+ std::map<const std::string, const PHInstance*> sorted_ilist;
+ sort_inspector_list(network->traffic_policy, sorted_ilist);
+ for ( const auto& p : sorted_ilist )
+ {
+ LogLabel(p.first.c_str());
+ p.second->handler->show(sc);
+ }
}
- const std::string label = "Inspection Policy : policy id " +
- std::to_string(inspection->user_policy_id) + " : " +
- shell->get_file();
- LogLabel(label.c_str());
-
- for ( const auto& p : sorted_ilist )
+ const auto inspection = policies->inspection;
+ if ( inspection and inspection->framework_policy )
{
- LogLabel(p.first.c_str());
- p.second->handler->show(sc);
+ const std::string label = "Inspection Policy : policy id " +
+ std::to_string(inspection->user_policy_id) + " : " +
+ shell->get_file();
+ LogLabel(label.c_str());
+ std::map<const std::string, const PHInstance*> sorted_ilist;
+ sort_inspector_list(inspection->framework_policy, sorted_ilist);
+ for ( const auto& p : sorted_ilist )
+ {
+ LogLabel(p.first.c_str());
+ p.second->handler->show(sc);
+ }
}
}
}
template<bool T>
static inline void execute(
- Packet* p, PHInstance** prep, unsigned num)
+ Packet* p, PHInstance* const * prep, unsigned num)
{
Stopwatch<SnortClock> timer;
for ( unsigned i = 0; i < num; ++i, ++prep )
if ( p->packet_flags & PKT_PASS_RULE )
break;
- PHClass& ppc = (*prep)->pp_class;
+ const PHClass& ppc = (*prep)->pp_class;
// FIXIT-P these checks can eventually be optimized
// but they are required to ensure that session and app
timer.start();
}
- FrameworkPolicy* fp = get_inspection_policy()->framework_policy;
- assert(fp);
+ const SnortConfig* sc = p->context->conf;
+ if ( !p->has_paf_payload() && sc->flow_tracking )
+ ::execute<T>(p, &sc->flow_tracking, 1);
- if ( !p->has_paf_payload() )
- {
- // FIXIT-L there is at most one in session; stream_base should
- // be elevated from inspector to framework component (it is just
- // a flow control wrapper) and use eval() instead of process()
- // for stream_*.
- ::execute<T>(p, fp->session.vec, fp->session.num);
- fp = get_inspection_policy()->framework_policy;
- }
// must check between each ::execute()
if ( p->disable_inspect )
return;
+ if (!p->flow)
+ DataBus::publish(PKT_WITHOUT_FLOW_EVENT, p);
+
+ FrameworkPolicy* fp = get_inspection_policy()->framework_policy;
+ assert(fp);
+
if ( !p->is_cooked() )
::execute<T>(p, fp->packet.vec, fp->packet.num);
if ( p->disable_inspect )
return;
- const SnortConfig* sc = p->context->conf;
- FrameworkPolicy* fp_dft = get_default_inspection_policy(sc)->framework_policy;
+ TrafficPolicy* tp = get_network_policy()->traffic_policy;
+ assert(tp);
+
+ if ( !p->is_cooked() )
+ ::execute<T>(p, tp->packet.vec, tp->packet.num);
+
+ if ( p->disable_inspect )
+ return;
if ( !p->flow )
{
- if ( fp_dft != fp )
- ::execute<T>(p, fp_dft->first.vec, fp_dft->first.num);
- ::execute<T>(p, fp->first.vec, fp->first.num);
+ ::execute<T>(p, tp->first.vec, tp->first.num);
if ( p->disable_inspect )
return;
- if (fp_dft != fp)
- ::execute<T>(p, fp_dft->network.vec, fp_dft->network.num);
::execute<T>(p, fp->network.vec, fp->network.num);
if ( p->disable_inspect )
return;
- ::execute<T>(p, fp_dft->control.vec, fp_dft->control.num);
+ ::execute<T>(p, tp->control.vec, tp->control.num);
}
else
{
if ( p->flow->reload_id != sc->reload_id )
{
- if ( fp_dft != fp )
- ::execute<T>(p, fp_dft->first.vec, fp_dft->first.num);
- ::execute<T>(p, fp->first.vec, fp->first.num);
+ ::execute<T>(p, tp->first.vec, tp->first.num);
p->flow->reload_id = sc->reload_id;
if ( p->disable_inspect )
}
if ( !p->flow->service )
- {
- if (fp_dft != fp)
- ::execute<T>(p, fp_dft->network.vec, fp_dft->network.num);
::execute<T>(p, fp->network.vec, fp->network.num);
- }
if ( p->disable_inspect )
return;
full_inspection<T>(p);
if ( !p->disable_inspect and !p->flow->is_inspection_disabled() )
- ::execute<T>(p, fp_dft->control.vec, fp_dft->control.num);
+ ::execute<T>(p, tp->control.vec, tp->control.num);
}
if ( T )
// Factory for Inspectors.
// Also provides packet evaluation.
+#include <map>
+
#include "framework/inspector.h"
class Binder;
-struct FrameworkPolicy;
+struct InspectorList;
struct InspectionPolicy;
+struct NetworkPolicy;
+struct PHInstance;
namespace snort
{
static std::vector<const InspectApi*> get_apis();
static const char* get_inspector_type(const char* name);
+ static void new_policy(NetworkPolicy*, NetworkPolicy*);
+ static void delete_policy(NetworkPolicy*, bool cloned);
+
static void new_policy(InspectionPolicy*, InspectionPolicy*);
static void delete_policy(InspectionPolicy*, bool cloned);
+
static void update_policy(SnortConfig* sc);
static void new_config(SnortConfig*);
static bool delete_inspector(SnortConfig*, const char* iname);
static void free_inspector(Inspector*);
+ static void free_flow_tracking(PHInstance*);
static InspectSsnFunc get_session(uint16_t proto);
SO_PUBLIC static Inspector* get_inspector(
static bool configure(SnortConfig*, bool cloned = false);
static void prepare_controls(SnortConfig*);
+ static std::string generate_inspector_label(const PHInstance*);
static void print_config(SnortConfig*);
static void thread_init(const SnortConfig*);
static void thread_stop(const SnortConfig*);
static void thread_term();
- static void release_policy(FrameworkPolicy*);
-
static void execute(Packet*);
static void probe(Packet*);
static void bumble(Packet*);
template<bool T> static void full_inspection(Packet*);
template<bool T> static void internal_execute(Packet*);
+ static void sort_inspector_list(const InspectorList* il,
+ std::map<const std::string, const PHInstance*>& sorted_ilist);
};
}
#endif
static bool interested(Module* m)
{
- if ( m->get_usage() == Module::GLOBAL && !default_inspection_policy() )
+ NetworkPolicy* np = get_network_policy();
+ if ( m->get_usage() == Module::GLOBAL && (!np || np->policy_id) )
return false;
if ( m->get_usage() != Module::INSPECT && only_inspection_policy() )
if ( m->get_usage() != Module::DETECT && only_ips_policy() )
return false;
- if ( m->get_usage() != Module::CONTEXT && only_network_policy() )
+ if ( m->get_usage() == Module::CONTEXT && !np )
return false;
return true;
{
if ( m->is_bindable() )
return "multiton";
- else if (
- (m->get_usage() == Module::GLOBAL) or
- (m->get_usage() == Module::CONTEXT) )
+ else if (m->get_usage() == Module::GLOBAL)
return "global";
+ else if (m->get_usage() == Module::CONTEXT)
+ return "network";
return "singleton";
}
cout << endl << "Type: " << mod_type(mh->api) << endl;
cout << endl << "Usage: " << mod_use(m->get_usage()) << endl;
- if ( mh->api and (mh->api->type == PT_INSPECTOR) )
+ if ( mh->api and mh->api->type == PT_INSPECTOR )
cout << endl << "Instance Type: " << mod_bind(m) << endl;
const Parameter* params = m->get_parameters();
// more modules support reload_module.
const vector<string> supported_modules =
{
- "dns_si", "firewall", "identity", "qos", "reputation", "url_si"
+ "dns_si", "firewall", "identity", "qos", "reputation", "url_si", "rt_network"
};
auto it = find(supported_modules.begin(), supported_modules.end(), name);
json.put("help", help);
json.put("type", type);
json.put("usage", usage);
- if ( mh->api and (mh->api->type == PT_INSPECTOR) )
+ if ( mh->api and mh->api->type == PT_INSPECTOR )
json.put("instance_type", mod_bind(mod));
dump_configs_json(json, mod);
#include "framework/connector.h"
#include "framework/logger.h"
#include "framework/mpse.h"
+#include "framework/policy_selector.h"
#include "helpers/directory.h"
#include "helpers/markup.h"
#include "log/messages.h"
#include "ips_manager.h"
#include "module_manager.h"
#include "mpse_manager.h"
+#include "policy_selector_manager.h"
#include "script_manager.h"
#include "so_manager.h"
{ "search_engine", SEAPI_VERSION, sizeof(MpseApi) },
{ "so_rule", SOAPI_VERSION, sizeof(SoApi) },
{ "logger", LOGAPI_VERSION, sizeof(LogApi) },
- { "connector", CONNECTOR_API_VERSION, sizeof(ConnectorApi) }
+ { "connector", CONNECTOR_API_VERSION, sizeof(ConnectorApi) },
+ { "policy_selector", POLICY_SELECTOR_API_VERSION, sizeof(PolicySelectorApi) },
#ifdef PIGLET
- ,
{ "piglet", PIGLET_API_VERSION, sizeof(Piglet::Api) }
#endif
};
[PT_IPS_OPTION] = { stringify(PT_IPS_OPTION), IPSAPI_VERSION, sizeof(IpsApi) },
[PT_SEARCH_ENGINE] = { stringify(PT_SEARCH_ENGINE), SEAPI_VERSION, sizeof(MpseApi) },
[PT_SO_RULE] = { stringify(PT_SO_RULE), SOAPI_VERSION, sizeof(SoApi) },
- [PT_LOGGER] = { stringify(PT_LOGGER), LOGAPI_VERSION, sizeof(LogApi) }
+ [PT_LOGGER] = { stringify(PT_LOGGER), LOGAPI_VERSION, sizeof(LogApi) },
+ [PT_CONNECTOR] = { stringify(PT_CONNECTOR), CONNECTOR_API_VERSION, sizeof(ConnectorApi) },
+ [PT_POLICY_SELECTOR] = { stringify(PT_POLICY_SELECTOR), POLICY_SELECTOR_API_VERSION,
+ sizeof(PolicySelectorApi) }
};
#endif
ConnectorManager::add_plugin((const ConnectorApi*)p.api);
break;
+ case PT_POLICY_SELECTOR:
+ PolicySelectorManager::add_plugin((const PolicySelectorApi*)p.api);
+ break;
+
#ifdef PIGLET
case PT_PIGLET:
Piglet::Manager::add_plugin((const Piglet::Api*)p.api);
ActionManager::dump_plugins();
EventManager::dump_plugins();
ConnectorManager::dump_plugins();
+ PolicySelectorManager::dump_plugins();
}
void PluginManager::release_plugins()
MpseManager::release_plugins();
CodecManager::release_plugins();
ConnectorManager::release_plugins();
+ PolicySelectorManager::release_plugins();
unload_plugins();
}
ConnectorManager::instantiate((const ConnectorApi*)api, mod, sc);
break;
+ case PT_POLICY_SELECTOR:
+ PolicySelectorManager::instantiate((const PolicySelectorApi*)api, mod, sc);
+ break;
+
case PT_SO_RULE:
// do not instantiate here; done later
//IpsManager::instantiate((SoApi*)api, mod, sc);
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// policy_selector_manager.cc author Ron Dempster <rdempste@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "policy_selector_manager.h"
+
+#include <cassert>
+#include <unordered_map>
+
+#include "framework/policy_selector.h"
+#include "framework/module.h"
+#include "main/snort_config.h"
+#include "log/messages.h"
+#include "utils/util.h"
+
+using namespace snort;
+
+static std::unordered_map<std::string, const PolicySelectorApi*> s_selectors;
+
+//-------------------------------------------------------------------------
+
+void PolicySelectorManager::add_plugin(const PolicySelectorApi* api)
+{
+ assert(s_selectors.find(api->base.name) == s_selectors.end());
+
+ s_selectors[api->base.name] = api;
+}
+
+void PolicySelectorManager::dump_plugins()
+{
+ Dumper d("Selectors");
+
+ for (auto& sc : s_selectors)
+ d.dump(sc.second->base.name, sc.second->base.version);
+}
+
+void PolicySelectorManager::release_plugins()
+{
+ s_selectors.clear();
+}
+
+void PolicySelectorManager::instantiate(const PolicySelectorApi* api, Module* mod, SnortConfig* sc)
+{
+ assert(sc);
+ if (sc->global_selector)
+ {
+ ParseError("Only one selector may be instantiated\n");
+ return;
+ }
+ assert(api);
+ sc->global_selector = api->ctor(mod);
+}
+
+void PolicySelectorManager::print_config(const SnortConfig* sc)
+{
+ assert(sc);
+ if (sc->global_selector)
+ {
+ LogLabel("Policy Selector");
+ std::string name = sc->global_selector->get_api()->base.name;
+ name += ":";
+ LogLabel(name.c_str());
+ sc->global_selector->show();
+ }
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// policy_selector_manager.h author Ron Dempster <rdempste@cisco.com>
+
+#ifndef POLICY_SELECTOR_MANAGER_H
+#define POLICY_SELECTOR_MANAGER_H
+
+// Policy selectors are used in a multi-tenant configuration to select all policies
+// based on layer 1 criteria. This is the manager for a given policy selector.
+// Only one selector is permitted in the configuration and it must be at the top level.
+
+namespace snort
+{
+struct PolicySelectorApi;
+class Module;
+struct SnortConfig;
+}
+
+//-------------------------------------------------------------------------
+
+class PolicySelectorManager
+{
+public:
+ static void add_plugin(const snort::PolicySelectorApi* api);
+ static void dump_plugins();
+ static void release_plugins();
+
+ static void instantiate(const snort::PolicySelectorApi*, snort::Module*, snort::SnortConfig*);
+ static void print_config(const snort::SnortConfig*);
+};
+
+#endif
+
ctxt->init_appid(sc, *this);
- DataBus::subscribe_global(SIP_EVENT_TYPE_SIP_DIALOG_KEY, new SipEventHandler(*this), sc);
+ DataBus::subscribe_network(SIP_EVENT_TYPE_SIP_DIALOG_KEY, new SipEventHandler(*this));
- DataBus::subscribe_global(HTTP_REQUEST_HEADER_EVENT_KEY, new HttpEventHandler(
- HttpEventHandler::REQUEST_EVENT, *this), sc);
+ DataBus::subscribe_network(HTTP_REQUEST_HEADER_EVENT_KEY, new HttpEventHandler(
+ HttpEventHandler::REQUEST_EVENT, *this));
- DataBus::subscribe_global(HTTP_RESPONSE_HEADER_EVENT_KEY, new HttpEventHandler(
- HttpEventHandler::RESPONSE_EVENT, *this), sc);
+ DataBus::subscribe_network(HTTP_RESPONSE_HEADER_EVENT_KEY, new HttpEventHandler(
+ HttpEventHandler::RESPONSE_EVENT, *this));
- DataBus::subscribe_global(HTTP2_REQUEST_BODY_EVENT_KEY, new AppIdHttp2ReqBodyEventHandler(),
- sc);
+ DataBus::subscribe_network(HTTP2_REQUEST_BODY_EVENT_KEY, new AppIdHttp2ReqBodyEventHandler());
- DataBus::subscribe_global(DATA_DECRYPT_EVENT, new DataDecryptEventHandler(), sc);
+ DataBus::subscribe_network(DATA_DECRYPT_EVENT, new DataDecryptEventHandler());
- DataBus::subscribe_global(DCERPC_EXP_SESSION_EVENT_KEY, new DceExpSsnEventHandler(), sc);
+ DataBus::subscribe_network(DCERPC_EXP_SESSION_EVENT_KEY, new DceExpSsnEventHandler());
- DataBus::subscribe_global(OPPORTUNISTIC_TLS_EVENT, new AppIdOpportunisticTlsEventHandler(), sc);
+ DataBus::subscribe_network(OPPORTUNISTIC_TLS_EVENT, new AppIdOpportunisticTlsEventHandler());
- DataBus::subscribe_global(EFP_PROCESS_EVENT, new AppIdEfpProcessEventHandler(), sc);
+ DataBus::subscribe_network(EFP_PROCESS_EVENT, new AppIdEfpProcessEventHandler());
return true;
}
static const PegInfo bind_pegs[] =
{
+ { CountType::SUM, "raw_packets", "raw packets evaluated" },
{ CountType::SUM, "new_flows", "new flows evaluated" },
{ CountType::SUM, "service_changes", "flow service changes evaluated" },
{ CountType::SUM, "assistant_inspectors", "flow assistant inspector requests handled" },
{ "addr_spaces", Parameter::PT_STRING, nullptr, nullptr,
"list of address space IDs" },
+ { "tenants", Parameter::PT_STRING, nullptr, nullptr,
+ "list of tenants" },
+
{ "role", Parameter::PT_ENUM, "client | server | any", "any",
"use the given configuration on one or any end of a session" },
{ "file", Parameter::PT_STRING, nullptr, nullptr,
"use configuration in given file" },
+ { "network_policy", Parameter::PT_STRING, nullptr, nullptr,
+ "use network policy from given file" },
+
{ "inspection_policy", Parameter::PT_STRING, nullptr, nullptr,
"use inspection policy from given file" },
};
template<typename T>
-static bool parse_int_set(const Value& v, unordered_set<T>& set)
+static bool parse_int_set(const snort::Value& v, std::unordered_set<T>& set)
{
- assert(v.get_type() == Value::VT_STR);
+ assert(v.get_type() == snort::Value::VT_STR);
set.clear();
- string pl = v.get_string();
+ std::string pl = v.get_string();
- stringstream ss(pl);
- ss >> setbase(0);
+ std::stringstream ss(pl);
+ ss >> std::setbase(0);
uint64_t n;
while ( ss >> n )
{
- if ( n > numeric_limits<T>::max() )
+ if ( n > static_cast<uint64_t>(std::numeric_limits<T>::max()) )
return false;
set.insert(n);
return false;
binding.when.add_criteria(BindWhen::Criteria::BWC_ADDR_SPACES);
}
+ else if ( v.is("tenants") )
+ {
+ if (!parse_int_set<uint32_t>(v, binding.when.tenants))
+ return false;
+ binding.when.add_criteria(BindWhen::Criteria::BWC_TENANTS);
+ }
else if ( v.is("role") )
binding.when.role = (BindWhen::Role)v.get_uint8();
if ( policy_type == FILE_KEY )
{
Shell* sh = new Shell(policy_filename.c_str());
- auto policies = sc->policy_map->add_shell(sh);
+ auto policies = sc->policy_map->add_shell(sh, false);
binding.use.inspection_index = policies->inspection->policy_id;
binding.use.ips_index = policies->ips->policy_id;
}
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-// bind_module.cc author Russ Combs <rucombs@cisco.com>
+// bind_module.h author Russ Combs <rucombs@cisco.com>
#ifndef BIND_MODULE_H
#define BIND_MODULE_H
struct BindStats
{
+ PegCount raw_packets;
PegCount new_flows;
PegCount service_changes;
PegCount assistant_inspectors;
#include "flow/flow.h"
#include "log/messages.h"
#include "managers/inspector_manager.h"
+#include "packet_io/active.h"
#include "profiler/profiler.h"
+#include "protocols/packet.h"
#include "pub_sub/assistant_gadget_event.h"
#include "stream/stream.h"
#include "stream/stream_splitter.h"
when += " addr_spaces = " + addr_spaces + ",";
}
+ if (bw.has_criteria(BindWhen::Criteria::BWC_TENANTS))
+ {
+ auto tenants = to_string<uint32_t>(bw.tenants);
+ when += " tenants = " + tenants + ",";
+ }
+
if (when.length() > 1)
when.pop_back();
bool update(const Binding&);
+ void apply_action(Packet*);
void apply_action(Flow&);
void apply_session(Flow&);
void apply_service(Flow&);
return false;
}
+void Stuff::apply_action(Packet* p)
+{
+ switch (action)
+ {
+ case BindUse::BA_RESET:
+ // disable all preproc analysis and detection for this packet
+ DetectionEngine::disable_all(p);
+ p->active->reset_session(p, true);
+ break;
+ case BindUse::BA_BLOCK:
+ // disable all preproc analysis and detection for this packet
+ DetectionEngine::disable_all(p);
+ p->active->block_session(p, true);
+ break;
+ case BindUse::BA_ALLOW:
+ p->active->trust_session(p, true);
+ break;
+ case BindUse::BA_INSPECT:
+ break;
+ default:
+ break;
+ }
+}
+
void Stuff::apply_action(Flow& flow)
{
switch (action)
void eval(Packet*) override { }
+ void handle_packet(const Packet*);
void handle_flow_setup(Flow&, bool standby = false);
void handle_flow_service_change(Flow&);
void handle_assistant_gadget(const char* service, Flow&);
private:
void get_policy_bindings(Flow&, const char* service);
+ void get_policy_bindings(Packet*);
void get_bindings(Flow&, Stuff&, const char* service = nullptr);
+ void get_bindings(Packet*, Stuff&);
void apply(Flow&, Stuff&);
void apply_assistant(Flow&, Stuff&, const char*);
Inspector* find_gadget(Flow&, Inspector*& data);
Inspector* default_ssn_inspectors[to_utype(PktType::MAX)]{};
};
+class NonFlowPacketHandler : public DataHandler
+{
+public:
+ NonFlowPacketHandler() : DataHandler(BIND_NAME)
+ { }
+
+ void handle(DataEvent& e, Flow*) override
+ {
+ Binder* binder = InspectorManager::get_binder();
+ if (binder)
+ binder->handle_packet(e.get_packet());
+ }
+};
+
class FlowStateSetupHandler : public DataHandler
{
public:
class StreamHANewFlowHandler : public DataHandler
{
public:
- StreamHANewFlowHandler() : DataHandler(BIND_NAME) { }
+ StreamHANewFlowHandler() : DataHandler(BIND_NAME)
+ { order = 100; }
void handle(DataEvent&, Flow* flow) override
{
default_ssn_inspectors[proto] = InspectorManager::get_inspector(name);
}
+ DataBus::subscribe(PKT_WITHOUT_FLOW_EVENT, new NonFlowPacketHandler());
DataBus::subscribe(FLOW_STATE_SETUP_EVENT, new FlowStateSetupHandler());
DataBus::subscribe(FLOW_SERVICE_CHANGE_EVENT, new FlowServiceChangeHandler());
DataBus::subscribe(STREAM_HA_NEW_FLOW_EVENT, new StreamHANewFlowHandler());
void Binder::show(const SnortConfig*) const
{
- std::once_flag b_once;
-
+ bool log_header = true;
for (const Binding& b : bindings)
{
- std::call_once(b_once, []{ ConfigLogger::log_option("bindings"); });
+ if (log_header)
+ {
+ ConfigLogger::log_option("bindings");
+ log_header = false;
+ }
auto bind_when = "{ when = " + to_string(b.when) + ",";
auto bind_use = "use = " + to_string(b.use) + " }";
ConfigLogger::log_list("", bind_use.c_str(), " ", true);
}
- std::once_flag pb_once;
-
+ log_header = true;
for (const Binding& b : policy_bindings)
{
- std::call_once(pb_once, []{ ConfigLogger::log_option("policy_bindings"); });
+ if (log_header)
+ {
+ ConfigLogger::log_option("policy_bindings");
+ log_header = false;
+ }
auto bind_when = "{ when = " + to_string(b.when) + ",";
auto bind_use = "use = " + to_string(b.use) + " }";
}
}
+void Binder::handle_packet(const Packet* pkt)
+{
+ Profile profile(bindPerfStats);
+
+ Stuff stuff;
+ Packet* p = const_cast<Packet*>(pkt);
+ get_bindings(p, stuff);
+ stuff.apply_action(p);
+
+ bstats.raw_packets++;
+ bstats.verdicts[stuff.action]++;
+}
+
void Binder::handle_flow_setup(Flow& flow, bool standby)
{
Profile profile(bindPerfStats);
}
}
+void Binder::get_policy_bindings(Packet* p)
+{
+ const SnortConfig* sc = SnortConfig::get_conf();
+ unsigned inspection_index = 0;
+ unsigned ips_index = 0;
+
+ // FIXIT-L This will select the first policy ID of each type that it finds and ignore the rest.
+ // It gets potentially hairy if people start specifying overlapping policy types in
+ // overlapping rules.
+ for (const Binding& b : policy_bindings)
+ {
+ // Skip any rules that don't contain an ID for a policy type we haven't set yet.
+ if ((!b.use.inspection_index || inspection_index) && (!b.use.ips_index || ips_index))
+ continue;
+
+ if (!b.check_all(p))
+ continue;
+
+ if (b.use.inspection_index && !inspection_index)
+ inspection_index = b.use.inspection_index;
+
+ if (b.use.ips_index && !ips_index)
+ ips_index = b.use.ips_index;
+ }
+
+ if (inspection_index)
+ {
+ set_inspection_policy(sc, inspection_index);
+ p->user_inspection_policy_id = get_inspection_policy()->user_policy_id;
+ }
+
+ if (ips_index)
+ {
+ set_ips_policy(sc, ips_index);
+ p->user_ips_policy_id = get_ips_policy()->user_policy_id;
+ }
+}
+
// FIXIT-P this is a simple linear search until functionality is nailed
// down. performance should be the focus of the next iteration.
void Binder::get_bindings(Flow& flow, Stuff& stuff, const char* service)
bstats.no_match++;
}
+void Binder::get_bindings(Packet* p, Stuff& stuff)
+{
+ // Evaluate policy ID bindings first
+ get_policy_bindings(p);
+
+ // If policy selection produced a new binder to use, use that instead.
+ Binder* sub = InspectorManager::get_binder();
+ if (sub && sub != this)
+ {
+ sub->get_bindings(p, stuff);
+ return;
+ }
+
+ // If we got here, that means that a sub-policy with a binder was not invoked.
+ // Continue using this binder for the rest of processing.
+
+ // Initialize the session inspector for both client and server to the default for this policy.
+ stuff.client = stuff.server = default_ssn_inspectors[to_utype(p->type())];
+
+ for (const Binding& b : bindings)
+ {
+ if (!b.check_all(p))
+ continue;
+
+ if (stuff.update(b))
+ return;
+ }
+
+ bstats.no_match++;
+}
+
Inspector* Binder::find_gadget(Flow& flow, Inspector*& data)
{
Stuff stuff;
#include "log/messages.h"
#include "main/snort_config.h"
#include "managers/inspector_manager.h"
+#include "protocols/packet.h"
using namespace snort;
return when.ips_id == flow.ips_policy_id;
}
+inline bool Binding::check_ips_policy() const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_IPS_ID))
+ return true;
+
+ return when.ips_id == get_ips_policy()->policy_id;
+}
+
inline bool Binding::check_vlan(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_VLANS))
return when.vlans.test(flow.key->vlan_tag);
}
+inline bool Binding::check_vlan(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_VLANS))
+ return true;
+
+ return when.vlans.test(p->get_flow_vlan_id());
+}
+
inline bool Binding::check_addr(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_NETS))
return false;
}
+inline bool Binding::check_addr(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_NETS))
+ return true;
+
+ switch (when.role)
+ {
+ case BindWhen::BR_SERVER:
+ if (sfvar_ip_in(when.src_nets, p->ptrs.ip_api.get_dst()))
+ return true;
+ break;
+
+ case BindWhen::BR_CLIENT:
+ if (sfvar_ip_in(when.src_nets, p->ptrs.ip_api.get_src()))
+ return true;
+ break;
+
+ case BindWhen::BR_EITHER:
+ if (sfvar_ip_in(when.src_nets, p->ptrs.ip_api.get_src()) ||
+ sfvar_ip_in(when.src_nets, p->ptrs.ip_api.get_dst()))
+ return true;
+ break;
+
+ default:
+ break;
+ }
+ return false;
+}
+
inline bool Binding::check_split_addr(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_SPLIT_NETS))
return true;
}
+inline bool Binding::check_split_addr(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_SPLIT_NETS))
+ return true;
+
+ if (when.src_nets && !sfvar_ip_in(when.src_nets, p->ptrs.ip_api.get_src()))
+ return false;
+
+ if (when.dst_nets && !sfvar_ip_in(when.dst_nets, p->ptrs.ip_api.get_dst()))
+ return false;
+
+ return true;
+}
+
inline bool Binding::check_proto(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_PROTO))
return (when.protos & proto_bit) != 0;
}
+inline bool Binding::check_proto(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_PROTO))
+ return true;
+
+ unsigned proto_bit = 1 << ((unsigned)p->type() - 1);
+ return (when.protos & proto_bit) != 0;
+}
+
inline bool Binding::check_port(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_PORTS))
return false;
}
+inline bool Binding::check_port(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_PORTS))
+ return true;
+
+ if (p->type() != PktType::TCP && p->type() != PktType::UDP)
+ return false;
+
+ switch (when.role)
+ {
+ case BindWhen::BR_SERVER:
+ if (when.src_ports.test(p->ptrs.dp))
+ return true;
+ break;
+
+ case BindWhen::BR_CLIENT:
+ if (when.src_ports.test(p->ptrs.sp))
+ return true;
+ break;
+
+ case BindWhen::BR_EITHER:
+ if (when.src_ports.test(p->ptrs.sp) ||
+ when.src_ports.test(p->ptrs.dp))
+ return true;
+ break;
+
+ default:
+ break;
+ }
+ return false;
+}
+
inline bool Binding::check_split_port(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_SPLIT_PORTS))
return true;
}
+inline bool Binding::check_split_port(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_SPLIT_PORTS))
+ return true;
+
+ if (p->type() != PktType::TCP && p->type() != PktType::UDP)
+ return false;
+
+ if (!when.src_ports.test(p->ptrs.sp))
+ return false;
+
+ if (!when.dst_ports.test(p->ptrs.dp))
+ return false;
+
+ return true;
+}
+
inline bool Binding::check_intf(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_INTFS))
return false;
}
+inline bool Binding::check_intf(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_INTFS))
+ return true;
+
+ switch (when.role)
+ {
+ case BindWhen::BR_SERVER:
+ if (when.src_intfs.count(p->pkth->egress_index))
+ return true;
+ break;
+
+ case BindWhen::BR_CLIENT:
+ if (when.src_intfs.count(p->pkth->ingress_index))
+ return true;
+ break;
+
+ case BindWhen::BR_EITHER:
+ if (when.src_intfs.count(p->pkth->ingress_index) ||
+ when.src_intfs.count(p->pkth->egress_index))
+ return true;
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
inline bool Binding::check_split_intf(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_SPLIT_INTFS))
return true;
}
+inline bool Binding::check_split_intf(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_SPLIT_INTFS))
+ return true;
+
+ if (!when.src_intfs.empty() && !when.src_intfs.count(p->pkth->ingress_index))
+ return false;
+
+ if (!when.dst_intfs.empty() && !when.dst_intfs.count(p->pkth->egress_index))
+ return false;
+
+ return true;
+}
+
inline bool Binding::check_group(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_GROUPS))
return false;
}
+inline bool Binding::check_group(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_GROUPS))
+ return true;
+
+ switch (when.role)
+ {
+ case BindWhen::BR_SERVER:
+ if (when.src_groups.count(p->pkth->egress_group))
+ return true;
+ break;
+
+ case BindWhen::BR_CLIENT:
+ if (when.src_groups.count(p->pkth->ingress_group))
+ return true;
+ break;
+
+ case BindWhen::BR_EITHER:
+ if (when.src_groups.count(p->pkth->ingress_group) ||
+ when.src_groups.count(p->pkth->egress_group))
+ return true;
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
inline bool Binding::check_split_group(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_SPLIT_GROUPS))
return true;
}
+inline bool Binding::check_split_group(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_SPLIT_GROUPS))
+ return true;
+
+ if (!when.src_groups.empty() && !when.src_groups.count(p->pkth->ingress_group))
+ return false;
+
+ if (!when.dst_groups.empty() && !when.dst_groups.count(p->pkth->egress_group))
+ return false;
+
+ return true;
+}
+
inline bool Binding::check_address_space(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_ADDR_SPACES))
return when.addr_spaces.count(flow.key->addressSpaceId) != 0;
}
+inline bool Binding::check_address_space(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_ADDR_SPACES))
+ return true;
+
+ return when.addr_spaces.count(p->pkth->address_space_id) != 0;
+}
+
+inline bool Binding::check_tenant(const Flow& flow) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_TENANTS))
+ return true;
+
+ return when.tenants.count(flow.tenant) != 0;
+}
+
+inline bool Binding::check_tenant(const Packet* p) const
+{
+ if (!when.has_criteria(BindWhen::Criteria::BWC_TENANTS))
+ return true;
+
+ return when.tenants.count(p->pkth->address_space_id) != 0;
+}
+
inline bool Binding::check_service(const Flow& flow) const
{
if (!when.has_criteria(BindWhen::Criteria::BWC_SVC))
return when.svc == service;
}
+inline bool Binding::check_service() const
+{
+ return when.has_criteria(BindWhen::Criteria::BWC_SVC) ? false : true;
+}
+
bool Binding::check_all(const Flow& flow, const char* service) const
{
// Do the service check first to optimize service change re-evaluations
if (!check_address_space(flow))
return false;
+ if (!check_tenant(flow))
+ return false;
+
+ return true;
+}
+
+bool Binding::check_all(const Packet* p) const
+{
+ if (!check_service())
+ return false;
+
+ if (!check_ips_policy())
+ return false;
+
+ if (!check_vlan(p))
+ return false;
+
+ if (!check_addr(p))
+ return false;
+
+ if (!check_split_addr(p))
+ return false;
+
+ if (!check_proto(p))
+ return false;
+
+ if (!check_port(p))
+ return false;
+
+ if (!check_split_port(p))
+ return false;
+
+ if (!check_intf(p))
+ return false;
+
+ if (!check_split_intf(p))
+ return false;
+
+ if (!check_group(p))
+ return false;
+
+ if (!check_split_group(p))
+ return false;
+
+ if (!check_address_space(p))
+ return false;
+
+ if (!check_tenant(p))
+ return false;
+
return true;
}
std::unordered_set<uint16_t> addr_spaces;
+ std::unordered_set<uint32_t> tenants;
+
enum Criteria
{
BWC_IPS_ID = 0x0001,
BWC_SPLIT_INTFS = 0x0200,
BWC_GROUPS = 0x0400,
BWC_SPLIT_GROUPS = 0x0800,
- BWC_ADDR_SPACES = 0x1000
+ BWC_ADDR_SPACES = 0x1000,
+ BWC_TENANTS = 0x2000
};
uint16_t criteria_flags;
void configure(const snort::SnortConfig* sc);
bool check_all(const snort::Flow&, const char* = nullptr) const;
+ bool check_all(const snort::Packet*) const;
bool check_ips_policy(const snort::Flow&) const;
+ bool check_ips_policy() const;
bool check_vlan(const snort::Flow&) const;
+ bool check_vlan(const snort::Packet*) const;
bool check_addr(const snort::Flow&) const;
+ bool check_addr(const snort::Packet*) const;
bool check_split_addr(const snort::Flow&) const;
+ bool check_split_addr(const snort::Packet*) const;
bool check_proto(const snort::Flow&) const;
+ bool check_proto(const snort::Packet*) const;
bool check_port(const snort::Flow&) const;
+ bool check_port(const snort::Packet*) const;
bool check_split_port(const snort::Flow&) const;
+ bool check_split_port(const snort::Packet*) const;
bool check_intf(const snort::Flow&) const;
+ bool check_intf(const snort::Packet*) const;
bool check_split_intf(const snort::Flow&) const;
+ bool check_split_intf(const snort::Packet*) const;
bool check_group(const snort::Flow&) const;
+ bool check_group(const snort::Packet*) const;
bool check_split_group(const snort::Flow&) const;
- bool check_address_space(const snort::Flow& flow) const;
+ bool check_split_group(const snort::Packet*) const;
+ bool check_address_space(const snort::Flow&) const;
+ bool check_address_space(const snort::Packet*) const;
+ bool check_tenant(const snort::Flow&) const;
+ bool check_tenant(const snort::Packet*) const;
bool check_service(const snort::Flow&) const;
bool check_service(const char* service) const;
+ bool check_service() const;
};
#endif
{ return &config; }
Usage get_usage() const override
- { return INSPECT; }
+ { return CONTEXT; }
private:
bool set_ip4(const char*, const snort::Value&, snort::SnortConfig*);
class PerfIdleHandler : public DataHandler
{
public:
- PerfIdleHandler(PerfMonitor& p, SnortConfig*& sc) : DataHandler(PERF_NAME), perf_monitor(p)
- { DataBus::subscribe_global(THREAD_IDLE_EVENT, this, sc); }
+ PerfIdleHandler(PerfMonitor& p) : DataHandler(PERF_NAME), perf_monitor(p)
+ { DataBus::subscribe_network(THREAD_IDLE_EVENT, this); }
void handle(DataEvent&, Flow*) override
{ perf_monitor.eval(nullptr); }
class PerfRotateHandler : public DataHandler
{
public:
- PerfRotateHandler(PerfMonitor& p, SnortConfig* sc) : DataHandler(PERF_NAME), perf_monitor(p)
- { DataBus::subscribe_global(THREAD_ROTATE_EVENT, this, sc); }
+ PerfRotateHandler(PerfMonitor& p) : DataHandler(PERF_NAME), perf_monitor(p)
+ { DataBus::subscribe_network(THREAD_ROTATE_EVENT, this); }
void handle(DataEvent&, Flow*) override
{ perf_monitor.rotate(); }
class FlowIPDataHandler : public DataHandler
{
public:
- FlowIPDataHandler(PerfMonitor& p, SnortConfig* sc) : DataHandler(PERF_NAME), perf_monitor(p)
- { DataBus::subscribe_global(FLOW_STATE_EVENT, this, sc); }
+ FlowIPDataHandler(PerfMonitor& p) : DataHandler(PERF_NAME), perf_monitor(p)
+ { DataBus::subscribe_network(FLOW_STATE_EVENT, this); }
void handle(DataEvent&, Flow* flow) override
{
// type and version fields immediately after timestamp like seconds, usec,
// type, version#, data1, data2, ...
-bool PerfMonitor::configure(SnortConfig* sc)
+bool PerfMonitor::configure(SnortConfig*)
{
- new PerfIdleHandler(*this, sc);
- new PerfRotateHandler(*this, sc);
- new FlowIPDataHandler(*this, sc);
+ new PerfIdleHandler(*this);
+ new PerfRotateHandler(*this);
+ new FlowIPDataHandler(*this);
return config->resolve();
}
++reputationstats.packets;
}
-bool Reputation::configure(SnortConfig* sc)
+bool Reputation::configure(SnortConfig*)
{
- DataBus::subscribe_global( AUXILIARY_IP_EVENT, new AuxiliaryIpRepHandler(config), sc );
+ DataBus::subscribe_network( AUXILIARY_IP_EVENT, new AuxiliaryIpRepHandler(config) );
return true;
}
ReputationConfig* get_data();
- Usage get_usage() const override
- { return GLOBAL; }
-
private:
ReputationConfig* conf;
};
bool RnaInspector::configure(SnortConfig* sc)
{
- DataBus::subscribe_global( APPID_EVENT_ANY_CHANGE, new RnaAppidEventHandler(*pnd), sc );
- DataBus::subscribe_global( DHCP_INFO_EVENT, new RnaDHCPInfoEventHandler(*pnd), sc);
- DataBus::subscribe_global( DHCP_DATA_EVENT, new RnaDHCPDataEventHandler(*pnd), sc);
- DataBus::subscribe_global( FP_SMB_DATA_EVENT, new RnaFpSMBEventHandler(*pnd), sc);
+ DataBus::subscribe_network( APPID_EVENT_ANY_CHANGE, new RnaAppidEventHandler(*pnd) );
+ DataBus::subscribe_network( DHCP_INFO_EVENT, new RnaDHCPInfoEventHandler(*pnd) );
+ DataBus::subscribe_network( DHCP_DATA_EVENT, new RnaDHCPDataEventHandler(*pnd) );
+ DataBus::subscribe_network( FP_SMB_DATA_EVENT, new RnaFpSMBEventHandler(*pnd) );
- DataBus::subscribe_global( STREAM_ICMP_NEW_FLOW_EVENT, new RnaIcmpNewFlowEventHandler(*pnd), sc );
- DataBus::subscribe_global( STREAM_ICMP_BIDIRECTIONAL_EVENT, new RnaIcmpBidirectionalEventHandler(*pnd), sc );
+ DataBus::subscribe_network( STREAM_ICMP_NEW_FLOW_EVENT, new RnaIcmpNewFlowEventHandler(*pnd) );
+ DataBus::subscribe_network( STREAM_ICMP_BIDIRECTIONAL_EVENT, new RnaIcmpBidirectionalEventHandler(*pnd) );
- DataBus::subscribe_global( STREAM_IP_NEW_FLOW_EVENT, new RnaIpNewFlowEventHandler(*pnd), sc );
- DataBus::subscribe_global( STREAM_IP_BIDIRECTIONAL_EVENT, new RnaIpBidirectionalEventHandler(*pnd), sc );
+ DataBus::subscribe_network( STREAM_IP_NEW_FLOW_EVENT, new RnaIpNewFlowEventHandler(*pnd) );
+ DataBus::subscribe_network( STREAM_IP_BIDIRECTIONAL_EVENT, new RnaIpBidirectionalEventHandler(*pnd) );
- DataBus::subscribe_global( STREAM_UDP_NEW_FLOW_EVENT, new RnaUdpNewFlowEventHandler(*pnd), sc );
- DataBus::subscribe_global( STREAM_UDP_BIDIRECTIONAL_EVENT, new RnaUdpBidirectionalEventHandler(*pnd), sc );
+ DataBus::subscribe_network( STREAM_UDP_NEW_FLOW_EVENT, new RnaUdpNewFlowEventHandler(*pnd) );
+ DataBus::subscribe_network( STREAM_UDP_BIDIRECTIONAL_EVENT, new RnaUdpBidirectionalEventHandler(*pnd) );
- DataBus::subscribe_global( STREAM_TCP_SYN_EVENT, new RnaTcpSynEventHandler(*pnd), sc );
- DataBus::subscribe_global( STREAM_TCP_SYN_ACK_EVENT, new RnaTcpSynAckEventHandler(*pnd), sc );
- DataBus::subscribe_global( STREAM_TCP_MIDSTREAM_EVENT, new RnaTcpMidstreamEventHandler(*pnd), sc );
- DataBus::subscribe_global( CPE_OS_INFO_EVENT, new RnaCPEOSInfoEventHandler(*pnd), sc );
+ DataBus::subscribe_network( STREAM_TCP_SYN_EVENT, new RnaTcpSynEventHandler(*pnd) );
+ DataBus::subscribe_network( STREAM_TCP_SYN_ACK_EVENT, new RnaTcpSynAckEventHandler(*pnd) );
+ DataBus::subscribe_network( STREAM_TCP_MIDSTREAM_EVENT, new RnaTcpMidstreamEventHandler(*pnd) );
+ DataBus::subscribe_network( CPE_OS_INFO_EVENT, new RnaCPEOSInfoEventHandler(*pnd) );
if (rna_conf && rna_conf->log_when_idle)
- DataBus::subscribe_global( THREAD_IDLE_EVENT, new RnaIdleEventHandler(*pnd), sc );
+ DataBus::subscribe_network( THREAD_IDLE_EVENT, new RnaIdleEventHandler(*pnd) );
// tinit is not called during reload, so pass processor pointers to threads via reload tuner
if ( Snort::is_reloading() && InspectorManager::get_inspector(RNA_NAME, true) )
{}
void LogMessage(const char*,...) {}
void WarningMessage(const char*,...) {}
-SnortConfig::SnortConfig(SnortConfig const*) {}
+SnortConfig::SnortConfig(const SnortConfig* const, const char*) {}
SnortConfig::~SnortConfig() = default;
time_t packet_time() { return 0; }
Flow::~Flow() = default;
IpsContext::IpsContext(unsigned int) { }
IpsContext::~IpsContext() = default;
-SnortConfig::SnortConfig(snort::SnortConfig const*) { }
+SnortConfig::SnortConfig(snort::SnortConfig const*, const char*) { }
SnortConfig::~SnortConfig() = default;
IpsContext ips_context;
--- /dev/null
+
+add_subdirectory(address_space_selector)
+add_subdirectory(tenant_selector)
+
+set(STATIC_POLICY_SELECTOR_PLUGINS
+ $<TARGET_OBJECTS:address_space_selector>
+ $<TARGET_OBJECTS:tenant_selector>
+ CACHE INTERNAL "STATIC_POLICY_SELECTOR_PLUGINS"
+)
+
+add_library( policy_selectors OBJECT
+ int_set_to_string.h
+ parse_int_set.h
+ policy_selectors.cc
+ policy_selectors.h
+)
--- /dev/null
+
+set(FILE_LIST
+ address_space_selection.cc
+ address_space_selection.h
+ address_space_selector.cc
+ address_space_selector_module.cc
+ address_space_selector_module.h
+)
+
+add_library(address_space_selector OBJECT ${FILE_LIST})
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// address_space_selection.cc author Ron Dempster <rdempste@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "address_space_selection.h"
+
+using namespace snort;
+
+AddressSpaceSelection::AddressSpaceSelection()
+{ clear(); }
+
+void AddressSpaceSelection::clear()
+{
+ addr_spaces.clear();
+
+ use.name.clear();
+ use.network_index = 0;
+ use.inspection_index = 0;
+ use.ips_index = 0;
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// address_space_selection.h author Ron Dempster <rdempste@cisco.com>
+
+#ifndef ADDRESS_SPACE_SELECTION_H
+#define ADDRESS_SPACE_SELECTION_H
+
+// Evaluation elements for selecting policies based on address space
+
+#include <vector>
+
+#include "framework/policy_selector.h"
+
+struct AddressSpaceSelection
+{
+ std::vector<uint32_t> addr_spaces;
+ snort::PolicySelectUse use;
+
+ AddressSpaceSelection();
+
+ void clear();
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// address_space_selector.cc author Ron Dempster <rdempste@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <algorithm>
+#include <unordered_map>
+#include <vector>
+
+#include "detection/ips_context.h"
+#include "framework/policy_selector.h"
+#include "log/messages.h"
+#include "policy_selectors/int_set_to_string.h"
+#include "profiler/profiler.h"
+
+#include "address_space_selector_module.h"
+#include "address_space_selection.h"
+
+using namespace snort;
+
+THREAD_LOCAL ProfileStats address_space_selectPerfStats;
+
+//-------------------------------------------------------------------------
+// helpers
+//-------------------------------------------------------------------------
+
+static std::string to_string(const std::vector<uint32_t>& as)
+{
+ std::string when;
+
+ if (!as.empty())
+ {
+ auto addr_spaces = int_set_to_string<uint32_t>(as);
+ when += "addr_spaces = " + addr_spaces;
+ }
+
+ return when;
+}
+
+//-------------------------------------------------------------------------
+// class stuff
+//-------------------------------------------------------------------------
+
+class AddressSpaceSelector : public PolicySelector
+{
+public:
+ AddressSpaceSelector(const PolicySelectorApi*, std::vector<AddressSpaceSelection>&);
+ ~AddressSpaceSelector() override;
+
+ void show() const override;
+
+ bool select_default_policies(const _daq_pkt_hdr*, const SnortConfig*) override;
+
+protected:
+ std::vector<AddressSpaceSelection> policy_selections;
+ std::unordered_map<uint32_t, snort::PolicySelectUse*> policy_map;
+};
+
+AddressSpaceSelector::AddressSpaceSelector(const PolicySelectorApi* api_in,
+ std::vector<AddressSpaceSelection>& psv) : PolicySelector(api_in)
+{
+ policy_selections = std::move(psv);
+ for (auto i = policy_selections.rbegin(); i != policy_selections.rend(); ++i)
+ {
+ std::sort((*i).addr_spaces.begin(), (*i).addr_spaces.end());
+ for(auto j = (*i).addr_spaces.begin(); j != (*i).addr_spaces.end(); ++j)
+ policy_map[*j] = &(*i).use;
+ }
+}
+
+AddressSpaceSelector::~AddressSpaceSelector()
+{
+ for (AddressSpaceSelection& s : policy_selections)
+ s.clear();
+}
+
+void AddressSpaceSelector::show() const
+{
+ bool log_header = true;
+ for (const AddressSpaceSelection& s : policy_selections)
+ {
+ if (log_header)
+ {
+ ConfigLogger::log_option("policy_selections");
+ log_header = false;
+ }
+
+ std::string select;
+ std::string when = to_string(s.addr_spaces);
+ if (when.empty())
+ select = "{ " + s.use.stringify() + " }";
+ else
+ select = "{ " + when + ", " + s.use.stringify() + " }";
+ ConfigLogger::log_list("", select.c_str(), " ");
+ }
+}
+
+bool AddressSpaceSelector::select_default_policies(const _daq_pkt_hdr* pkthdr, const SnortConfig* sc)
+{
+ Profile profile(address_space_selectPerfStats);
+
+ address_space_select_stats.packets++;
+
+ auto i = policy_map.find(static_cast<uint32_t>(pkthdr->address_space_id));
+ if (i != policy_map.end())
+ {
+ auto use = (*i).second;
+ set_network_policy(sc, use->network_index);
+ set_inspection_policy(sc, use->inspection_index);
+ set_ips_policy(sc, use->ips_index);
+ return true;
+ }
+ address_space_select_stats.no_match++;
+ return false;
+}
+
+//-------------------------------------------------------------------------
+// api stuff
+//-------------------------------------------------------------------------
+
+static Module* mod_ctor()
+{ return new AddressSpaceSelectorModule; }
+
+static void mod_dtor(Module* m)
+{ delete m; }
+
+static PolicySelector* address_space_select_ctor(Module*);
+static void address_space_select_dtor(PolicySelector*);
+
+static const PolicySelectorApi select_api =
+{
+ {
+ PT_POLICY_SELECTOR,
+ sizeof(PolicySelectorApi),
+ POLICY_SELECTOR_API_VERSION,
+ 0,
+ API_RESERVED,
+ API_OPTIONS,
+ ADDRESS_SPACE_SELECT_NAME,
+ ADDRESS_SPACE_SELECT_HELP,
+ mod_ctor,
+ mod_dtor
+ },
+ address_space_select_ctor,
+ address_space_select_dtor,
+};
+
+const BaseApi* ps_address_space_selector = &select_api.base;
+
+static PolicySelector* address_space_select_ctor(Module* m)
+{
+ AddressSpaceSelectorModule* mod = static_cast<AddressSpaceSelectorModule*>(m);
+ std::vector<AddressSpaceSelection>& psv = mod->get_policy_selections();
+ return new AddressSpaceSelector(&select_api, psv);
+}
+
+static void address_space_select_dtor(PolicySelector* p)
+{ delete p; }
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// address_space_selector_module.cc author Ron Dempster <rdempste@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "address_space_selector_module.h"
+
+#include "log/messages.h"
+#include "main/shell.h"
+#include "main/snort_config.h"
+#include "managers/module_manager.h"
+#include "policy_selectors/parse_int_set.h"
+
+using namespace snort;
+using namespace std;
+
+THREAD_LOCAL PolicySelectStats address_space_select_stats;
+
+static const PegInfo select_pegs[] =
+{
+ { CountType::SUM, "packets", "packets evaluated" },
+ { CountType::SUM, "no_match", "selection evaluations that had no matches" },
+ { CountType::END, nullptr, nullptr }
+};
+
+//-------------------------------------------------------------------------
+// selector module
+//-------------------------------------------------------------------------
+
+static const Parameter selector_when_params[] =
+{
+ { "addr_spaces", Parameter::PT_STRING, nullptr, nullptr,
+ "list of address space IDs" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+static const Parameter selector_use_params[] =
+{
+ { "file", Parameter::PT_STRING, nullptr, nullptr,
+ "use configuration in given file" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+static const Parameter s_params[] =
+{
+ { "addr_spaces", Parameter::PT_STRING, nullptr, nullptr,
+ "list of address space IDs to match" },
+
+ { "file", Parameter::PT_STRING, nullptr, nullptr,
+ "use configuration in given file" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+AddressSpaceSelectorModule::AddressSpaceSelectorModule() : Module(ADDRESS_SPACE_SELECT_NAME, ADDRESS_SPACE_SELECT_HELP, s_params, true)
+{ }
+
+AddressSpaceSelectorModule::~AddressSpaceSelectorModule()
+{
+ policy_selections.clear();
+ selection.clear();
+}
+
+ProfileStats* AddressSpaceSelectorModule::get_profile() const
+{ return &address_space_selectPerfStats; }
+
+void AddressSpaceSelectorModule::add_policy_file(const char* name)
+{ policy_filename = name; }
+
+bool AddressSpaceSelectorModule::begin(const char* fqn, int idx, SnortConfig*)
+{
+ if ( idx && !strcmp(fqn, ADDRESS_SPACE_SELECT_NAME) )
+ {
+ selection.clear();
+ policy_filename.clear();
+ }
+
+ return true;
+}
+
+bool AddressSpaceSelectorModule::set(const char*, Value& v, SnortConfig*)
+{
+ if ( v.is("addr_spaces") )
+ {
+ if (!parse_int_set<uint32_t>(v, selection.addr_spaces))
+ return false;
+ }
+
+ // use
+ else if ( v.is("file") )
+ add_policy_file(v.get_string());
+
+ return true;
+}
+
+bool AddressSpaceSelectorModule::end(const char* fqn, int idx, SnortConfig* sc)
+{
+ if ( !strcmp(fqn, ADDRESS_SPACE_SELECT_NAME) && idx )
+ {
+ // Use validation
+ if ( policy_filename.empty() )
+ {
+ ParseError("Missing policy file name");
+ return false;
+ }
+
+ Shell* sh = new Shell(policy_filename.c_str());
+ auto policies = sc->policy_map->add_shell(sh, true);
+ selection.use.network_index = policies->network->policy_id;
+ selection.use.inspection_index = policies->inspection->policy_id;
+ selection.use.ips_index = policies->ips->policy_id;
+
+ // Store the policy filename for verbose output
+ selection.use.name = policy_filename;
+
+ commit_policy_selection();
+ }
+ return true;
+}
+
+void AddressSpaceSelectorModule::commit_policy_selection()
+{ policy_selections.emplace_back(selection); }
+
+vector<AddressSpaceSelection>& AddressSpaceSelectorModule::get_policy_selections()
+{ return policy_selections; }
+
+const PegInfo* AddressSpaceSelectorModule::get_pegs() const
+{ return select_pegs; }
+
+PegCount* AddressSpaceSelectorModule::get_counts() const
+{ return (PegCount*)&address_space_select_stats; }
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// address_space_selector_module.h author Ron Dempster <rdempste@cisco.com>
+
+#ifndef ADDRESS_SPACE_SELECTOR_MODULE_H
+#define ADDRESS_SPACE_SELECTOR_MODULE_H
+
+// address space selector management interface
+
+#include "framework/module.h"
+#include "framework/policy_selector.h"
+#include "address_space_selection.h"
+
+#define ADDRESS_SPACE_SELECT_NAME "address_space_selector"
+#define ADDRESS_SPACE_SELECT_HELP "configure traffic processing based on address space"
+
+extern THREAD_LOCAL snort::PolicySelectStats address_space_select_stats;
+extern THREAD_LOCAL snort::ProfileStats address_space_selectPerfStats;
+
+class AddressSpaceSelectorModule : public snort::Module
+{
+public:
+ AddressSpaceSelectorModule();
+ ~AddressSpaceSelectorModule() override;
+
+ bool set(const char*, snort::Value&, snort::SnortConfig*) override;
+ bool begin(const char*, int, snort::SnortConfig*) override;
+ bool end(const char*, int, snort::SnortConfig*) override;
+
+ const PegInfo* get_pegs() const override;
+ PegCount* get_counts() const override;
+ snort::ProfileStats* get_profile() const override;
+
+ std::vector<AddressSpaceSelection>& get_policy_selections();
+
+ Usage get_usage() const override
+ { return GLOBAL; }
+
+private:
+ AddressSpaceSelection selection;
+ std::vector<AddressSpaceSelection> policy_selections;
+ std::string policy_filename;
+
+ void add_policy_file(const char* name);
+ void commit_policy_selection();
+};
+
+#endif
+
--- /dev/null
+The address space selector maps configuration to a packet based on the address space
+ID in the packet header.
+
+AddressSpaceSelectorModule creates a vector of AddressSpaceSelections from the Lua
+selector table which is moved to the AddressSpaceSelector upon its construction. The
+PolicySelectUse portion of the AddressSpaceSelections is added to a policy map that
+is keyed with the tenant IDs. For each default policy selection, the policy map is
+queried for a match given the address space ID. The match selects the following
+policies:
+
+* network policy
+* inspection policy
+* IPS policy
+
--- /dev/null
+A set of policy selectors to select the default policies in a multi-tenant
+environment. The selectors can only use constraints that are known before
+packet decode, such as address space ID, interfaces, tenants, etc.
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// int_set_to_string.h author Ron Dempster <rdempste@cisco.com>
+
+#ifndef INT_SET_TO_STRING_H
+#define INT_SET_TO_STRING_H
+
+// used to format configuration for output in show methods
+
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <vector>
+
+template <typename T>
+static std::string int_set_to_string(const std::vector<T>& v)
+{
+ if (v.empty())
+ return "";
+
+ std::stringstream ss;
+ for (auto e : v)
+ ss << e << " ";
+
+ auto str = ss.str();
+ if (!str.empty())
+ str.pop_back();
+
+ return str;
+}
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// parse_int_set.h author Ron Dempster <rdempste@cisco.com>
+
+#ifndef PARSE_INT_SET_H
+#define PARSE_INT_SET_H
+
+// used to parse an int set
+
+#include <cstdint>
+#include <iomanip>
+#include <limits>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "framework/value.h"
+
+template<typename T>
+static bool parse_int_set(const snort::Value& v, std::vector<T>& set)
+{
+ assert(v.get_type() == snort::Value::VT_STR);
+
+ set.clear();
+
+ std::string pl = v.get_string();
+
+ std::stringstream ss(pl);
+ ss >> std::setbase(0);
+
+ int64_t n;
+
+ while ( ss >> n )
+ {
+ if ( n > std::numeric_limits<T>::max() )
+ return false;
+
+ set.emplace_back(n);
+ }
+ if ( !ss.eof() )
+ return false;
+
+ return true;
+}
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+#include "policy_selectors.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "managers/plugin_manager.h"
+
+using namespace snort;
+
+extern const BaseApi* ps_address_space_selector;
+extern const BaseApi* ps_tenant_selector;
+
+static const BaseApi* policy_selectors[] =
+{
+ ps_address_space_selector,
+ ps_tenant_selector,
+ nullptr
+};
+
+void load_policy_selectors()
+{
+ PluginManager::load_plugins(policy_selectors);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+#ifndef POLICY_SELECTORS_H
+#define POLICY_SELECTORS_H
+
+void load_policy_selectors();
+
+#endif
+
--- /dev/null
+
+set(FILE_LIST
+ tenant_selection.cc
+ tenant_selection.h
+ tenant_selector.cc
+ tenant_selector_module.cc
+ tenant_selector_module.h
+)
+
+add_library(tenant_selector OBJECT ${FILE_LIST})
+
--- /dev/null
+The tenant selector maps configuration to a packet based on the tenant ID in the packet
+header.
+
+TenantSelectorModule creates a vector of TenantSelections from the Lua selector table which
+is moved to the TenantSelector upon its construction. The PolicySelectUse portion of the
+TenantSelections is added to a policy map that is keyed with the tenant IDs. For each
+default policy selection, the policy map is queried for a match given the tenant ID.
+The match selects the following policies:
+
+* network policy
+* inspection policy
+* IPS policy
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// tenant_selection.cc author Ron Dempster <rdempste@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tenant_selection.h"
+
+using namespace snort;
+
+TenantSelection::TenantSelection()
+{ clear(); }
+
+void TenantSelection::clear()
+{
+ tenants.clear();
+
+ use.name.clear();
+ use.network_index = 0;
+ use.inspection_index = 0;
+ use.ips_index = 0;
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// tenant_selection.h author Ron Dempster <rdempste@cisco.com>
+
+#ifndef TENANT_SELECTION_H
+#define TENANT_SELECTION_H
+
+// Evaluation elements for selecting policies based on tenant
+
+#include <vector>
+
+#include "framework/policy_selector.h"
+
+struct TenantSelection
+{
+ std::vector<uint32_t> tenants;
+ snort::PolicySelectUse use;
+
+ TenantSelection();
+
+ void clear();
+};
+
+#endif
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// selector.cc author Ron Dempster <rdempste@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <algorithm>
+#include <unordered_map>
+#include <vector>
+
+#include "detection/ips_context.h"
+#include "framework/policy_selector.h"
+#include "log/messages.h"
+#include "policy_selectors/int_set_to_string.h"
+#include "profiler/profiler.h"
+
+#include "tenant_selector_module.h"
+#include "tenant_selection.h"
+
+using namespace snort;
+
+THREAD_LOCAL ProfileStats tenant_select_perf_stats;
+
+//-------------------------------------------------------------------------
+// helpers
+//-------------------------------------------------------------------------
+
+static std::string to_string(const std::vector<uint32_t>& t)
+{
+ std::string when;
+
+ if (!t.empty())
+ {
+ auto tenants = int_set_to_string<uint32_t>(t);
+ when += "tenants = " + tenants;
+ }
+
+ return when;
+}
+
+//-------------------------------------------------------------------------
+// class stuff
+//-------------------------------------------------------------------------
+
+class TenantSelector : public PolicySelector
+{
+public:
+ TenantSelector(const PolicySelectorApi*, std::vector<TenantSelection>&);
+ ~TenantSelector() override;
+
+ void show() const override;
+
+ bool select_default_policies(const _daq_pkt_hdr*, const SnortConfig*) override;
+
+protected:
+ std::vector<TenantSelection> policy_selections;
+ std::unordered_map<uint32_t, snort::PolicySelectUse*> policy_map;
+};
+
+TenantSelector::TenantSelector(const PolicySelectorApi* api_in, std::vector<TenantSelection>& psv)
+ : PolicySelector(api_in)
+{
+ policy_selections = std::move(psv);
+ for (auto i = policy_selections.rbegin(); i != policy_selections.rend(); ++i)
+ {
+ std::sort((*i).tenants.begin(), (*i).tenants.end());
+ for(auto j = (*i).tenants.begin(); j != (*i).tenants.end(); ++j)
+ policy_map[*j] = &(*i).use;
+ }
+}
+
+TenantSelector::~TenantSelector()
+{
+ for (TenantSelection& s : policy_selections)
+ s.clear();
+}
+
+void TenantSelector::show() const
+{
+ bool log_header = true;
+ for (const TenantSelection& s : policy_selections)
+ {
+ if (log_header)
+ {
+ ConfigLogger::log_option("policy_selections");
+ log_header = false;
+ }
+
+ std::string select;
+ std::string when = to_string(s.tenants);
+ if (when.empty())
+ select = "{ " + s.use.stringify() + " }";
+ else
+ select = "{ " + when + ", " + s.use.stringify() + " }";
+ ConfigLogger::log_list("", select.c_str(), " ");
+ }
+}
+
+bool TenantSelector::select_default_policies(const _daq_pkt_hdr* pkthdr, const SnortConfig* sc)
+{
+ Profile profile(tenant_select_perf_stats);
+
+ tenant_select_stats.packets++;
+
+ // FIXIT-H replace address_space_id with tenant_id when it is added to the pkthdr
+ auto i = policy_map.find(static_cast<uint32_t>(pkthdr->address_space_id));
+ if (i != policy_map.end())
+ {
+ auto use = (*i).second;
+ set_network_policy(sc, use->network_index);
+ set_inspection_policy(sc, use->inspection_index);
+ set_ips_policy(sc, use->ips_index);
+ return true;
+ }
+ tenant_select_stats.no_match++;
+ return false;
+}
+
+//-------------------------------------------------------------------------
+// api stuff
+//-------------------------------------------------------------------------
+
+static Module* mod_ctor()
+{ return new TenantSelectorModule; }
+
+static void mod_dtor(Module* m)
+{ delete m; }
+
+static PolicySelector* tenant_select_ctor(Module*);
+
+static void tenant_select_dtor(PolicySelector* p)
+{ delete p; }
+
+
+static const PolicySelectorApi select_api =
+{
+ {
+ PT_POLICY_SELECTOR,
+ sizeof(PolicySelectorApi),
+ POLICY_SELECTOR_API_VERSION,
+ 0,
+ API_RESERVED,
+ API_OPTIONS,
+ TENANT_SELECT_NAME,
+ TENANT_SELECT_HELP,
+ mod_ctor,
+ mod_dtor
+ },
+ tenant_select_ctor,
+ tenant_select_dtor,
+};
+
+const BaseApi* ps_tenant_selector = &select_api.base;
+
+static PolicySelector* tenant_select_ctor(Module* m)
+{
+ TenantSelectorModule* mod = static_cast<TenantSelectorModule*>(m);
+ std::vector<TenantSelection>& psv = mod->get_policy_selections();
+ return new TenantSelector(&select_api, psv);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// selector_module.cc author Ron Dempster <rdempste@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tenant_selector_module.h"
+
+#include "framework/module.h"
+#include "log/messages.h"
+#include "main/shell.h"
+#include "main/snort_config.h"
+#include "policy_selectors/parse_int_set.h"
+
+using namespace snort;
+using namespace std;
+
+THREAD_LOCAL PolicySelectStats tenant_select_stats;
+
+static const PegInfo select_pegs[] =
+{
+ { CountType::SUM, "packets", "packets evaluated" },
+ { CountType::SUM, "no_match", "selection evaluations that had no matches" },
+ { CountType::END, nullptr, nullptr }
+};
+
+//-------------------------------------------------------------------------
+// selector module
+//-------------------------------------------------------------------------
+
+static const Parameter s_params[] =
+{
+ { "tenants", Parameter::PT_STRING, nullptr, nullptr,
+ "list of tenants to match" },
+
+ { "file", Parameter::PT_STRING, nullptr, nullptr,
+ "use configuration in given file" },
+
+ { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
+TenantSelectorModule::TenantSelectorModule()
+ : Module(TENANT_SELECT_NAME, TENANT_SELECT_HELP, s_params, true)
+{ }
+
+TenantSelectorModule::~TenantSelectorModule()
+{
+ policy_selections.clear();
+ selection.clear();
+}
+
+ProfileStats* TenantSelectorModule::get_profile() const
+{ return &tenant_select_perf_stats; }
+
+void TenantSelectorModule::add_policy_file(const char* name)
+{ policy_filename = name; }
+
+bool TenantSelectorModule::begin(const char* fqn, int idx, SnortConfig*)
+{
+ if ( idx && !strcmp(fqn, TENANT_SELECT_NAME) )
+ {
+ selection.clear();
+ policy_filename.clear();
+ }
+
+ return true;
+}
+
+bool TenantSelectorModule::set(const char*, Value& v, SnortConfig*)
+{
+ if ( v.is("tenants") )
+ {
+ if (!parse_int_set<uint32_t>(v, selection.tenants))
+ return false;
+ }
+
+ // use
+ else if ( v.is("file") )
+ add_policy_file(v.get_string());
+
+ return true;
+}
+
+bool TenantSelectorModule::end(const char* fqn, int idx, SnortConfig* sc)
+{
+ if ( !strcmp(fqn, TENANT_SELECT_NAME) && idx )
+ {
+ // Use validation
+ if ( policy_filename.empty() )
+ {
+ ParseError("Missing policy file name");
+ return false;
+ }
+
+ Shell* sh = new Shell(policy_filename.c_str());
+ auto policies = sc->policy_map->add_shell(sh, true);
+ selection.use.network_index = policies->network->policy_id;
+ selection.use.inspection_index = policies->inspection->policy_id;
+ selection.use.ips_index = policies->ips->policy_id;
+
+ // Store the policy filename for verbose output
+ selection.use.name = policy_filename;
+
+ commit_policy_selection();
+ }
+ return true;
+}
+
+void TenantSelectorModule::commit_policy_selection()
+{ policy_selections.emplace_back(selection); }
+
+vector<TenantSelection>& TenantSelectorModule::get_policy_selections()
+{ return policy_selections; }
+
+const PegInfo* TenantSelectorModule::get_pegs() const
+{ return select_pegs; }
+
+PegCount* TenantSelectorModule::get_counts() const
+{ return (PegCount*)&tenant_select_stats; }
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// tenant_selector_module.h author Ron Dempster <rdempste@cisco.com>
+
+#ifndef TENANT_SELECTOR_MODULE_H
+#define TENANT_SELECTOR_MODULE_H
+
+// tenant selector management interface
+
+#include <string>
+#include <vector>
+
+#include "framework/module.h"
+#include "tenant_selection.h"
+
+#define TENANT_SELECT_NAME "tenant_selector"
+#define TENANT_SELECT_HELP "configure traffic processing based on tenants"
+
+extern THREAD_LOCAL snort::PolicySelectStats tenant_select_stats;
+extern THREAD_LOCAL snort::ProfileStats tenant_select_perf_stats;
+
+class TenantSelectorModule : public snort::Module
+{
+public:
+ TenantSelectorModule();
+ ~TenantSelectorModule() override;
+
+ bool set(const char*, snort::Value&, snort::SnortConfig*) override;
+ bool begin(const char*, int, snort::SnortConfig*) override;
+ bool end(const char*, int, snort::SnortConfig*) override;
+
+ const PegInfo* get_pegs() const override;
+ PegCount* get_counts() const override;
+ snort::ProfileStats* get_profile() const override;
+
+ std::vector<TenantSelection>& get_policy_selections();
+
+ Usage get_usage() const override
+ { return GLOBAL; }
+
+private:
+ TenantSelection selection;
+ std::vector<TenantSelection> policy_selections;
+ std::string policy_filename;
+
+ void add_policy_file(const char* name);
+ void commit_policy_selection();
+};
+
+#endif
+
#include "main/snort_types.h"
#include "target_based/snort_protocols.h"
+// Event that is generated when a packet without a flow is processed
+#define PKT_WITHOUT_FLOW_EVENT "non_flow_pkt"
namespace snort
{
static std::vector<void *> s_state;
static ScratchAllocator* scratcher = nullptr;
-SnortConfig::SnortConfig(const SnortConfig* const)
+SnortConfig::SnortConfig(const SnortConfig* const, const char*)
{
state = &s_state;
num_slots = 1;
static std::vector<void *> s_state;
-SnortConfig::SnortConfig(const SnortConfig* const)
+SnortConfig::SnortConfig(const SnortConfig* const, const char*)
{
state = &s_state;
num_slots = 1;
{
ConfigLogger::log_value("dump_file", config->dump_file);
ConfigLogger::log_value("update_timeout", config->update_timeout);
- std::once_flag d_once;
+ bool log_header = true;
for ( auto const& d : config->device_rule_map )
{
- std::call_once(d_once, []{ ConfigLogger::log_option("rules"); });
+ if (log_header)
+ {
+ ConfigLogger::log_option("rules");
+ log_header = false;
+ }
SfIpString addr_str;
d.first.ntop(addr_str);
for( auto const& r : d.second.exclude )
for (auto elem : keys)
{
+ NetflowSessionRecord& record = cache[elem];
str = "Netflow Record #";
str += std::to_string(++i);
str += "\n";
str += " Initiator IP (Port): ";
str += elem.ntop(ip_str);
- str += " (" + std::to_string(cache[elem].initiator_port) + ")";
+ str += " (" + std::to_string(record.initiator_port) + ")";
str += " -> Responder IP (Port): ";
- str += cache[elem].responder_ip.ntop(ip_str);
- str += " (" + std::to_string(cache[elem].responder_port) + ")";
+ str += record.responder_ip.ntop(ip_str);
+ str += " (" + std::to_string(record.responder_port) + ")";
str += "\n";
str += " Protocol: ";
- str += std::to_string(cache[elem].proto);
+ str += std::to_string(record.proto);
str += " Packets: ";
- str += std::to_string(cache[elem].initiator_pkts);
+ str += std::to_string(record.initiator_pkts);
str += "\n";
str += " Source Mask: ";
- str += std::to_string(cache[elem].nf_src_mask);
+ str += std::to_string(record.nf_src_mask);
str += " Destination Mask: ";
- str += std::to_string(cache[elem].nf_dst_mask);
+ str += std::to_string(record.nf_dst_mask);
str += "\n";
str += " Next Hop IP: ";
- str += cache[elem].next_hop_ip.ntop(ip_str);
+ str += record.next_hop_ip.ntop(ip_str);
str += "\n";
str += "------\n";
return false;
}
-// FIXIT-L: when comparing ip4 vs ip6 we have !(ip4 < ip6) and !(ip6 < ip4).
-// This may be OK in some cases, but will not work e.g. on a binary tree
-// (stl::map) with SfIp as keys, whose implementation relies only on "<".
-// This affects SfIp::less_than() and SfIp::greater_than().
inline bool SfIp::_is_lesser(const SfIp& rhs) const
{
- if (is_ip4())
- {
- return (rhs.is_ip4() &&
- (htonl(ip32[3]) < htonl(rhs.ip32[3])));
- }
- else if (is_ip6())
- {
- return (rhs.is_ip6() &&
- (htonl(ip32[0]) < htonl(rhs.ip32[0])) &&
- (htonl(ip32[1]) < htonl(rhs.ip32[1])) &&
- (htonl(ip32[2]) < htonl(rhs.ip32[2])) &&
- (htonl(ip32[3]) < htonl(rhs.ip32[3])));
- }
- return false;
+ if (is_ip4() && rhs.is_ip4())
+ return ntohl(ip32[3]) < ntohl(rhs.ip32[3]);
+ uint32_t a = ntohl(ip32[0]);
+ uint32_t b = ntohl(rhs.ip32[0]);
+ if (a != b)
+ return a < b;
+ a = ntohl(ip32[1]);
+ b = ntohl(rhs.ip32[1]);
+ if (a != b)
+ return a < b;
+ a = ntohl(ip32[2]);
+ b = ntohl(rhs.ip32[2]);
+ if (a != b)
+ return a < b;
+ a = ntohl(ip32[3]);
+ b = ntohl(rhs.ip32[3]);
+ return a < b;
}
inline bool SfIp::equals(const SfIp& rhs, bool match_unset) const
const SnortConfig* sc = SnortConfig::get_conf();
set_inspection_policy(sc, flow->inspection_policy_id);
set_ips_policy(sc, flow->ips_policy_id);
- set_network_policy(sc, flow->network_policy_id);
return p;
}