]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2020 in SNORT/snort3 from ~SBAIGAL/snort3:so_reload_2 to master
authorSteve Chew (stechew) <stechew@cisco.com>
Mon, 2 Mar 2020 15:39:36 +0000 (15:39 +0000)
committerSteve Chew (stechew) <stechew@cisco.com>
Mon, 2 Mar 2020 15:39:36 +0000 (15:39 +0000)
Squashed commit of the following:

commit 0ffe1aa821d7d4e092a64173900e9a264f999dde
Author: Steven Baigal (sbaigal) <sbaigal@cisco.com>
Date:   Wed Feb 19 11:01:43 2020 -0500

    plugin_manager: add support for reload so_rule plugins

13 files changed:
src/ips_options/ips_so.cc
src/main.cc
src/main/help.cc
src/main/snort.cc
src/main/snort.h
src/main/snort_config.cc
src/main/snort_config.h
src/main/snort_module.cc
src/managers/plugin_manager.cc
src/managers/plugin_manager.h
src/managers/so_manager.cc
src/managers/so_manager.h
src/parser/parse_rule.cc

index ce7b452a34b8d6cbada391bd7a8be506a46b3063..f9470221089cbd58c87831f573825d8ba14145a6 100644 (file)
@@ -27,6 +27,7 @@
 #include "framework/so_rule.h"
 #include "hash/hash_key_operations.h"
 #include "log/messages.h"
+#include "main/snort_config.h"
 #include "managers/so_manager.h"
 #include "profiler/profiler.h"
 
@@ -40,7 +41,7 @@ static THREAD_LOCAL ProfileStats soPerfStats;
 class SoOption : public IpsOption
 {
 public:
-    SoOption(const char*, const char*, bool, SoEvalFunc f, void* v);
+    SoOption(const char*, const char*, bool, SoEvalFunc f, void* v, SnortConfig*);
     ~SoOption() override;
 
     uint32_t hash() const override;
@@ -57,10 +58,11 @@ private:
     bool relative_flag;
     SoEvalFunc func;
     void* data;
+    SoRules* so_rules;
 };
 
 SoOption::SoOption(
-    const char* id, const char* s, bool r, SoEvalFunc f, void* v)
+    const char* id, const char* s, bool r, SoEvalFunc f, void* v, SnortConfig* sc)
     : IpsOption(s_name)
 {
     soid = id;
@@ -68,12 +70,12 @@ SoOption::SoOption(
     relative_flag = r;
     func = f;
     data = v;
+    so_rules = sc->so_rules;
 }
 
 SoOption::~SoOption()
 {
-    if ( data )
-        SoManager::delete_so_data(soid, data);
+    SoManager::delete_so_data(soid, data, so_rules);
 }
 
 uint32_t SoOption::hash() const
@@ -142,12 +144,14 @@ public:
 public:
     string name;
     bool relative_flag;
+    SnortConfig* cfg;
 };
 
-bool SoModule::begin(const char*, int, SnortConfig*)
+bool SoModule::begin(const char*, int, SnortConfig* sc)
 {
     name.clear();
     relative_flag = false;
+    cfg = sc;
     return true;
 }
 
@@ -191,14 +195,14 @@ static IpsOption* so_ctor(Module* p, OptTreeNode* otn)
         ParseError("no soid before so:%s", name);
         return nullptr;
     }
-    SoEvalFunc func = SoManager::get_so_eval(otn->soid, name, &data);
+    SoEvalFunc func = SoManager::get_so_eval(otn->soid, name, &data, m->cfg);
 
     if ( !func )
     {
         ParseError("can't link so:%s", name);
         return nullptr;
     }
-    return new SoOption(otn->soid, name, relative_flag, func, data);
+    return new SoOption(otn->soid, name, relative_flag, func, data, m->cfg);
 }
 
 static void so_dtor(IpsOption* p)
index 1b0ae01eda7a76f38ff21e3ecc20e5a6b16586e8..f95e191b5c2d226ba3c798b6fe18f0a5f8bd6c1e 100644 (file)
@@ -329,16 +329,24 @@ int main_reload_config(lua_State* L)
         return 0;
     }
     const char* fname =  nullptr;
