stash = nullptr;
}
- service.reset();
+ service = nullptr;
}
inline void Flow::clean()
stash->reset();
deferred_trust.clear();
- service.reset();
constexpr size_t offset = offsetof(Flow, context_chain);
// FIXIT-L need a struct to zero here to make future proof
void Flow::free_flow_data()
{
- NetworkPolicy* np = get_network_policy();
- InspectionPolicy* ip = get_inspection_policy();
- IpsPolicy* ipsp = get_ips_policy();
-
- unsigned t_reload_id = SnortConfig::get_thread_reload_id();
- if (reload_id == t_reload_id)
+ const SnortConfig* sc = SnortConfig::get_conf();
+ PolicySelector* ps = sc->policy_map->get_policy_selector();
+ NetworkPolicy* np = nullptr;
+ InspectionPolicy* ip = nullptr;
+ IpsPolicy* ipsp = nullptr;
+ if (ps)
{
- ::set_network_policy(network_policy_id);
- ::set_inspection_policy(inspection_policy_id);
- ::set_ips_policy(SnortConfig::get_conf(), ips_policy_id);
- }
- else
- {
- _daq_pkt_hdr pkthdr = {};
- pkthdr.address_space_id = key->addressSpaceId;
- select_default_policy(pkthdr, SnortConfig::get_conf());
+ np = get_network_policy();
+ ip = get_inspection_policy();
+ ipsp = get_ips_policy();
+
+ unsigned t_reload_id = SnortConfig::get_thread_reload_id();
+ if (reload_id == t_reload_id)
+ {
+ ::set_network_policy(network_policy_id);
+ ::set_inspection_policy(inspection_policy_id);
+ ::set_ips_policy(sc, ips_policy_id);
+ }
+ else
+ {
+ _daq_pkt_hdr pkthdr = {};
+ pkthdr.address_space_id = key->addressSpaceId;
+ select_default_policy(pkthdr, sc);
+ }
}
+
while (flow_data)
{
FlowData* tmp = flow_data;
delete tmp;
}
- set_network_policy(np);
- set_inspection_policy(ip);
- set_ips_policy(ipsp);
+ if (ps)
+ {
+ set_network_policy(np);
+ set_inspection_policy(ip);
+ set_ips_policy(ipsp);
+ }
}
void Flow::call_handlers(Packet* p, bool eof)
return (session_flags & SSNFLAG_ABORT_CLIENT);
}
-void Flow::set_service(Packet* pkt, std::shared_ptr<std::string> new_service)
+void Flow::set_service(Packet* pkt, const char* new_service)
{
- if (!new_service.use_count())
- return clear_service(pkt);
-
service = new_service;
DataBus::publish(FLOW_SERVICE_CHANGE_EVENT, pkt);
}
-void Flow::clear_service(Packet* pkt)
-{
- service.reset();
- DataBus::publish(FLOW_SERVICE_CHANGE_EVENT, pkt);
-}
-
void Flow::swap_roles()
{
std::swap(flowstats.client_pkts, flowstats.server_pkts);
// state. Inspector state is stored in FlowData, and Flow manages a list
// of FlowData items.
-#include <memory>
#include <string>
#include <sys/time.h>
void set_mpls_layer_per_dir(Packet*);
Layer get_mpls_layer_per_dir(bool);
void swap_roles();
- void set_service(Packet*, std::shared_ptr<std::string> new_service);
- void clear_service(Packet*);
- bool has_service() const
- { return 0 != service.use_count(); }
+ void set_service(Packet*, const char* new_service);
bool get_attr(const std::string& key, int32_t& val);
bool get_attr(const std::string& key, std::string& val);
void set_attr(const std::string& key, const int32_t& val);
// void space and allow for memset of tail end of struct
DeferredTrust deferred_trust;
- std::shared_ptr<std::string> service;
// Anything before this comment is not zeroed during construction
const FlowKey* key;
Inspector* gadget; // service handler
Inspector* assistant_gadget;
Inspector* data;
+ const char* service;
uint64_t expire_time;
{
unsigned reload_id = SnortConfig::get_thread_reload_id();
if (flow->reload_id != reload_id)
- {
flow->network_policy_id = get_network_policy()->policy_id;
- if (flow->flow_state == Flow::FlowState::INSPECT)
- DataBus::publish(FLOW_STATE_RELOADED_EVENT, p, flow);
- }
else
{
set_inspection_policy(flow->inspection_policy_id);
static void ff_service(const Args& a)
{
const char* svc = "unknown";
- if ( a.pkt->flow and a.pkt->flow->has_service() )
- svc = a.pkt->flow->service->c_str();
+ if ( a.pkt->flow and a.pkt->flow->service )
+ svc = a.pkt->flow->service;
TextLog_Puts(csv_log, svc);
}
{
const char* svc = "unknown";
- if ( a.pkt->flow and a.pkt->flow->has_service() )
- svc = a.pkt->flow->service->c_str();
+ if ( a.pkt->flow and a.pkt->flow->service )
+ svc = a.pkt->flow->service;
print_label(a, "service");
TextLog_Quote(json_log, svc);
void set_network_policy(unsigned i)
{
PolicyMap* pm = SnortConfig::get_conf()->policy_map;
-
- if ( i < pm->network_policy_count() )
- set_network_policy(pm->get_network_policy(i));
+ NetworkPolicy* np = pm->get_network_policy(i);
+ if ( np )
+ set_network_policy(np);
}
void set_inspection_policy(unsigned i)
#include "snort_config.h"
#include <grp.h>
+#include <mutex>
#include <pwd.h>
#include <syslog.h>
+#include <unordered_map>
#include "actions/ips_actions.h"
#include "detection/detect.h"
#endif
}
+std::mutex SnortConfig::static_names_mutex;
+std::unordered_map<std::string, std::string> SnortConfig::static_names;
+
+const char* SnortConfig::get_static_name(const char* name)
+{
+ std::lock_guard<std::mutex> static_name_lock(static_names_mutex);
+ auto entry = static_names.find(name);
+ if ( entry != static_names.end() )
+ return entry->second.c_str();
+ static_names.emplace(name, name);
+ return static_names[name].c_str();
+}
#include <sys/types.h>
#include <list>
+#include <mutex>
#include <unordered_map>
#include <vector>
private:
std::list<ReloadResourceTuner*> reload_tuners;
unsigned reload_id = 0;
+ static std::mutex static_names_mutex;
+ static std::unordered_map<std::string, std::string> static_names;
public:
//------------------------------------------------------
static bool log_show_plugins()
{ return logging_flags & LOGGING_FLAG__SHOW_PLUGINS; }
+
+ SO_PUBLIC static const char* get_static_name(const char* name);
};
}
{
Flow* flow = p->flow;
- if ( flow->has_service() and flow->searching_for_service()
+ if ( flow->service and flow->searching_for_service()
and (!(p->is_cooked()) or p->is_defrag()) )
bumble(p);
if ( p->disable_inspect )
return;
- if (!p->flow)
+ unsigned reload_id = SnortConfig::get_thread_reload_id();
+ if ( p->flow )
+ {
+ if ( p->flow->reload_id != reload_id )
+ DataBus::publish(FLOW_STATE_RELOADED_EVENT, p, p->flow);
+ }
+ else
DataBus::publish(PKT_WITHOUT_FLOW_EVENT, p);
FrameworkPolicy* fp = get_inspection_policy()->framework_policy;
if ( !p->has_paf_payload() and p->flow->flow_state == Flow::FlowState::INSPECT )
p->flow->session->process(p);
- unsigned reload_id = SnortConfig::get_thread_reload_id();
if ( p->flow->reload_id != reload_id )
{
::execute<T>(p, tp->first.vec, tp->first.num);
return;
}
- if ( !p->flow->has_service() )
+ if ( !p->flow->service )
::execute<T>(p, fp->network.vec, fp->network.num);
if ( p->disable_inspect )
void handle(DataEvent&, Flow* flow) override
{
- Binder* binder = InspectorManager::get_binder();
- if (binder && flow)
- binder->handle_flow_after_reload(*flow);
+ // If reload_id is zero, this is a new flow and is bound by FLOW_STATE_SETUP_EVENT
+ if (flow && flow->reload_id && Flow::FlowState::INSPECT == flow->flow_state)
+ {
+ Binder* binder = InspectorManager::get_binder();
+ if (binder)
+ binder->handle_flow_after_reload(*flow);
+ }
}
};
if (flow.ssn_state.snort_protocol_id != UNKNOWN_PROTOCOL_ID)
{
const SnortConfig* sc = SnortConfig::get_conf();
- flow.service = sc->proto_ref->get_shared_name(flow.ssn_state.snort_protocol_id);
+ flow.set_service(nullptr, sc->proto_ref->get_name(flow.ssn_state.snort_protocol_id));
}
}
Inspector* ins = nullptr;
Inspector* data = nullptr;
- if (flow.has_service())
+ if (flow.service)
{
ins = find_gadget(flow, data);
if (flow.gadget != ins)
// If there is no inspector bound to this flow after the service change, see if there's at least
// an associated protocol ID.
- if (!ins && flow.has_service())
- flow.ssn_state.snort_protocol_id = SnortConfig::get_conf()->proto_ref->find(flow.service->c_str());
+ if (!ins && flow.service)
+ flow.ssn_state.snort_protocol_id = SnortConfig::get_conf()->proto_ref->find(flow.service);
if (flow.is_stream())
{
Inspector* Binder::find_gadget(Flow& flow, Inspector*& data)
{
Stuff stuff;
- get_bindings(flow, stuff, flow.has_service() ? flow.service->c_str() : nullptr);
+ get_bindings(flow, stuff, flow.service);
data = stuff.data;
return stuff.gadget;
}
if (!when.has_criteria(BindWhen::Criteria::BWC_SVC))
return true;
- if (!flow.has_service())
+ if (!flow.service)
return false;
- return when.svc == flow.service->c_str();
+ return when.svc == flow.service;
}
inline bool Binding::check_service(const char* service) const
class SO_PUBLIC OpportunisticTlsEvent : public snort::DataEvent
{
public:
- OpportunisticTlsEvent(const snort::Packet* p, std::shared_ptr<std::string> service) :
+ OpportunisticTlsEvent(const snort::Packet* p, const char* service) :
pkt(p), next_service(service) { }
const snort::Packet* get_packet() override
{ return pkt; }
- std::shared_ptr<std::string> get_next_service()
+ const char* get_next_service()
{ return next_service; }
private:
const snort::Packet* pkt;
- std::shared_ptr<std::string> next_service;
+ const char* next_service;
};
}
THREAD_LOCAL int dce2_detected = 0;
static THREAD_LOCAL bool using_rpkt = false;
-std::shared_ptr<std::string> dce_rpc_service_name =
- std::make_shared<std::string>(DCE_RPC_SERVICE_NAME);
-
static const char* dce2_get_policy_name(DCE2_Policy policy)
{
const char* policyStr = nullptr;
#define GID_DCE2 133
#define DCE_RPC_SERVICE_NAME "dcerpc"
-extern std::shared_ptr<std::string> dce_rpc_service_name;
enum DCE2_Policy
{
if ( c2s_splitter->cutover_inspector() && s2c_splitter->cutover_inspector() )
{
dce_http_proxy_stats.http_proxy_sessions++;
- flow->set_service(p, dce_rpc_service_name);
+ flow->set_service(p, DCE_RPC_SERVICE_NAME);
}
else
dce_http_proxy_stats.http_proxy_session_failures++;
if ( splitter->cutover_inspector())
{
dce_http_server_stats.http_server_sessions++;
- flow->set_service(p, dce_rpc_service_name);
+ flow->set_service(p, DCE_RPC_SERVICE_NAME);
}
else
dce_http_server_stats.http_server_session_failures++;
"FTP data channel handler"
static const char* const fd_svc_name = "ftp-data";
-static std::shared_ptr<std::string> shared_fd_svc_name =
- std::make_shared<std::string>(fd_svc_name);
static THREAD_LOCAL ProfileStats ftpdataPerfStats;
static THREAD_LOCAL SimpleStats fdstats;
void FtpDataFlowData::handle_expected(Packet* p)
{
- if (!p->flow->has_service())
+ if (!p->flow->service)
{
- p->flow->set_service(p, shared_fd_svc_name);
+ p->flow->set_service(p, fd_svc_name);
FtpDataFlowData* fd =
(FtpDataFlowData*)p->flow->get_flow_data(FtpDataFlowData::inspector_id);
if (fd and fd->in_tls)
{
- OpportunisticTlsEvent evt(p, shared_fd_svc_name);
+ OpportunisticTlsEvent evt(p, fd_svc_name);
DataBus::publish(OPPORTUNISTIC_TLS_EVENT, evt, p->flow);
}
else
if (session_data->cutover_on_clear)
{
Flow* flow = p->flow;
- flow->clear_service(p);
+ flow->set_service(p, nullptr);
flow->free_flow_data(HttpFlowData::inspector_id);
}
}
/* This is either an initial server response or a STARTTLS response */
if (smtp_ssn->state == STATE_CONNECT)
smtp_ssn->state = STATE_COMMAND;
-
break;
case RESP_250:
// class stuff
//-------------------------------------------------------------------------
static const char* s_name = "ssl";
-static std::shared_ptr<std::string> shared_s_name = std::make_shared<std::string>(s_name);
class Ssl : public Inspector
{
pkt->flow->flags.trigger_finalize_event = fd->finalize_info.orig_flag;
fd->finalize_info.switch_in = false;
pkt->flow->set_proxied();
- pkt->flow->set_service(const_cast<Packet*>(pkt), shared_s_name);
+ pkt->flow->set_service(const_cast<Packet*>(pkt), s_name);
}
}
};
// map between service and curse details
static vector<CurseDetails> curse_map
{
- // name service alg is_tcp
- { "dce_udp", make_shared<string>("dcerpc") , dce_udp_curse, false },
- { "dce_tcp", make_shared<string>("dcerpc") , dce_tcp_curse, true },
- { "dce_smb", make_shared<string>("netbios-ssn"), dce_smb_curse, true },
- { "sslv2" , make_shared<string>("ssl") , ssl_v2_curse , true }
+ // name service alg is_tcp
+ { "dce_udp", "dcerpc" , dce_udp_curse, false },
+ { "dce_tcp", "dcerpc" , dce_tcp_curse, true },
+ { "dce_smb", "netbios-ssn", dce_smb_curse, true },
+ { "sslv2" , "ssl" , ssl_v2_curse , true }
};
bool CurseBook::add_curse(const char* key)
#define CURSES_H
#include <cstdint>
-#include <memory>
#include <string>
#include <vector>
struct CurseDetails
{
std::string name;
- std::shared_ptr<std::string> service;
+ const char* service;
curse_alg alg;
bool is_tcp;
};
#include <cstdlib>
+#include "main/snort_config.h"
+
#include "magic.h"
+using namespace snort;
using namespace std;
#define WILD 0x100
++i;
}
p->key = key;
- p->value = make_shared<string>(val);
+ p->value = SnortConfig::get_static_name(val);
}
bool HexBook::add_spell(const char* key, const char*& val)
}
if ( p->key == key )
{
- val = p->value->c_str();
+ val = p->value;
return false;
}
if ( const MagicPage* q = find_spell(s, n, p->any, i+1) )
return q;
}
- return p->value.use_count() ? p : nullptr;
+ return p->value ? p : nullptr;
}
return p;
}
delete any;
}
-std::shared_ptr<std::string> MagicBook::find_spell(const uint8_t* data, unsigned len,
+const char* MagicBook::find_spell(const uint8_t* data, unsigned len,
const MagicPage*& p) const
{
assert(p);
-
p = find_spell(data, len, p, 0);
- if ( p && p->value.use_count() )
- return p->value;
-
- return nullptr;
+ return p ? p->value : nullptr;
}
MagicBook::MagicBook()
#ifndef MAGIC_H
#define MAGIC_H
-#include <memory>
#include <string>
#include <vector>
struct MagicPage
{
std::string key;
- std::shared_ptr<std::string> value;
+ const char* value = nullptr;
MagicPage* next[256];
MagicPage* any;
MagicBook& operator=(const MagicBook&) = delete;
virtual bool add_spell(const char* key, const char*& val) = 0;
- virtual std::shared_ptr<std::string> find_spell(const uint8_t*, unsigned len,
- const MagicPage*&) const;
+ virtual const char* find_spell(const uint8_t* data, unsigned len, const MagicPage*&) const;
const MagicPage* page1() const
{ return root; }
#include <cassert>
+#include "main/snort_config.h"
+
#include "magic.h"
+using namespace snort;
using namespace std;
#define WILD 0x100
++i;
}
p->key = key;
- p->value = make_shared<string>(val);
+ p->value = SnortConfig::get_static_name(val);
}
bool SpellBook::add_spell(const char* key, const char*& val)
}
if ( p->key == key )
{
- val = p->value->c_str();
+ val = p->value;
return false;
}
}
// If no match but has glob, continue lookup from glob
- if ( !p->value.use_count() && glob )
+ if ( !p->value && glob )
{
p = glob;
glob = nullptr;
return find_spell(s, n, p, i);
}
- return p->value.use_count() ? p : nullptr;
+ return p->value ? p : nullptr;
}
return p;
}
if ( wizard->cast_spell(wand, pkt->flow, data, len, wizard_processed_bytes) )
{
trace_logf(wizard_trace, pkt, "%s streaming search found service %s\n",
- to_server() ? "c2s" : "s2c", pkt->flow->service->c_str());
+ to_server() ? "c2s" : "s2c", pkt->flow->service);
count_hit(pkt->flow);
wizard_processed_bytes = 0;
return STOP;
// delayed. Because AppId depends on wizard only for SSH detection and SSH inspector can be
// attached very early, event is raised here after first scan. In the future, wizard should be
// enhanced to abort sooner if it can't detect service.
- if (!pkt->flow->has_service() && !pkt->flow->flags.svc_event_generated)
+ if (!pkt->flow->service && !pkt->flow->flags.svc_event_generated)
{
DataBus::publish(FLOW_NO_SERVICE_EVENT, pkt);
pkt->flow->flags.svc_event_generated = true;
if ( cast_spell(wand, p->flow, p->data, p->dsize, udp_processed_bytes) )
{
trace_logf(wizard_trace, p, "%s datagram search found service %s\n",
- c2s ? "c2s" : "s2c", p->flow->service->c_str());
+ c2s ? "c2s" : "s2c", p->flow->service);
++tstats.udp_hits;
}
else
bool Wizard::spellbind(
const MagicPage*& m, Flow* f, const uint8_t* data, unsigned len)
{
- std::shared_ptr<std::string> p_shared = m->book.find_spell(data, len, m);
- if (p_shared.use_count())
- f->service = p_shared;
- else
- f->service.reset();
- return f->has_service();
+ f->service = m->book.find_spell(data, len, m);
+ return f->service != nullptr;
}
bool Wizard::cursebind(const vector<CurseServiceTracker>& curse_tracker, Flow* f,
{
if (cst.curse->alg(data, len, cst.tracker))
{
- if (cst.curse->service.use_count())
- f->service = cst.curse->service;
- else
- f->service.reset();
- if ( f->has_service() )
+ f->service = cst.curse->service;
+ if ( f->service )
return true;
}
}
// If we reach max value of wizard_processed_bytes,
// but not assign any inspector - raise tcp_miss and stop
- if ( !f->has_service() && wizard_processed_bytes >= max_search_depth )
+ if ( !f->service && wizard_processed_bytes >= max_search_depth )
{
w.spell = nullptr;
w.hex = nullptr;
#include "snort_protocols.h"
#include <algorithm>
+#include <cassert>
#include "log/messages.h"
+#include "main/snort_config.h"
#include "protocols/packet.h"
#include "utils/util.h"
#include "utils/util_cstring.h"
{ return protocol_number; }
const char* ProtocolReference::get_name(SnortProtocolId id) const
-{
- std::shared_ptr<std::string> shared_name = get_shared_name(id);
- return shared_name->c_str();
-}
-
-std::shared_ptr<std::string> ProtocolReference::get_shared_name(SnortProtocolId id) const
{
if ( id >= id_map.size() )
id = 0;
struct Compare
{
bool operator()(SnortProtocolId a, SnortProtocolId b)
- { return map[a]->c_str() < map[b]->c_str(); }
+ { return 0 > strcmp(map[a], map[b]); }
- vector<shared_ptr<string>>& map;
+ vector<const char*>& map;
};
const char* ProtocolReference::get_name_sorted(SnortProtocolId id)
if ( id >= ind_map.size() )
return nullptr;
- return id_map[ind_map[id]]->c_str();
+ return id_map[ind_map[id]];
}
SnortProtocolId ProtocolReference::add(const char* protocol)
return protocol_ref->second;
SnortProtocolId snort_protocol_id = protocol_number++;
- id_map.emplace_back(make_shared<string>(protocol));
+ protocol = SnortConfig::get_static_name(protocol);
+ id_map.emplace_back(protocol);
ref_table[protocol] = snort_protocol_id;
return snort_protocol_id;
{ init(old_proto_ref); }
ProtocolReference::~ProtocolReference()
-{ ref_table.clear(); }
+{
+ ref_table.clear();
+ id_map.clear();
+ ind_map.clear();
+}
#ifndef SNORT_PROTOCOLS_H
#define SNORT_PROTOCOLS_H
-#include <memory>
#include <string>
#include <vector>
#include <unordered_map>
SnortProtocolId get_count() const;
const char* get_name(SnortProtocolId id) const;
- std::shared_ptr<std::string> get_shared_name(SnortProtocolId id) const;
const char* get_name_sorted(SnortProtocolId id);
SnortProtocolId add(const char* protocol);
bool operator()(SnortProtocolId a, SnortProtocolId b);
private:
- std::vector<std::shared_ptr<std::string>> id_map;
+ std::vector<const char*> id_map;
std::vector<SnortProtocolId> ind_map;
std::unordered_map<std::string, SnortProtocolId> ref_table;
void init(const ProtocolReference* old_proto_ref);
};
+
+void protocol_reference_global_init();
+void protocol_reference_global_term();
+
}
#endif
using namespace snort;
+const char* SnortConfig::get_static_name(const char* name) { return name; }
+
TEST_GROUP(protocol_reference)
-{};
+{ };
// Service Protocols
//