// this is the current version of the base api
// must be prefixed to subtype version
-#define BASE_API_VERSION 6
+#define BASE_API_VERSION 7
// set options to API_OPTIONS to ensure compatibility
#ifndef API_OPTIONS
#include "config.h"
#endif
+#include <algorithm>
+
#include "data_bus.h"
#include "main/policy.h"
// private methods
//--------------------------------------------------------------------------
+static bool compare(DataHandler* a, DataHandler* b)
+{
+ if ( a->order and b->order )
+ return a->order < b->order;
+
+ if ( a->order )
+ return true;
+
+ return false;
+}
+
void DataBus::_subscribe(const char* key, DataHandler* h)
{
DataList& v = map[key];
v.emplace_back(h);
+ std::sort(v.begin(), v.end(), compare);
}
void DataBus::_unsubscribe(const char* key, DataHandler* h)
const char* module_name;
bool cloned;
+ // order is desired position in the call sequence of handlers: 1 = first, 0 = last
+ // the sequence among subscribers with the same order is not specified
+ unsigned order = 0;
+
protected:
DataHandler(std::nullptr_t) = delete;
DataHandler(const char* mod_name) : module_name(mod_name), cloned(false) { }
class UTestHandler : public DataHandler
{
public:
- UTestHandler() : DataHandler("unit_test")
- { }
+ UTestHandler(unsigned u = 0) : DataHandler("unit_test")
+ { if ( u ) order = u; }
void handle(DataEvent&, Flow*) override;
int evt_msg = 0;
+ unsigned seq = 99;
};
+static unsigned s_next = 0;
+
void UTestHandler::handle(DataEvent& event, Flow*)
{
UTestEvent* evt = (UTestEvent*)&event;
evt_msg = evt->get_message();
+ seq = ++s_next;
}
+
#define DB_UTEST_EVENT "unit.test.event"
//--------------------------------------------------------------------------
delete h;
}
+TEST(data_bus, order1)
+{
+ UTestHandler* h0 = new UTestHandler();
+ DataBus::subscribe(DB_UTEST_EVENT, h0);
+
+ UTestHandler* h1 = new UTestHandler(1);
+ DataBus::subscribe(DB_UTEST_EVENT, h1);
+
+ UTestHandler* h9 = new UTestHandler(9);
+ DataBus::subscribe(DB_UTEST_EVENT, h9);
+
+ s_next = 0;
+ UTestEvent event(100);
+ DataBus::publish(DB_UTEST_EVENT, event);
+
+ CHECK(1 == h1->seq);
+ CHECK(2 == h9->seq);
+ CHECK(3 == h0->seq);
+
+ DataBus::unsubscribe(DB_UTEST_EVENT, h0);
+ DataBus::unsubscribe(DB_UTEST_EVENT, h1);
+ DataBus::unsubscribe(DB_UTEST_EVENT, h9);
+
+ delete h0;
+ delete h1;
+ delete h9;
+}
+
+TEST(data_bus, order2)
+{
+ UTestHandler* h0 = new UTestHandler(0);
+ DataBus::subscribe(DB_UTEST_EVENT, h0);
+
+ UTestHandler* h9 = new UTestHandler(9);
+ DataBus::subscribe(DB_UTEST_EVENT, h9);
+
+ UTestHandler* h1 = new UTestHandler(1);
+ DataBus::subscribe(DB_UTEST_EVENT, h1);
+
+ s_next = 0;
+ UTestEvent event(100);
+ DataBus::publish(DB_UTEST_EVENT, event);
+
+ CHECK(1 == h1->seq);
+ CHECK(2 == h9->seq);
+ CHECK(3 == h0->seq);
+
+ DataBus::unsubscribe(DB_UTEST_EVENT, h0);
+ DataBus::unsubscribe(DB_UTEST_EVENT, h1);
+ DataBus::unsubscribe(DB_UTEST_EVENT, h9);
+
+ delete h0;
+ delete h1;
+ delete h9;
+}
+
//-------------------------------------------------------------------------
// main
//-------------------------------------------------------------------------
IpsPolicy* get_ips_policy()
{ return s_detection_policy; }
-IpsPolicy* get_ips_policy(const SnortConfig* sc, unsigned i)
+void set_network_policy(NetworkPolicy* p)
+{ s_traffic_policy = p; }
+
+void set_inspection_policy(InspectionPolicy* p)
+{ s_inspection_policy = p; }
+
+void set_ips_policy(IpsPolicy* p)
+{ s_detection_policy = p; }
+
+NetworkPolicy* get_user_network_policy(const SnortConfig* sc, unsigned policy_id)
{
- return sc && i < sc->policy_map->ips_policy_count() ?
- sc->policy_map->get_ips_policy(i) : nullptr;
+ 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);
}
InspectionPolicy* get_default_inspection_policy(const SnortConfig* sc)
{ return sc->policy_map->get_inspection_policy(0); }
-void set_ips_policy(IpsPolicy* p)
-{ s_detection_policy = p; }
-
-void set_network_policy(NetworkPolicy* p)
-{ s_traffic_policy = p; }
+IpsPolicy* get_ips_policy(const SnortConfig* sc, unsigned i)
+{
+ return sc && i < sc->policy_map->ips_policy_count() ?
+ sc->policy_map->get_ips_policy(i) : nullptr;
+}
IpsPolicy* get_user_ips_policy(const SnortConfig* sc, unsigned policy_id)
{
{
return sc->policy_map->get_empty_ips();
}
-
-NetworkPolicy* get_user_network_policy(const SnortConfig* sc, unsigned policy_id)
-{
- return sc->policy_map->get_user_network(policy_id);
-}
} // namespace snort
void set_network_policy(const SnortConfig* sc, unsigned i)
set_network_policy(pm->get_network_policy(i));
}
-void set_inspection_policy(InspectionPolicy* p)
-{ s_inspection_policy = p; }
-
void set_inspection_policy(const SnortConfig* sc, unsigned i)
{
PolicyMap* pm = sc->policy_map;
set_ips_policy(sc->policy_map->get_ips_policy(0));
}
+bool only_network_policy()
+{ return get_network_policy() && !get_ips_policy() && !get_inspection_policy(); }
+
+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 true;
}
-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 only_network_policy()
-{ return get_network_policy() && !get_ips_policy() && !get_inspection_policy(); }
-
Shell* get_shell(unsigned i = 0)
{ return i < shells.size() ? shells[i] : nullptr; }
+ void set_user_network(NetworkPolicy* p)
+ { user_network[p->user_policy_id] = p; }
+
void set_user_inspection(InspectionPolicy* p)
{ user_inspection[p->user_policy_id] = p; }
void set_user_ips(IpsPolicy* p)
{ user_ips[p->user_policy_id] = p; }
- void set_user_network(NetworkPolicy* p)
- { user_network[p->user_policy_id] = p; }
+ NetworkPolicy* get_user_network(unsigned user_id)
+ {
+ auto it = user_network.find(user_id);
+ return it == user_network.end() ? nullptr : it->second;
+ }
+
+ InspectionPolicy* get_user_inspection(unsigned user_id)
+ {
+ auto it = user_inspection.find(user_id);
+ return it == user_inspection.end() ? nullptr : it->second;
+ }
IpsPolicy* get_user_ips(unsigned user_id)
{
return it == user_ips.end() ? nullptr : it->second;
}
- NetworkPolicy* get_user_network(unsigned user_id)
- {
- auto it = user_network.find(user_id);
- return it == user_network.end() ? nullptr : it->second;
- }
+ NetworkPolicy* get_network_policy(unsigned i = 0)
+ { return i < network_policy.size() ? network_policy[i] : nullptr; }
InspectionPolicy* get_inspection_policy(unsigned i = 0)
{ return i < inspection_policy.size() ? inspection_policy[i] : nullptr; }
IpsPolicy* get_empty_ips()
{ return empty_ips_policy; }
- NetworkPolicy* get_network_policy(unsigned i = 0)
- { return i < network_policy.size() ? network_policy[i] : nullptr; }
+ unsigned network_policy_count()
+ { return network_policy.size(); }
unsigned inspection_policy_count()
{ return inspection_policy.size(); }
unsigned ips_policy_count()
{ return ips_policy.size(); }
- unsigned network_policy_count()
- { return network_policy.size(); }
-
unsigned shells_count()
{ return shells.size(); }
std::vector<InspectionPolicy*> inspection_policy;
std::vector<IpsPolicy*> ips_policy;
std::vector<NetworkPolicy*> network_policy;
+
IpsPolicy* empty_ips_policy;
+
std::unordered_map<Shell*, std::shared_ptr<PolicyTuple>> shell_map;
+ std::unordered_map<unsigned, NetworkPolicy*> user_network;
std::unordered_map<unsigned, InspectionPolicy*> user_inspection;
std::unordered_map<unsigned, IpsPolicy*> user_ips;
- std::unordered_map<unsigned, NetworkPolicy*> user_network;
bool cloned = false;
-
};
//-------------------------------------------------------------------------
// navigator stuff
//-------------------------------------------------------------------------
-
// FIXIT-L may be inlined at some point; on lockdown for now
// FIXIT-L SO_PUBLIC required because SnortConfig::inline_mode(), etc. uses the function
namespace snort
SO_PUBLIC NetworkPolicy* get_network_policy();
SO_PUBLIC InspectionPolicy* get_inspection_policy();
SO_PUBLIC IpsPolicy* get_ips_policy();
-SO_PUBLIC IpsPolicy* get_ips_policy(const snort::SnortConfig*, unsigned i = 0);
-SO_PUBLIC InspectionPolicy* get_default_inspection_policy(const snort::SnortConfig*);
-SO_PUBLIC void set_ips_policy(IpsPolicy*);
+
SO_PUBLIC void set_network_policy(NetworkPolicy*);
+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 InspectionPolicy* get_user_inspection_policy(const snort::SnortConfig*, unsigned policy_id);
+SO_PUBLIC InspectionPolicy* get_default_inspection_policy(const snort::SnortConfig*);
+
+SO_PUBLIC IpsPolicy* get_ips_policy(const snort::SnortConfig*, unsigned i = 0);
SO_PUBLIC IpsPolicy* get_user_ips_policy(const snort::SnortConfig*, unsigned policy_id);
SO_PUBLIC IpsPolicy* get_empty_ips_policy(const snort::SnortConfig*);
-SO_PUBLIC NetworkPolicy* get_user_network_policy(const snort::SnortConfig*, unsigned policy_id);
}
void set_network_policy(const snort::SnortConfig*, unsigned = 0);
-
-void set_inspection_policy(InspectionPolicy*);
void set_inspection_policy(const snort::SnortConfig*, unsigned = 0);
-
void set_ips_policy(const snort::SnortConfig*, unsigned = 0);
void set_policies(const snort::SnortConfig*, Shell*);
void set_default_policy(const snort::SnortConfig*);
-bool default_inspection_policy();
+bool only_network_policy();
bool only_inspection_policy();
bool only_ips_policy();
-bool only_network_policy();
+bool default_inspection_policy();
#endif
if ( cloned and idx )
break;
- set_inspection_policy(sc, 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;
}
- set_inspection_policy(sc);
+ ::set_inspection_policy(sc);
SearchTool::set_conf(nullptr);
return ok;
class FlowStateSetupHandler : public DataHandler
{
public:
- FlowStateSetupHandler() : DataHandler(BIND_NAME) { }
+ FlowStateSetupHandler() : DataHandler(BIND_NAME)
+ { order = 100; }
void handle(DataEvent&, Flow* flow) override
{