// return verification status
virtual bool configure(SnortConfig*) { return true; }
+ // cleanup for inspector instance removal from the running configuration
+ // this is only called for inspectors in the default inspection policy that
+ // were present in the prior snort configuration and were removed in the snort
+ // configuration that is being loaded during a reload_config command
+ virtual void tear_down(SnortConfig*) { }
+
// called on controls after everything is configured
// return true if there is nothing to do ever based on config
virtual bool disable(SnortConfig*) { return false; }
current_request->respond(".. reloading configuration\n");
const SnortConfig* old = SnortConfig::get_conf();
- SnortConfig* sc = Snort::get_reload_config(fname, plugin_path);
+ SnortConfig* sc = Snort::get_reload_config(fname, plugin_path, old);
if ( !sc )
{
TraceApi::thread_reinit(sc->trace_config);
}
+void Analyzer::stop_removed(const SnortConfig* sc)
+{
+ InspectorManager::thread_stop_removed(sc);
+}
+
void Analyzer::term()
{
const SnortConfig* sc = SnortConfig::get_conf();
void resume(uint64_t msg_cnt);
void reload_daq();
void reinit(const snort::SnortConfig*);
+ void stop_removed(const snort::SnortConfig*);
void rotate();
snort::SFDAQInstance* get_daq_instance() { return daq_instance; }
if ( reload_tuners->empty() )
{
delete reload_tuners;
+ ps->finish(analyzer);
return true;
}
// FIXIT-M refactor this so startup and reload call the same core function to
// instantiate things that can be reloaded
-SnortConfig* Snort::get_reload_config(const char* fname, const char* plugin_path)
+SnortConfig* Snort::get_reload_config(const char* fname, const char* plugin_path,
+ const SnortConfig* old)
{
reloading = true;
ModuleManager::reset_errors();
return nullptr;
}
+ InspectorManager::tear_down_removed_inspectors(old, sc);
InspectorManager::prepare_controls(sc);
FileService::verify_reload(sc);
class Snort
{
public:
- static SnortConfig* get_reload_config(const char* fname, const char* plugin_path = nullptr);
+ static SnortConfig* get_reload_config(const char* fname, const char* plugin_path,
+ const SnortConfig* old);
static SnortConfig* get_updated_policy(SnortConfig*, const char* fname, const char* iname);
static SnortConfig* get_updated_module(SnortConfig*, const char* name);
static void setup(int argc, char* argv[]);
#include "swapper.h"
+#include "managers/inspector_manager.h"
+
#include "analyzer.h"
#include "snort.h"
#include "snort_config.h"
Swapper::~Swapper()
{
+ if ( new_conf )
+ InspectorManager::clear_removed_inspectors(new_conf);
if ( old_conf )
delete old_conf;
}
analyzer.reinit(new_conf);
}
}
+
+void Swapper::finish(Analyzer& analyzer)
+{
+ if ( new_conf )
+ analyzer.stop_removed(new_conf);
+}
~Swapper();
void apply(Analyzer&);
+ void finish(Analyzer&);
snort::SnortConfig* get_new_conf() { return new_conf; }
static bool get_reload_in_progress() { return reload_in_progress; }
void InspectorManager::thread_term() { }
void InspectorManager::thread_stop(const SnortConfig*) { }
void InspectorManager::thread_reinit(const SnortConfig*) { }
+void InspectorManager::thread_stop_removed(const SnortConfig*) { }
void ModuleManager::accumulate() { }
void Stream::handle_timeouts(bool) { }
void Stream::purge_flows() { }
struct FrameworkPolicy
{
PHInstanceList ilist; // List of inspector module instances
+ PHInstanceList removed_ilist; // List of removed inspector module instances
PHVector passive;
PHVector packet;
while ( !trash.empty() )
{
auto* p = trash.front();
+ trash.pop_front();
if ( !p->is_inactive() )
+ {
+ trash.emplace_back(p);
return;
+ }
InspectorManager::free_inspector(p);
- trash.pop_front();
}
}
return (Binder*)pi->framework_policy->binder;
}
+void InspectorManager::clear_removed_inspectors(SnortConfig* sc)
+{
+ FrameworkPolicy* fp = sc->policy_map->get_inspection_policy()->framework_policy;
+ for ( auto* p : fp->removed_ilist )
+ p->handler->rem_ref();
+ fp->removed_ilist.clear();
+}
+
+void InspectorManager::tear_down_removed_inspectors(const SnortConfig* old, SnortConfig* 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;
+ for (auto it = old_fp->ilist.begin(); it != old_fp->ilist.end(); ++it)
+ {
+ PHInstance* instance = get_instance(fp, (*it)->name.c_str());
+ if (!instance)
+ {
+ fp->removed_ilist.emplace_back(*it);
+ (*it)->handler->add_ref();
+ (*it)->handler->tear_down(sc);
+ }
+ }
+}
+
// FIXIT-P cache get_inspector() returns or provide indexed lookup
Inspector* InspectorManager::get_inspector(const char* key, bool dflt_only, const SnortConfig* sc)
{
}
}
+void InspectorManager::thread_stop_removed(const SnortConfig* sc)
+{
+ // pin->tinit() only called for default policy
+ InspectionPolicy* pi = get_default_inspection_policy(sc);
+
+ if ( pi && pi->framework_policy )
+ {
+ // Call pin->tterm() for anything that has been initialized and removed
+ for ( auto* p : pi->framework_policy->removed_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_stop(const SnortConfig* sc)
{
// If thread_init() was never called, we have nothing to do.
set_default_policy(sc);
InspectionPolicy* pi = get_inspection_policy();
- // FIXIT-RC Any inspectors that were once configured/instantiated but
- // no longer exist in the conf cannot have their instance tterm()
- // called and will leak!
-
if ( pi && pi->framework_policy )
{
for ( auto* p : pi->framework_policy->ilist )
static void thread_init(const SnortConfig*);
static void thread_reinit(const SnortConfig*);
+ static void thread_stop_removed(const SnortConfig*);
static void thread_stop(const SnortConfig*);
static void thread_term();
static void clear(Packet*);
static void empty_trash();
+ static void tear_down_removed_inspectors(const SnortConfig*, SnortConfig*);
+ static void clear_removed_inspectors(SnortConfig*);
#ifdef PIGLET
static Inspector* instantiate(const char*, Module*, SnortConfig*);
void PacketTracer::add_eth_header_info(const Packet& p)
{
auto eh = layer::get_eth_layer(&p);
- if (!(shell_enabled) && eh )
+ if (eh)
{
- // MAC layer
- PacketTracer::log("%02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X %04X\n",
- eh->ether_src[0], eh->ether_src[1], eh->ether_src[2],
- eh->ether_src[3], eh->ether_src[4], eh->ether_src[5],
- eh->ether_dst[0], eh->ether_dst[1], eh->ether_dst[2],
- eh->ether_dst[3], eh->ether_dst[4], eh->ether_dst[5],
- (uint16_t)eh->ethertype());
+ if (shell_enabled)
+ {
+ PacketTracer::log("\n");
+ char gr_buf[32] = { '\0' };
+ if (p.is_inter_group_flow())
+ snprintf(gr_buf, sizeof(gr_buf), " GR=%hd-%hd", p.pkth->ingress_group,
+ p.pkth->egress_group);
+
+ snprintf(debug_session, sizeof(debug_session),
+ "%02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X %04X"
+ " AS=%hu ID=%u%s ",
+ eh->ether_src[0], eh->ether_src[1], eh->ether_src[2],
+ eh->ether_src[3], eh->ether_src[4], eh->ether_src[5],
+ eh->ether_dst[0], eh->ether_dst[1], eh->ether_dst[2],
+ eh->ether_dst[3], eh->ether_dst[4], eh->ether_dst[5],
+ (uint16_t)eh->ethertype(), p.pkth->address_space_id, get_instance_id(),
+ gr_buf);
+ s_pkt_trace->active = true;
+ }
+ else
+ {
+ // MAC layer
+ PacketTracer::log("%02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X %04X\n",
+ eh->ether_src[0], eh->ether_src[1], eh->ether_src[2],
+ eh->ether_src[3], eh->ether_src[4], eh->ether_src[5],
+ eh->ether_dst[0], eh->ether_dst[1], eh->ether_dst[2],
+ eh->ether_dst[3], eh->ether_dst[4], eh->ether_dst[5],
+ (uint16_t)eh->ethertype());
+ }
}
}
StreamBase(const StreamModuleConfig*);
void show(const SnortConfig*) const override;
+ void tear_down(SnortConfig*) override;
+
void tinit() override;
void tterm() override;
StreamBase::StreamBase(const StreamModuleConfig* c)
{ config = *c; }
+void StreamBase::tear_down(SnortConfig* sc)
+{ sc->register_reload_resource_tuner(new StreamUnloadReloadResourceManager); }
+
void StreamBase::tinit()
{
assert(!flow_con && config.flow_cache_cfg.max_flows);
{
StreamHAManager::tterm();
FlushBucket::clear();
+ base_prep();
+ delete flow_con;
+ flow_con = nullptr;
}
void StreamBase::show(const SnortConfig* sc) const
{
StreamHAManager::tterm();
FlushBucket::clear();
-
- // this can't happen sooner because the counts haven't been harvested yet
- delete flow_con;
- flow_con = nullptr;
TcpStreamTracker::thread_term();
}
return ( flows_to_delete ) ? false : true;
}
+bool StreamUnloadReloadResourceManager::tinit()
+{
+ unsigned max_flows = flow_con->get_flow_cache_config().max_flows;
+ if (max_flows)
+ {
+ stream_base_stats.reload_total_deletes += max_flows;
+ return true;
+ }
+ return false;
+}
+
+bool StreamUnloadReloadResourceManager::tune_packet_context()
+{
+ ++stream_base_stats.reload_tuning_packets;
+ return tune_resources(max_work);
+}
+
+bool StreamUnloadReloadResourceManager::tune_idle_context()
+{
+ ++stream_base_stats.reload_tuning_idle;
+ return tune_resources(max_work_idle);
+}
+
+bool StreamUnloadReloadResourceManager::tune_resources(unsigned work_limit)
+{
+ unsigned flows_to_delete = flow_con->get_flows_allocated();
+
+ if (!flows_to_delete)
+ return true;
+
+ if (flows_to_delete > work_limit)
+ flows_to_delete -= flow_con->delete_flows(work_limit);
+ else
+ flows_to_delete -= flow_con->delete_flows(flows_to_delete);
+
+ return (flows_to_delete) ? false : true;
+}
+
void StreamModuleConfig::show() const
{
ConfigLogger::log_value("max_flows", flow_cache_cfg.max_flows);
timeval reload_time{};
};
+class StreamUnloadReloadResourceManager : public snort::ReloadResourceTuner
+{
+public:
+ StreamUnloadReloadResourceManager() { }
+
+ bool tinit() override;
+ bool tune_packet_context() override;
+ bool tune_idle_context() override;
+
+private:
+ bool tune_resources(unsigned work_limit);
+};
+
class StreamModule : public snort::Module
{
public:
{ ma_pseudo_packet = new Packet(false); }
void TcpSegmentDescriptor::clear()
-{ delete ma_pseudo_packet; }
+{
+ delete ma_pseudo_packet;
+ ma_pseudo_packet = nullptr;
+}
uint32_t TcpSegmentDescriptor::init_mss(uint16_t* value)
{