+    const char* plugin_path =  nullptr;
 
     if ( L )
     {
         Lua::ManageStack(L, 1);
         fname = luaL_checkstring(L, 1);
+        if (lua_gettop(L) > 1)
+        {
+            plugin_path = luaL_checkstring(L, 2);
+            std::ostringstream plugin_path_msg;
+            plugin_path_msg << "-- reload plugin_path: " << plugin_path << "\n";
+            current_request->respond(plugin_path_msg.str().c_str());
+        }
     }
 
     current_request->respond(".. reloading configuration\n");
     SnortConfig* old = SnortConfig::get_conf();
-    SnortConfig* sc = Snort::get_reload_config(fname);
+    SnortConfig* sc = Snort::get_reload_config(fname, plugin_path);
 
     if ( !sc )
     {
@@ -361,10 +369,12 @@ int main_reload_config(lua_State* L)
 
     if ( !tc )
     {
+        // FIXIT-L it does not seem a valid check, delete old config if come to it
         current_request->respond("== reload failed - bad config\n");
         SnortConfig::set_parser_conf(nullptr);
         return 0;
     }
+    PluginManager::reload_so_plugins_cleanup(sc);
     SnortConfig::set_conf(sc);
     proc_stats.conf_reloads++;
 
index 1599a62b14b84a282913e7298d66a182161cf1fc..fa9e689a4c341e4bc0e40f5789cf2ef2bcb72a68 100644 (file)
@@ -155,6 +155,7 @@ enum HelpType
     SnortConfig::set_conf(new SnortConfig);
     ScriptManager::load_scripts(sc->script_paths);
     PluginManager::load_plugins(sc->plugin_path);
+    PluginManager::load_so_plugins(sc);
     ModuleManager::init();
 
     switch ( ht )
@@ -172,7 +173,7 @@ enum HelpType
         ModuleManager::dump_rules(val);
         break;
     case HT_DDR:
-        SoManager::dump_rule_stubs(val);
+        SoManager::dump_rule_stubs(val, sc);
         break;
     case HT_DFL:
         ModuleManager::dump_defaults(val);
index 22ddc02e3938412301ff59f1c418127564b79319..45c4548fc4da2a01f0fd66b8e9b82a3bf3e91e19 100644 (file)
@@ -155,7 +155,7 @@ void Snort::init(int argc, char** argv)
      * Set the global snort_conf that will be used during run time */
     sc->merge(snort_cmd_line_conf);
     SnortConfig::set_conf(sc);
-
+    PluginManager::load_so_plugins(sc);
 #ifdef PIGLET
     if ( !Piglet::piglet_mode() )
 #endif
@@ -428,7 +428,7 @@ void Snort::reload_failure_cleanup(SnortConfig* sc)
 
 // 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)
+SnortConfig* Snort::get_reload_config(const char* fname, const char* plugin_path)
 {
     reloading = true;
     ModuleManager::reset_errors();
@@ -445,6 +445,8 @@ SnortConfig* Snort::get_reload_config(const char* fname)
         return nullptr;
     }
 
+    PluginManager::reload_so_plugins(plugin_path, sc);
+
     sc->setup();
 
 #ifdef SHELL
index efe5a9e7503c80123ea9f739262d93b00ea903e6..3efeb7fc4636cc140d3182baa0cd7d6f66607a60 100644 (file)
@@ -38,7 +38,7 @@ struct SnortConfig;
 class Snort
 {
 public:
-    static SnortConfig* get_reload_config(const char* fname);
+    static SnortConfig* get_reload_config(const char* fname, const char* plugin_path = nullptr);
     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[]);
index 6a736a2c9c86ee55f442d1e409b384131bd1f013..3fb2de0cf85a4c75c821ad2a24693ff0fd3c7c01 100644 (file)
@@ -47,6 +47,8 @@
 #include "managers/ips_manager.h"
 #include "managers/module_manager.h"
 #include "managers/mpse_manager.h"
+#include "managers/plugin_manager.h"
+#include "managers/so_manager.h"
 #include "memory/memory_config.h"
 #include "packet_io/sfdaq.h"
 #include "packet_io/sfdaq_config.h"
@@ -209,6 +211,7 @@ void SnortConfig::init(const SnortConfig* const other_conf, ProtocolReference* p
         memset(evalOrder, 0, sizeof(evalOrder));
         proto_ref = new ProtocolReference(protocol_reference);
         flowbits_ginit(this);
+        so_rules = new SoRules;
     }
     else
     {
@@ -304,7 +307,9 @@ SnortConfig::~SnortConfig()
     delete memory;
     delete daq_config;
     delete proto_ref;
-
+    delete so_rules;
+    if ( plugins )
+        delete plugins;
     reload_tuners.clear();
 
     trim_heap();
index 4c5dcdc1b00df7c740b3b58c1c8c53461861969d..ce428f451554e20dcbc3406e4bab341adc7362a3 100644 (file)
@@ -136,12 +136,14 @@ struct HighAvailabilityConfig;
 struct IpsActionsConfig;
 struct LatencyConfig;
 struct MemoryConfig;
+struct Plugins;
 struct PORT_RULE_MAP;
 struct RateFilterConfig;
 struct ReferenceSystemNode;
 struct RuleListNode;
 struct RulePortTables;
 struct SFDAQConfig;
+struct SoRules;
 struct ThresholdConfig;
 struct VarNode;
 
@@ -413,7 +415,8 @@ public:
     //Reload inspector related
 
     bool cloned = false;
-
+    Plugins* plugins = nullptr;
+    SoRules* so_rules = nullptr;
 private:
     std::list<ReloadResourceTuner*> reload_tuners;
 
index a6d5f750fc02226887aebdc7465af4667b2882c6..17cd9c3c0c47608487f843954083079d866c923b 100644 (file)
@@ -65,6 +65,14 @@ static const Parameter s_reload[] =
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
+static const Parameter s_reload_w_path[] =
+{
+    { "filename", Parameter::PT_STRING, "(optional)", nullptr,
+      "[<plugin path>] name of file to load" },
+
+    { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
+};
+
 static const Parameter s_delete[] =
 {
     { "inspector", Parameter::PT_STRING, nullptr, nullptr,
@@ -98,7 +106,7 @@ static const Command snort_cmds[] =
 
     { "dump_stats", main_dump_stats, nullptr, "show summary statistics" },
     { "rotate_stats", main_rotate_stats, nullptr, "roll perfmonitor log files" },
-    { "reload_config", main_reload_config, s_reload, "load new configuration" },
+    { "reload_config", main_reload_config, s_reload_w_path, "load new configuration" },
     { "reload_policy", main_reload_policy, s_reload, "reload part or all of the default policy" },
     { "reload_module", main_reload_module, s_module, "reload module" },
     { "reload_daq", main_reload_daq, nullptr, "reload daq module" },
index a0ea0c35dd74c977e875b81e5002b94500dc8a57..63fc5a3f1b3a6e1bbd02d19a6c7d1358d29ce8e4 100644 (file)
@@ -25,7 +25,6 @@
 
 #include <dlfcn.h>
 #include <iostream>
-#include <map>
 #include <sstream>
 #include <sys/stat.h>
 
@@ -36,6 +35,7 @@
 #include "helpers/directory.h"
 #include "helpers/markup.h"
 #include "log/messages.h"
+#include "main/snort_config.h"
 
 #ifdef PIGLET
 #include "piglet/piglet_api.h"
@@ -125,31 +125,24 @@ struct Plugin
 {
     string source;
     string key;
-
-    const BaseApi* api;
-    void* handle;
-
-    Plugin()
-    { clear(); }
-
-    void clear()
-    { source.clear(); key.clear(); api = nullptr; handle = nullptr; }
+    const BaseApi* api = nullptr;
+    SoHandlePtr handle;
 };
 
-typedef std::map<string, Plugin> PlugMap;
-static PlugMap plug_map;
-
-struct RefCount
+Plugins::~Plugins()
 {
-    unsigned count;
-
-    RefCount() { count = 0; }
+    plug_map.clear();
+}
 
-    //~RefCount() { assert(!count); }; // FIXIT-L fails on fatal error
-};
+SoHandle::~SoHandle()
+{
+#ifndef REG_TEST
+    if ( handle )
+        dlclose(handle);
+#endif
+}
 
-typedef std::map<void*, RefCount> RefMap;
-static RefMap ref_map;
+static Plugins s_plugins;
 
 static void set_key(string& key, Symbol* sym, const char* name)
 {
@@ -178,8 +171,16 @@ static bool compatible_builds(const char* plug_opts)
     return true;
 }
 
+static bool plugin_is_reloadable(const BaseApi* api)
+{
+    if ( api->type == PT_SO_RULE )
+        return true;
+    else
+        return false;
+}
+
 static bool register_plugin(
-    const BaseApi* api, void* handle, const char* file)
+    const BaseApi* api, SoHandlePtr handle, const char* file, SnortConfig* sc)
 {
     if ( api->type >= PT_MAX )
         return false;
@@ -206,20 +207,17 @@ static bool register_plugin(
         return false;
     }
 
-    // validate api ?
+    if ( sc and !plugin_is_reloadable(api) )
+        return false;
 
     string key;
     set_key(key, sym, api->name);
 
-    Plugin& p = plug_map[key];
-
+    Plugin& p = ( sc ? sc->plugins->plug_map[key] : s_plugins.plug_map[key] );
     if ( p.api )
     {
-        if ( p.api->version >= api->version)
+        if ( p.api->version > api->version )
             return false;  // keep the old one
-
-        if ( p.handle && !--ref_map[p.handle].count )
-            dlclose(p.handle); // drop the old one
     }
 
     p.key = key;
@@ -227,28 +225,35 @@ static bool register_plugin(
     p.handle = handle;
     p.source = file;
 
-    if ( handle )
-        ++ref_map[handle].count;
-
     return true;
 }
 
 static void load_list(
-    const BaseApi** api, void* handle = nullptr, const char* file = "static")
+    const BaseApi** api, void* handle = nullptr, const char* file = "static", SnortConfig* sc = nullptr)
 {
-    bool keep = false;
+    SoHandlePtr so_file;
+    if ( handle and sc )
+    {   // for reload, if the so lib file was previously opened, reuse the shared_ptr
+        for( auto const& i : s_plugins.plug_map )
+        {
+            if ( i.second.api == (*api) and i.second.handle.get()->handle == handle )
+            {
+                so_file = i.second.handle;
+                break;
+            }
+        }
+    }
+    if ( !so_file.get() )
+        so_file = std::make_shared<SoHandle>(handle);
 
     while ( *api )
     {
-        keep = register_plugin(*api, handle, file) || keep;
-        //printf("loaded %s\n", (*api)->name);
+        register_plugin(*api, so_file, file, sc);
         ++api;
     }
-    if ( handle && !keep )
-        dlclose(handle);
 }
 
-static bool load_lib(const char* file)
+static bool load_lib(const char* file, SnortConfig* sc)
 {
     struct stat fs;
     void* handle;
@@ -272,7 +277,7 @@ static bool load_lib(const char* file)
         dlclose(handle);
         return false;
     }
-    load_list(api, handle, file);
+    load_list(api, handle, file, sc);
     return true;
 }
 
@@ -314,7 +319,7 @@ static void add_plugin(Plugin& p)
         break;
 
     case PT_SO_RULE:
-        SoManager::add_plugin((const SoApi*)p.api);
+        // SO rules are added later
         break;
 
     case PT_LOGGER:
@@ -337,7 +342,7 @@ static void add_plugin(Plugin& p)
     }
 }
 
