if (asd)
{
// Skip sessions using old odp context after odp reload
- AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
- if (inspector and (&(inspector->get_ctxt().get_odp_ctxt()) != &(asd->get_odp_ctxt())))
+ if (!pkt_thread_odp_ctxt or
+ pkt_thread_odp_ctxt->get_version() != asd->get_odp_ctxt_version())
return nullptr;
if (app_id == APP_ID_UNKNOWN)
if (asd)
{
// Skip sessions using old odp context after odp reload
- AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
- if (inspector and (&(inspector->get_ctxt().get_odp_ctxt()) != &(asd->get_odp_ctxt())))
+ if (!pkt_thread_odp_ctxt or
+ pkt_thread_odp_ctxt->get_version() != asd->get_odp_ctxt_version())
return nullptr;
AppId appid = asd->pick_ss_payload_app_id();
if (asd)
{
// Skip detection for sessions using old odp context after odp reload
- AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
- if (inspector and (&(inspector->get_ctxt().get_odp_ctxt()) != &(asd->get_odp_ctxt())))
+ if (!pkt_thread_odp_ctxt or
+ pkt_thread_odp_ctxt->get_version() != asd->get_odp_ctxt_version())
return false;
AppidChangeBits change_bits;
ThirdPartyAppIdContext* AppIdContext::tp_appid_ctxt = nullptr;
OdpContext* AppIdContext::odp_ctxt = nullptr;
+uint32_t OdpContext::next_version = 0;
static void map_app_names_to_snort_ids(SnortConfig* sc, AppIdConfig& config)
{
app_info_mgr.init_appid_info_table(config, sc, *this);
client_pattern_detector = new PatternClientDetector(&client_disco_mgr);
service_pattern_detector = new PatternServiceDetector(&service_disco_mgr);
+ version = next_version++;
}
OdpContext::~OdpContext()
~OdpContext();
void initialize();
+ uint32_t get_version() const
+ {
+ return version;
+ }
+
AppInfoManager& get_app_info_mgr()
{
return app_info_mgr;
std::array<AppId, APP_ID_PORT_ARRAY_SIZE> tcp_port_only = {}; // port-only TCP services
std::array<AppId, APP_ID_PORT_ARRAY_SIZE> udp_port_only = {}; // port-only UDP services
std::array<AppId, 256> ip_protocol = {}; // non-TCP / UDP protocol services
+
+ uint32_t version;
+ static uint32_t next_version;
};
class OdpThreadContext
else
{
// Skip sessions using old odp context after reload detectors
- AppIdInspector* inspector = (AppIdInspector*) snort::InspectorManager::get_inspector(MOD_NAME, true);
- if (inspector and (&(inspector->get_ctxt().get_odp_ctxt()) != &(asd->get_odp_ctxt())))
+ if (!pkt_thread_odp_ctxt or
+ (pkt_thread_odp_ctxt->get_version() != asd->get_odp_ctxt_version()))
return;
}
OdpContext& odp_ctxt)
{
// Skip inspection for sessions using old odp context after an odp reload
- if (asd and (&(asd->get_odp_ctxt()) != &(inspector.get_ctxt().get_odp_ctxt())))
+ if (asd and
+ asd->get_odp_ctxt_version() != odp_ctxt.get_version())
{
appid_stats.odp_reload_ignored_pkts++;
appid_stats.tp_reload_ignored_pkts++;
if (tp_appid_ctxt and ((service_id = asd.pick_service_app_id()) != APP_ID_HTTP2))
{
// Skip third-party inspection for sessions using old config
- if (asd.tpsession and &(asd.tpsession->get_ctxt()) != tp_appid_ctxt)
+ if (asd.tpsession and asd.tpsession->get_ctxt_version() != tp_appid_ctxt->get_version())
{
bool is_tp_done = asd.is_tp_processing_done();
delete asd.tpsession;
else
{
// Skip detection for sessions using old odp context after odp reload
- AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
- if (inspector and (&(asd->get_odp_ctxt()) != &(inspector->get_ctxt().get_odp_ctxt())))
+ if (!pkt_thread_odp_ctxt or
+ (asd->get_odp_ctxt_version() != pkt_thread_odp_ctxt->get_version()))
return;
}
CRYPTO_cleanup_all_ex_data();
}
-static void add_appid_to_packet_trace(Flow& flow, OdpContext& odp_context)
+static void add_appid_to_packet_trace(Flow& flow, const OdpContext& odp_context)
{
AppIdSession* session = appid_api.get_appid_session(flow);
// Skip sessions using old odp context after odp reload
- if (!session || (&(session->get_odp_ctxt()) != &odp_context))
+ if (!session || (session->get_odp_ctxt_version() != odp_context.get_version()))
return;
AppId service_id, client_id, payload_id, misc_id;
assert(odp_thread_local_ctxt);
delete odp_thread_local_ctxt;
odp_thread_local_ctxt = nullptr;
- ThirdPartyAppIdContext* tp_appid_ctxt = ctxt->get_tp_appid_ctxt();
- if (tp_appid_ctxt)
- tp_appid_ctxt->tfini();
+ if (pkt_thread_tp_appid_ctxt)
+ pkt_thread_tp_appid_ctxt->tfini();
}
void AppIdInspector::eval(Packet* p)
{
public:
bool execute(Analyzer&, void**) override;
- ACThirdPartyAppIdContextSwap(const AppIdInspector& inspector, ThirdPartyAppIdContext* tp_ctxt,
+ ACThirdPartyAppIdContextSwap(const AppIdInspector& inspector,
Request& current_request, bool from_shell): inspector(inspector),
- tp_ctxt(tp_ctxt),request(current_request), from_shell(from_shell) { }
+ request(current_request), from_shell(from_shell)
+ {
+ LogMessage("== swapping third-party configuration\n");
+ request.respond("== swapping third-party configuration\n", from_shell, true);
+ }
+
~ACThirdPartyAppIdContextSwap() override;
const char* stringify() override { return "THIRD-PARTY_CONTEXT_SWAP"; }
private:
const AppIdInspector& inspector;
- ThirdPartyAppIdContext* tp_ctxt = nullptr;
Request& request;
bool from_shell;
};
bool ACThirdPartyAppIdContextSwap::execute(Analyzer&, void**)
+{
+ assert(!pkt_thread_tp_appid_ctxt);
+ pkt_thread_tp_appid_ctxt = inspector.get_ctxt().get_tp_appid_ctxt();
+ pkt_thread_tp_appid_ctxt->tinit();
+ pkt_thread_tp_appid_ctxt->set_tp_reload_in_progress(false);
+
+ return true;
+}
+
+ACThirdPartyAppIdContextSwap::~ACThirdPartyAppIdContextSwap()
+{
+ Swapper::set_reload_in_progress(false);
+ LogMessage("== reload third-party complete\n");
+ request.respond("== reload third-party complete\n", from_shell, true);
+}
+
+class ACThirdPartyAppIdContextUnload : public AnalyzerCommand
+{
+public:
+ bool execute(Analyzer&, void**) override;
+ ACThirdPartyAppIdContextUnload(const AppIdInspector& inspector, ThirdPartyAppIdContext* tp_ctxt,
+ Request& current_request, bool from_shell): inspector(inspector),
+ tp_ctxt(tp_ctxt), request(current_request), from_shell(from_shell) { }
+ ~ACThirdPartyAppIdContextUnload() override;
+ const char* stringify() override { return "THIRD-PARTY_CONTEXT_UNLOAD"; }
+private:
+ const AppIdInspector& inspector;
+ ThirdPartyAppIdContext* tp_ctxt = nullptr;
+ Request& request;
+ bool from_shell;
+};
+
+bool ACThirdPartyAppIdContextUnload::execute(Analyzer&, void**)
{
assert(pkt_thread_tp_appid_ctxt);
- ThirdPartyAppIdContext* tp_appid_ctxt = inspector.get_ctxt().get_tp_appid_ctxt();
- assert(pkt_thread_tp_appid_ctxt != tp_appid_ctxt);
+ pkt_thread_tp_appid_ctxt->set_tp_reload_in_progress(true);
bool reload_in_progress = pkt_thread_tp_appid_ctxt->tfini(true);
- pkt_thread_tp_appid_ctxt->set_tp_reload_in_progress(reload_in_progress);
if (reload_in_progress)
return false;
- tp_appid_ctxt->tinit();
- pkt_thread_tp_appid_ctxt = tp_appid_ctxt;
+ pkt_thread_tp_appid_ctxt = nullptr;
return true;
}
-ACThirdPartyAppIdContextSwap::~ACThirdPartyAppIdContextSwap()
+ACThirdPartyAppIdContextUnload::~ACThirdPartyAppIdContextUnload()
{
delete tp_ctxt;
- Swapper::set_reload_in_progress(false);
- LogMessage("== reload third-party complete\n");
- request.respond("== reload third-party complete\n", from_shell, true);
+ AppIdContext& ctxt = inspector.get_ctxt();
+ ctxt.create_tp_appid_ctxt();
+ main_broadcast_command(new ACThirdPartyAppIdContextSwap(inspector,
+ request, from_shell), from_shell);
}
class ACOdpContextSwap : public AnalyzerCommand
current_request.respond("== reload third-party failed - appid not enabled\n", from_shell);
return 0;
}
- AppIdContext& ctxt = inspector->get_ctxt();
+ const AppIdContext& ctxt = inspector->get_ctxt();
ThirdPartyAppIdContext* old_ctxt = ctxt.get_tp_appid_ctxt();
if (!old_ctxt)
{
return 0;
}
Swapper::set_reload_in_progress(true);
- ctxt.create_tp_appid_ctxt();
- current_request.respond("== swapping third-party configuration\n", from_shell);
- main_broadcast_command(new ACThirdPartyAppIdContextSwap(*inspector, old_ctxt,
+ current_request.respond("== unloading old third-party configuration\n", from_shell);
+ main_broadcast_command(new ACThirdPartyAppIdContextUnload(*inspector, old_ctxt,
current_request, from_shell), from_shell);
return 0;
}
{
service_ip.clear();
initiator_port = port;
+ odp_ctxt_version = odp_ctxt.get_version();
appid_stats.total_sessions++;
}
return odp_ctxt;
}
+ uint32_t get_odp_ctxt_version() const
+ {
+ return odp_ctxt_version;
+ }
+
ThirdPartyAppIdContext* get_tp_appid_ctxt() const
{
return tp_appid_ctxt;
snort::AppIdSessionApi& api;
static uint16_t inferred_svcs_ver;
OdpContext& odp_ctxt;
+ uint32_t odp_ctxt_version;
ThirdPartyAppIdContext* tp_appid_ctxt = nullptr;
};
else
{
// Inspection is not done for sessions using old odp context after reload detectors
- AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
- if (inspector and (&(inspector->get_ctxt().get_odp_ctxt()) != &(asd->get_odp_ctxt())))
+ if (!pkt_thread_odp_ctxt or
+ (pkt_thread_odp_ctxt->get_version() != asd->get_odp_ctxt_version()))
return false;
}
cooked_client = true;
// Skip stats for sessions using old odp context after reload detectors
- AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME, true);
- OdpContext& odp_ctxt = asd.get_odp_ctxt();
- if (inspector and (&(inspector->get_ctxt().get_odp_ctxt()) != &odp_ctxt))
+ if (!pkt_thread_odp_ctxt or
+ (pkt_thread_odp_ctxt->get_version() != asd.get_odp_ctxt_version()))
{
snort_free(record);
return;
}
+ OdpContext& odp_ctxt = asd.get_odp_ctxt();
AppInfoTableEntry* entry
= odp_ctxt.get_app_info_mgr().get_app_info_entry(app_id);
AppIdSession* session = appid_api.get_appid_session(*(p->flow));
// Skip detection for sessions using old odp context after odp reload
- if ( !session || (&(session->get_odp_ctxt()) != pkt_thread_odp_ctxt))
+ if ( !session or !pkt_thread_odp_ctxt or
+ (session->get_odp_ctxt_version() != pkt_thread_odp_ctxt->get_version()))
return NO_MATCH;
AppId app_ids[APP_PROTOID_MAX];
mock_init_appid_pegs();
SfIp ip;
mock_session = new AppIdSession(IpProtocol::TCP, &ip, 1492, dummy_appid_inspector,
- dummy_appid_inspector.get_ctxt().get_odp_ctxt());
+ dummy_appid_inspector.get_ctxt().get_odp_ctxt());
+ pkt_thread_odp_ctxt = &mock_session->get_odp_ctxt();
flow = new Flow;
flow->set_flow_data(mock_session);
mock().setDataObject("test_log", "char", test_log);
#include <CppUTest/TestHarness.h>
#include <CppUTestExt/MockSupport.h>
+uint32_t ThirdPartyAppIdContext::next_version = 0;
+
namespace snort
{
// Stubs for packet
flow = new Flow;
SfIp ip;
mock_session = new AppIdSession(IpProtocol::TCP, &ip, 1492, dummy_appid_inspector, stub_odp_ctxt);
+ pkt_thread_odp_ctxt = &mock_session->get_odp_ctxt();
mock_session->create_http_session();
flow->set_flow_data(mock_session);
appidDebug = new AppIdDebug();
AppIdInspector dummy_appid_inspector( appid_mod );
AppIdConfig appid_config;
AppIdContext appid_ctxt(appid_config);
+THREAD_LOCAL OdpContext* pkt_thread_odp_ctxt = nullptr;
AppIdInspector::AppIdInspector(AppIdModule& ) { ctxt = &appid_ctxt; }
unsigned AppIdSession::inspector_id = 0;
std::mutex AppIdSession::inferred_svcs_lock;
uint16_t AppIdSession::inferred_svcs_ver = 0;
+uint32_t OdpContext::next_version = 0;
class MockAppIdDnsSession : public AppIdDnsSession
{
OdpContext&) : FlowData(inspector_id, &inspector), config(stub_config),
protocol(proto), api(*(new AppIdSessionApi(this, *ip))), odp_ctxt(stub_odp_ctxt)
{
+ odp_ctxt_version = odp_ctxt.get_version();
service_port = APPID_UT_SERVICE_PORT;
AppidChangeBits change_bits;
#include <CppUTest/CommandLineTestRunner.h>
#include <CppUTest/TestHarness.h>
-void ApplicationDescriptor::set_id(const Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
-
AppIdSession* mock_session = nullptr;
AppIdSessionApi* appid_session_api = nullptr;
static AppIdConfig config;
static OdpContext odpctxt(config, nullptr);
+
+void ApplicationDescriptor::set_id(const Packet&, AppIdSession&, AppidSessionDirection, AppId, AppidChangeBits&) { }
+
Inspector* InspectorManager::get_inspector(char const*, bool, const snort::SnortConfig*)
{
return nullptr;
SfIp ip;
mock_session = new AppIdSession(IpProtocol::TCP, &ip, 1492, dummy_appid_inspector, odpctxt);
+ pkt_thread_odp_ctxt = &mock_session->get_odp_ctxt();
mock_session->set_ss_application_ids(APPID_UT_ID, APPID_UT_ID, APPID_UT_ID,
APPID_UT_ID, APPID_UT_ID, change_bits);
}
using namespace snort;
using namespace std;
+uint32_t ThirdPartyAppIdContext::next_version = 0;
+
class ThirdPartyAppIdContextImpl : public ThirdPartyAppIdContext
{
public:
{
public:
ThirdPartyAppIdContext(uint32_t ver, const char* mname, ThirdPartyConfig& config)
- : version(ver), name(mname), cfg(config) { }
+ : api_version(ver), name(mname), cfg(config)
+ {
+ version = next_version++;
+ }
+
+ uint32_t get_version() const
+ {
+ return version;
+ }
virtual ~ThirdPartyAppIdContext() { }
- uint32_t api_version() const { return version; }
+ uint32_t get_api_version() const { return api_version; }
const std::string& module_name() const { return name; }
virtual int tinit() = 0;
bool get_tp_reload_in_progress() { return tp_reload_in_progress; }
protected:
- const uint32_t version;
+ const uint32_t api_version;
const std::string name;
ThirdPartyConfig cfg;
private:
// No implicit constructor as derived classes need to provide
// version and name.
- ThirdPartyAppIdContext() : version(0), name("") { }
+ ThirdPartyAppIdContext() : api_version(0), name(""), version(0) { }
+ uint32_t version;
static THREAD_LOCAL bool tp_reload_in_progress;
+ // Increments when a new third-party context is loaded
+ SO_PUBLIC static uint32_t next_version;
};
#endif
{
public:
ThirdPartyAppIdSession(const ThirdPartyAppIdContext& ctxt)
- : appid(APP_ID_NONE), confidence(100), state(TP_STATE_INIT), ctxt(ctxt) { }
+ : appid(APP_ID_NONE), confidence(100), state(TP_STATE_INIT), ctxt(ctxt)
+ {
+ ctxt_version = ctxt.get_version();
+ }
virtual ~ThirdPartyAppIdSession() { }
virtual bool reset() = 0; // just reset state
virtual AppId get_appid(int& conf) { conf=confidence; return appid; }
virtual const ThirdPartyAppIdContext& get_ctxt() const
{ return ctxt; }
+ uint32_t get_ctxt_version() { return ctxt_version; }
protected:
AppId appid;
int confidence;
TPState state;
const ThirdPartyAppIdContext& ctxt;
+ uint32_t ctxt_version;
};
#endif
using namespace snort;
TPLibHandler* TPLibHandler::self = nullptr;
+uint32_t ThirdPartyAppIdContext::next_version = 0;
bool TPLibHandler::load_callback(const char* const path)
{
return nullptr;
}
- if ( (tp_appid_ctxt->api_version() != THIRD_PARTY_APPID_API_VERSION)
+ if ( (tp_appid_ctxt->get_api_version() != THIRD_PARTY_APPID_API_VERSION)
|| (tp_appid_ctxt->module_name().empty()) )
{
ErrorMessage("Ignoring incomplete 3rd party AppID module (%s, %u, %s)!\n",
- config.tp_appid_path.c_str(), tp_appid_ctxt->api_version(),
+ config.tp_appid_path.c_str(), tp_appid_ctxt->get_api_version(),
tp_appid_ctxt->module_name().empty() ? "empty" : tp_appid_ctxt->module_name().c_str());
delete tp_appid_ctxt;