-static void load_plugins(const std::string& paths)
+static void load_plugins(const std::string& paths, SnortConfig* sc = nullptr)
 {
     struct stat sb;
     stringstream paths_stream(paths);
@@ -358,40 +363,27 @@ static void load_plugins(const std::string& paths)
             Directory d(path.c_str(), lib_pattern);
 
             while ( const char* f = d.next() )
-                load_lib(f);
+                load_lib(f, sc);
         }
         else
         {
             if ( path.find("/") == string::npos )
                 path = "./" + path;
 
-            load_lib(path.c_str());
+            load_lib(path.c_str(), sc);
         }
     }
 }
 
 static void add_plugins()
 {
-    PlugMap::iterator it;
-
-    for ( it = plug_map.begin(); it != plug_map.end(); ++it )
+    for ( auto it = s_plugins.plug_map.begin(); it != s_plugins.plug_map.end(); ++it )
         add_plugin(it->second);
 }
 
 static void unload_plugins()
 {
-    for ( PlugMap::iterator it = plug_map.begin(); it != plug_map.end(); ++it )
-    {
-        if ( it->second.handle )
-            --ref_map[it->second.handle].count;
-
-        it->second.clear();
-    }
-
-#ifndef REG_TEST
-    for ( RefMap::iterator it = ref_map.begin(); it != ref_map.end(); ++it )
-        dlclose(it->first);
-#endif
+    s_plugins.plug_map.clear();
 }
 
 //-------------------------------------------------------------------------
@@ -417,11 +409,43 @@ void PluginManager::load_plugins(const std::string& paths)
     add_plugins();
 }
 
-void PluginManager::list_plugins()
+void PluginManager::reload_so_plugins(const char* paths, SnortConfig* sc)
+{
+    sc->plugins = new Plugins;
+    sc->plugins->plug_map = s_plugins.plug_map;
+    if ( paths )
+    {
+        // once plugin_path is provided for reload, old so_rules will be dropped
+        for( auto i = sc->plugins->plug_map.begin(); i != sc->plugins->plug_map.end(); ++i )
+            if ( plugin_is_reloadable(i->second.api) )
+                sc->plugins->plug_map.erase(i);
+        ::load_plugins(paths, sc);
+    }
+    load_so_plugins(sc, true);
+}
+
+void PluginManager::reload_so_plugins_cleanup(SnortConfig* sc)
 {
-    PlugMap::iterator it;
+    if ( !sc->plugins )
+        return;
 
-    for ( it = plug_map.begin(); it != plug_map.end(); ++it )
+    // set the new plugins to current
+    s_plugins.plug_map.clear();
+    s_plugins.plug_map = sc->plugins->plug_map;
+    sc->plugins->plug_map.clear();
+}
+
+void PluginManager::load_so_plugins(SnortConfig* sc, bool is_reload)
+{
+    auto p = is_reload ? sc->plugins->plug_map : s_plugins.plug_map;
+    for ( auto it = p.begin(); it != p.end(); ++it )
+        if ( it->second.api->type == PT_SO_RULE )
+            SoManager::add_plugin((const SoApi*)it->second.api, sc, it->second.handle);
+}
+
+void PluginManager::list_plugins()
+{
+    for ( auto it = s_plugins.plug_map.begin(); it != s_plugins.plug_map.end(); ++it )
     {
         Plugin& p = it->second;
         cout << Markup::item();
@@ -434,9 +458,7 @@ void PluginManager::list_plugins()
 
 void PluginManager::show_plugins()
 {
-    PlugMap::iterator it;
-
-    for ( it = plug_map.begin(); it != plug_map.end(); ++it )
+    for ( auto it = s_plugins.plug_map.begin(); it != s_plugins.plug_map.end(); ++it )
     {
         Plugin& p = it->second;
 
@@ -464,7 +486,6 @@ void PluginManager::release_plugins()
     ActionManager::release_plugins();
     InspectorManager::release_plugins();
     IpsManager::release_plugins();
-    SoManager::release_plugins();
     MpseManager::release_plugins();
     CodecManager::release_plugins();
     ConnectorManager::release_plugins();
@@ -480,9 +501,9 @@ const BaseApi* PluginManager::get_api(PlugType type, const char* name)
     string key;
     set_key(key, symbols+type, name);
 
-    const PlugMap::iterator it = plug_map.find(key);
+    auto it = s_plugins.plug_map.find(key);
 
-    if ( it != plug_map.end() )
+    if ( it != s_plugins.plug_map.end() )
         return it->second.api;
 
     return nullptr;
@@ -491,7 +512,7 @@ const BaseApi* PluginManager::get_api(PlugType type, const char* name)
 #ifdef PIGLET
 PlugType PluginManager::get_type_from_name(const std::string& name)
 {
-    for ( auto it = plug_map.begin(); it != plug_map.end(); ++it )
+    for ( auto it = s_plugins.plug_map.begin(); it != s_plugins.plug_map.end(); ++it )
     {
         const auto* api = it->second.api;
         if ( name == api->name )
@@ -562,8 +583,7 @@ const char* PluginManager::get_available_plugins(PlugType t)
 {
     static std::string s;
     s.clear();
-
-    for ( auto it = plug_map.begin(); it != plug_map.end(); ++it )
+    for ( auto it = s_plugins.plug_map.begin(); it != s_plugins.plug_map.end(); ++it )
     {
         const auto* api = it->second.api;
 
@@ -577,4 +597,3 @@ const char* PluginManager::get_available_plugins(PlugType t)
     }
     return s.c_str();
 }
-
index a8a13d52fd8997b46aeb57036053c8e33aaa6d94..48b8f4a83572ebbf915954a9d10c96b3c28792d3 100644 (file)
@@ -31,6 +31,8 @@
 //    based on configuration.
 //-------------------------------------------------------------------------
 
+#include <map>
+#include <memory>
 #include <string>
 
 #include "framework/base_api.h"
@@ -67,7 +69,27 @@ public:
         const char* name);
 
     static const char* get_available_plugins(PlugType);
+    static void load_so_plugins(snort::SnortConfig*, bool is_reload = false);
+    static void reload_so_plugins(const char*, snort::SnortConfig*);
+    static void reload_so_plugins_cleanup(snort::SnortConfig*);
 };
 
+struct Plugin;
+struct Plugins
+{
+    std::map<std::string, Plugin> plug_map;
+    ~Plugins();
+};
+
+struct SoHandle
+{
+    void* handle;
+
+    SoHandle(void* h) : handle(h) { }
+    ~SoHandle();
+};
+
+using SoHandlePtr = std::shared_ptr<SoHandle>;
+
 #endif
 
index 1bf2b3437e56795804fa96b7f1e0c410d732e45a..8c8c8b046a89e3d31504396d4f29291ceb5e8140 100644 (file)
 #include <cstring>
 #include <iomanip>
 #include <iostream>
-#include <list>
 #include <sstream>
 
 #include "log/messages.h"
+#include "main/snort_config.h"
 #include "parser/parse_so_rule.h"
 
 using namespace snort;
 using namespace std;
 
-static list<const SoApi*> s_rules;
-
 //-------------------------------------------------------------------------
 // plugins
 //-------------------------------------------------------------------------
-
-void SoManager::add_plugin(const SoApi* api)
+SoRules::~SoRules()
 {
-    s_rules.emplace_back(api);
+    api.clear();
+    handles.clear();
 }
 
-void SoManager::release_plugins()
+void SoManager::add_plugin(const SoApi* api, SnortConfig* sc, SoHandlePtr handle)
 {
-    s_rules.clear();
+    sc->so_rules->api.emplace_back(api);
+    sc->so_rules->handles.emplace_back(handle);
 }
 
 void SoManager::dump_plugins()
 {
     Dumper d("SO Rules");
 
-    for ( auto* p : s_rules )
+    for ( auto* p : SnortConfig::get_conf()->so_rules->api )
         d.dump(p->base.name, p->base.version);
 }
 
@@ -186,18 +185,18 @@ static const char* revert(const uint8_t* data, unsigned len)
 
 //-------------------------------------------------------------------------
 
-static const SoApi* get_so_api(const char* soid)
+static const SoApi* get_so_api(const char* soid, SoRules* so_rules)
 {
-    for ( auto* p : s_rules )
+    for ( auto* p : so_rules->api )
         if ( !strcmp(p->base.name, soid) )
             return p;
 
     return nullptr;
 }
 
-const char* SoManager::get_so_rule(const char* soid)
+const char* SoManager::get_so_rule(const char* soid, SnortConfig* sc)
 {
-    const SoApi* api = get_so_api(soid);
+    const SoApi* api = get_so_api(soid, sc->so_rules);
 
     if ( !api )
         return nullptr;
@@ -207,9 +206,9 @@ const char* SoManager::get_so_rule(const char* soid)
     return rule;
 }
 
-SoEvalFunc SoManager::get_so_eval(const char* soid, const char* so, void** data)
+SoEvalFunc SoManager::get_so_eval(const char* soid, const char* so, void** data, SnortConfig* sc)
 {
-    const SoApi* api = get_so_api(soid);
+    const SoApi* api = get_so_api(soid, sc->so_rules);
 
     if ( !api || !api->ctor )
         return nullptr;
@@ -217,9 +216,11 @@ SoEvalFunc SoManager::get_so_eval(const char* soid, const char* so, void** data)
     return api->ctor(so, data);
 }
 
-void SoManager::delete_so_data(const char* soid, void* pv)
+void SoManager::delete_so_data(const char* soid, void* pv, SoRules* so_rules)
 {
-    const SoApi* api = get_so_api(soid);
+    if (!pv or !so_rules)
+        return;
+    const SoApi* api = get_so_api(soid, so_rules);
 
     if ( api && api->dtor )
         api->dtor(pv);
@@ -227,11 +228,11 @@ void SoManager::delete_so_data(const char* soid, void* pv)
 
 //-------------------------------------------------------------------------
 
-void SoManager::dump_rule_stubs(const char*)
+void SoManager::dump_rule_stubs(const char*, SnortConfig* sc)
 {
     unsigned c = 0;
 
-    for ( auto* p : s_rules )
+    for ( auto* p : sc->so_rules->api )
     {
         const char* rule = revert(p->rule, p->length);
 
index ae30f0a7dd2901a3f3ac1db3f8f1d00790e58f89..bbcc89e1997b488c455567923610c6e91ea073fe 100644 (file)
 
 // Factory for shared object rules.
 // Runtime is same as for text rules.
-
+#include <list>
 #include "framework/so_rule.h"
+#include "managers/plugin_manager.h"
 
 namespace snort
 {
 struct SnortConfig;
 }
-struct SoApi;
 
 //-------------------------------------------------------------------------
+struct SoRules
+{
+    std::list<const SoApi*> api;
+    std::list<SoHandlePtr> handles;
+    ~SoRules();
+};
 
 class SoManager
 {
 public:
-    static void add_plugin(const SoApi*);
+    static void add_plugin(const SoApi*, snort::SnortConfig*, SoHandlePtr);
     static void dump_plugins();
-    static void release_plugins();
 
     static void instantiate(const SoApi*);
 
     // soid is arg to soid option, so is arg to so option
-    static const char* get_so_rule(const char* soid);
-    static SoEvalFunc get_so_eval(const char* soid, const char* so, void** data);
-    static void delete_so_data(const char* soid, void*);
+    static const char* get_so_rule(const char* soid, snort::SnortConfig* sc = nullptr);
+    static SoEvalFunc get_so_eval(const char* soid, const char* so,
+        void** data, snort::SnortConfig* sc = nullptr);
+    static void delete_so_data(const char* soid, void*, SoRules*);
 
     static void rule_to_hex(const char* file);
     static void rule_to_text(const char* file);
-    static void dump_rule_stubs(const char*);
+    static void dump_rule_stubs(const char*, snort::SnortConfig*);
 };
 
 #endif
index fae711f51782372e992e94a49ce86c521dfe422a..e23a5d342422e79b0a6638df224a225adf43da7d 100644 (file)
@@ -1147,7 +1147,7 @@ void parse_rule_close(SnortConfig* sc, RuleTreeNode& rtn, OptTreeNode* otn)
         if ( rtn.dip )
             sfvar_free(rtn.dip);
 
-        const char* rule = SoManager::get_so_rule(otn->soid);
+        const char* rule = SoManager::get_so_rule(otn->soid, sc);
         IpsManager::reset_options();
 
         if ( !rule )