]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #953 in SNORT/snort3 from reload_inspector to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 4 Aug 2017 16:36:21 +0000 (12:36 -0400)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Fri, 4 Aug 2017 16:36:21 +0000 (12:36 -0400)
Squashed commit of the following:

commit c5ec856a1fd022d83fddc05eac88aa5969dede2c
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Thu Aug 3 23:53:09 2017 -0400

    control: dev notes updates, updates to code per review

commit 4c020ea967d22d3db38468fd46810c304bbba64e
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Mon Jul 31 09:35:40 2017 -0400

    control: updates to reload_policy per review

commit a1218168afb28e65253bd0a5e4984438e0214bba
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Wed Jul 26 12:39:02 2017 -0400

    control: enforce fname argument for reload policy

commit 80a3a2d95d0738818017904920546e42738d3cd7
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Wed Jul 26 12:17:29 2017 -0400

    control: renaming the stats for policy reloads

commit fa2456f55f3cd0925a227ca0e26083b87ee91c26
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Wed Jul 26 11:37:55 2017 -0400

    control: update snort_config.cc per master

commit 408f6872cda9970d940ea8623486fdb829e36024
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Sun Jul 23 16:16:49 2017 -0400

    updating unit tests

commit 249eeee92fdcff74e4fd093e4c5022451aeb484f
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Sat Jul 22 16:07:28 2017 -0400

    control: update binder with new inspector

commit cd0b2b8f38af2d1a38f4b6aedb574791ccf30512
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Mon Jul 17 21:44:41 2017 -0400

    control: Changes per code review : reinstantiate default binder when inspectors are enabled. rename command to reload_policy

commit 06e84c034ec8da7fe8daea2afb8d0ed9e26136cc
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Fri Jul 14 16:48:34 2017 -0400

    control: delete the old binder while reloading inspector

commit 9b1928c8587b878b518eb7b5339ec290c613daa5
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Wed Jul 26 11:05:30 2017 -0400

    control: resolve merge conflicts

19 files changed:
src/dev_notes.txt
src/hash/test/sfghash_test.cc
src/ips_options/test/ips_regex_test.cc
src/main.cc
src/main.h
src/main/policy.cc
src/main/policy.h
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/inspector_manager.cc
src/managers/inspector_manager.h
src/managers/module_manager.cc
src/search_engines/test/hyperscan_test.cc
src/search_engines/test/search_tool_test.cc
src/utils/stats.cc
src/utils/stats.h

index 47e88274bf0535fce36edeca40066b0a388b7a99..a1a78ea0771e7a0271c6bfad4d9f146acb389d4b 100644 (file)
@@ -23,3 +23,16 @@ Reload is implemented by swapping a thread local config pointer by each
 running Pig.  The inspector manager is called to empty trash if the main
 loop is not otherwise busy.
 
+Reload policy is implemented by cloning the thread local config and 
+overwriting the policy map and the inspection policy in the main thread. 
+The inspector list from the old config's inspection policy is copied 
+into the inspection policy of the new config. After the config pointer 
+is cloned, the new inspection policy elements (reloadable) such as 
+inspectors, binder, wizard etc are read and instantiated. 
+The inspector list of the new config is updated by swapping out the 
+old inspectors, binder etc. with the newly instantiated elements. The
+reloaded inspectors, binders and other inspection policy elements are 
+marked for deletion. After the new inspection policy is loaded, the 
+thread local config pointer is swapped with the new cloned config 
+by running Pig. This happens in the packet thread. The inspector manager
+ is then called to delete any reloaded policy elements and empty trash. 
index 72ca020c8ac83d36c42c35b1713cace815f0c471..fe27ff77e3327dea64da553ad50bfcd43a99958b 100644 (file)
@@ -33,7 +33,8 @@
 // Stubs whose sole purpose is to make the test code link
 SnortConfig my_config;
 THREAD_LOCAL SnortConfig *snort_conf = &my_config;
-SnortConfig::SnortConfig() { snort_conf->run_flags = 0;} // run_flags is used indirectly from SFHASHFCN class by calling SnortConfig::static_hash()
+SnortConfig::SnortConfig(SnortConfig*) 
+{ snort_conf->run_flags = 0;} // run_flags is used indirectly from SFHASHFCN class by calling SnortConfig::static_hash()
 SnortConfig::~SnortConfig() {}
 // implement functions for virtual
 FileVerdict FilePolicy::type_lookup(Flow* , FileContext* ) { return FILE_VERDICT_UNKNOWN;}
index 1f72cdde8c053b8194482be16203d01c1d747f1d..0a59ede062511062f2d41bb2bebe4e2c1d356f07 100644 (file)
@@ -65,7 +65,7 @@ THREAD_LOCAL SnortConfig* snort_conf = &s_conf;
 
 static SnortState s_state;
 
-SnortConfig::SnortConfig()
+SnortConfig::SnortConfig(SnortConfig*)
 {
     state = &s_state;
     memset(state, 0, sizeof(*state));
index 1325d8a57b28d8b7d4712decda0b37e470414dc1..52e341d4cac5a7e2c52d8297d8f641a365e536d6 100644 (file)
@@ -329,6 +329,47 @@ int main_reload_config(lua_State* L)
     return 0;
 }
 
+int main_reload_policy(lua_State* L)
+{
+    if ( Swapper::get_reload_in_progress() )
+    {
+        current_request->respond("== reload pending; retry\n");
+        return 0;
+    }
+    const char* fname =  nullptr;
+
+    if ( L )
+    {
+        Lua::ManageStack(L, 1);
+        fname = luaL_checkstring(L, 1);
+    }
+
+    if ( fname and *fname )
+        current_request->respond(".. reloading policy\n");
+    else
+    {
+        current_request->respond("== filename required\n");
+        return 0;
+    }
+
+    SnortConfig* old = snort_conf;
+    SnortConfig* sc = Snort::get_reloaded_policy(old, fname);
+
+    if ( !sc )
+    {
+        current_request->respond("== reload failed\n");
+        return 0;
+    }
+    snort_conf = sc;
+    proc_stats.policy_reloads++;
+
+    bool from_shell = ( L != nullptr );
+    current_request->respond(".. swapping policy\n", from_shell);
+    broadcast(get_command(new ACSwap(new Swapper(old, sc)), from_shell));
+
+    return 0;
+}
+
 int main_reload_daq(lua_State* L)
 {
     bool from_shell = ( L != nullptr );
index 555ae3f8a4db5a30fb7f924775ed2e01d5f44d2a..c9a7e88e3c93709c51434bfc7d2791840d95c626 100644 (file)
@@ -29,6 +29,7 @@ const char* get_prompt();
 int main_dump_stats(lua_State* = nullptr);
 int main_rotate_stats(lua_State* = nullptr);
 int main_reload_config(lua_State* = nullptr);
+int main_reload_policy(lua_State* = nullptr);
 int main_reload_daq(lua_State* = nullptr);
 int main_reload_hosts(lua_State* = nullptr);
 int main_process(lua_State* = nullptr);
index b72cb0e17bcde2bbca4505746a8db2b032f28640..5a61ee18a7bc22a0ef43a34695ed09d337a32b6b 100644 (file)
@@ -65,16 +65,17 @@ public:
     { DetectionEngine::detect((Packet*)e.get_packet()); }  // FIXIT-L not const!
 };
 
-InspectionPolicy::InspectionPolicy()
+InspectionPolicy::InspectionPolicy(InspectionPolicy* other_inspection_policy)
 {
     framework_policy = nullptr;
+    cloned = false;
 
-    InspectorManager::new_policy(this);
+    InspectorManager::new_policy(this, other_inspection_policy);
 }
 
 InspectionPolicy::~InspectionPolicy()
 {
-    InspectorManager::delete_policy(this);
+    InspectorManager::delete_policy(this, cloned);
 }
 
 void InspectionPolicy::configure()
@@ -121,9 +122,12 @@ IpsPolicy::~IpsPolicy()
 // policy map
 //-------------------------------------------------------------------------
 
-PolicyMap::PolicyMap()
+PolicyMap::PolicyMap(PolicyMap* other_map)
 {
-    add_shell(new Shell);
+    if ( other_map )
+        clone(other_map);
+    else
+        add_shell(new Shell);
 
     set_inspection_policy(inspection_policy[0]);
     set_ips_policy(ips_policy[0]);
@@ -132,17 +136,29 @@ PolicyMap::PolicyMap()
 
 PolicyMap::~PolicyMap()
 {
-    for ( auto p : shells )
-        delete p;
+    if ( cloned )
+    {
+        if ( inspection_policy.size() )
+        {
+            InspectionPolicy* default_policy = inspection_policy[0];
+            default_policy->cloned = true;
+            delete default_policy;
+        }
+    }
+    else
+    {
+        for ( auto p : shells )
+            delete p;
 
-    for ( auto p : inspection_policy )
-        delete p;
+        for ( auto p : inspection_policy )
+            delete p;
 
-    for ( auto p : ips_policy )
-        delete p;
+        for ( auto p : ips_policy )
+            delete p;
 
-    for ( auto p : network_policy )
-        delete p;
+        for ( auto p : network_policy )
+            delete p;
+    }
 
     shells.clear();
     inspection_policy.clear();
@@ -150,6 +166,23 @@ PolicyMap::~PolicyMap()
     network_policy.clear();
 }
 
+void PolicyMap::clone(PolicyMap *other_map)
+{
+    shells = other_map->shells;
+    ips_policy = other_map->ips_policy;
+    network_policy = other_map->network_policy;
+
+    for ( unsigned i = 0; i < (other_map->inspection_policy.size()); i++)
+    {
+        if ( i == 0 )
+        {
+            inspection_policy.push_back(new InspectionPolicy(other_map->inspection_policy[i]));
+        }
+        else
+            inspection_policy.push_back(other_map->inspection_policy[i]);
+    }
+}
+
 unsigned PolicyMap::add_shell(Shell* sh)
 {
     unsigned idx = shells.size();
index cb156e64ea36b12c641a4bbfe4809b1da030d9bd..429152ea546aef8c078a4a65fc0aae684d2e789a 100644 (file)
@@ -85,7 +85,7 @@ public:
 struct InspectionPolicy
 {
 public:
-    InspectionPolicy();
+    InspectionPolicy(InspectionPolicy* old_inspection_policy = nullptr);
     ~InspectionPolicy();
 
     void configure();
@@ -93,6 +93,7 @@ public:
 public:
     struct FrameworkPolicy* framework_policy;
     DataBus dbus;
+    bool cloned;
 };
 
 //-------------------------------------------------------------------------
@@ -143,10 +144,11 @@ class Shell;
 class PolicyMap
 {
 public:
-    PolicyMap();
+    PolicyMap(PolicyMap* old_map = nullptr);
     ~PolicyMap();
 
     unsigned add_shell(Shell*);
+    void clone(PolicyMap *old_map);
 
     Shell* get_shell(unsigned i = 0)
     { return i < shells.size() ? shells[i] : nullptr; }
@@ -156,6 +158,7 @@ public:  // FIXIT-M make impl private
     std::vector<InspectionPolicy*> inspection_policy;
     std::vector<IpsPolicy*> ips_policy;
     std::vector<NetworkPolicy*> network_policy;
+    bool cloned = false;
 };
 
 //-------------------------------------------------------------------------
index ebf4c684ec98da21c77ca099b30dc9dcdba215b0..f1cfb9fb60f5c56e94c1a49681eee3af5637238a 100644 (file)
@@ -56,6 +56,7 @@
 #include "log/packet_tracer.h"
 #include "loggers/loggers.h"
 #include "main.h"
+#include "main/shell.h"
 #include "managers/action_manager.h"
 #include "managers/codec_manager.h"
 #include "managers/inspector_manager.h"
@@ -630,6 +631,41 @@ SnortConfig* Snort::get_reload_config(const char* fname)
     return sc;
 }
 
+SnortConfig* Snort::get_reloaded_policy(SnortConfig* other_conf, const char* fname)
+{
+    reloading = true;
+
+    SnortConfig* sc = new SnortConfig(other_conf);
+    Shell sh = Shell(fname);
+    sh.configure(sc);
+
+    if ( ModuleManager::get_errors() || !sc->verify() )
+    {
+        sc->cloned = true;
+        InspectorManager::update_policy(other_conf);
+        delete sc;
+        set_policies(other_conf);
+        reloading = false;
+        return nullptr;
+    }
+
+    if ( !InspectorManager::configure(sc, true) )
+    {
+        sc->cloned = true;
+        InspectorManager::update_policy(other_conf);
+        delete sc;
+        set_policies(other_conf);
+        reloading = false;
+        return nullptr;
+    }
+
+    other_conf->cloned = true;
+
+    InspectorManager::update_policy(sc);
+    reloading = false;
+    return sc;
+}
+
 void Snort::capture_packet()
 {
     if ( snort_main_thread_pid == gettid() )
index 449ad50ff2a2a04c78a5a56a4a7e8ffaf8b0cf34..cb19533ca2497b11b432f7088a8a4fa62492c830 100644 (file)
@@ -38,6 +38,7 @@ class Snort
 {
 public:
     static SnortConfig* get_reload_config(const char* fname);
+    static SnortConfig* get_reloaded_policy(SnortConfig*, const char* fname);
     static void setup(int argc, char* argv[]);
     static bool drop_privileges();
     static void do_pidfile();
index 44be55320717290eab11e72ef92dd70970b893b4..b25cf1c967ac5d673d6c1df1ac60c3bb751ba626 100644 (file)
@@ -168,37 +168,56 @@ static void init_policies(SnortConfig* sc)
  * but the goal is to minimize config checks at run time when running in
  * IDS mode so we keep things simple and enforce that the only difference
  * among run_modes is how we handle packets via the log_func. */
-SnortConfig::SnortConfig()
+SnortConfig::SnortConfig(SnortConfig* other_conf)
 {
-    num_layers = DEFAULT_LAYERMAX;
+    homenet.clear();
+    obfuscation_net.clear();
 
-    max_attribute_hosts = DEFAULT_MAX_ATTRIBUTE_HOSTS;
-    max_attribute_services_per_host = DEFAULT_MAX_ATTRIBUTE_SERVICES_PER_HOST;
+    if ( !other_conf )
+    {
+        num_layers = DEFAULT_LAYERMAX;
 
-    max_metadata_services = DEFAULT_MAX_METADATA_SERVICES;
-    mpls_stack_depth = DEFAULT_LABELCHAIN_LENGTH;
+        max_attribute_hosts = DEFAULT_MAX_ATTRIBUTE_HOSTS;
+        max_attribute_services_per_host = DEFAULT_MAX_ATTRIBUTE_SERVICES_PER_HOST;
 
-    daq_config = new SFDAQConfig();
-    InspectorManager::new_config(this);
+        max_metadata_services = DEFAULT_MAX_METADATA_SERVICES;
+        mpls_stack_depth = DEFAULT_LABELCHAIN_LENGTH;
 
-    num_slots = ThreadConfig::get_instance_max();
-    state = (SnortState*)snort_calloc(num_slots, sizeof(SnortState));
+        daq_config = new SFDAQConfig();
+        InspectorManager::new_config(this);
 
-    profiler = new ProfilerConfig;
-    latency = new LatencyConfig();
-    memory = new MemoryConfig();
-    policy_map = new PolicyMap;
-    thread_config = new ThreadConfig();
+        num_slots = ThreadConfig::get_instance_max();
+        state = (SnortState*)snort_calloc(num_slots, sizeof(SnortState));
 
-    homenet.clear();
-    obfuscation_net.clear();
+        profiler = new ProfilerConfig;
+        latency = new LatencyConfig();
+        memory = new MemoryConfig();
+        policy_map = new PolicyMap;
+        thread_config = new ThreadConfig();
 
-    memset(evalOrder, 0, sizeof(evalOrder));
-    proto_ref = new ProtocolReference;
+        memset(evalOrder, 0, sizeof(evalOrder));
+        proto_ref = new ProtocolReference;
+    }
+    else
+    {
+        clone(other_conf);
+        policy_map = new PolicyMap(other_conf->policy_map);
+    }
+
+    set_inspection_policy(get_inspection_policy());
+    set_ips_policy(get_ips_policy());
+    set_network_policy(get_network_policy());
 }
 
 SnortConfig::~SnortConfig()
 {
+    if ( cloned )
+    {
+        policy_map->cloned = true;
+        delete policy_map;
+        return;
+    }
+
     free_rule_state_list();
     FreeClassifications(classifications);
     FreeReferences(references);
@@ -298,6 +317,17 @@ void SnortConfig::post_setup()
 #endif
 }
 
+void SnortConfig::clone(SnortConfig* conf)
+{
+    *this = *conf;
+    if (conf->homenet.get_family() != 0)
+        memcpy(&homenet, &conf->homenet, sizeof(homenet));
+
+    if (conf->obfuscation_net.get_family() != 0)
+        memcpy(&obfuscation_net, &conf->obfuscation_net, sizeof(obfuscation_net));
+
+}
+
 // merge in everything from the command line config
 void SnortConfig::merge(SnortConfig* cmd_line)
 {
index c2199f746885cbfb028544700b90c92dd8a0d086..27712d83a5f85a7ee08650ebf3238b39caedcc61 100644 (file)
@@ -140,7 +140,7 @@ struct SnortState
 struct SnortConfig
 {
 public:
-    SnortConfig();
+    SnortConfig(SnortConfig* other_conf = nullptr );
     ~SnortConfig();
 
     void setup();
@@ -148,6 +148,7 @@ public:
     bool verify();
 
     void merge(SnortConfig*);
+    void clone(SnortConfig*);
 
 public:
     //------------------------------------------------------
@@ -347,6 +348,11 @@ public:
 
     ThreadConfig* thread_config;
 
+    //------------------------------------------------------
+    //Reload inspector related
+
+    bool cloned = false;
+
     //------------------------------------------------------
     // policy access
     InspectionPolicy* get_inspection_policy()
index 424b03b635c036efa25fc3a156c1757367543fab..afdbfd8b25fa90bd933642fb39c14ee6430a52af 100644 (file)
@@ -65,6 +65,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_policy", main_reload_policy, s_reload, "reload part or all of the default policy" },
     { "reload_daq", main_reload_daq, nullptr, "reload daq module" },
     { "reload_hosts", main_reload_hosts, s_reload, "load a new hosts table" },
 
index cdf2efb2953cb755072a6a703454b9c5e41fec53..61d4cfb1c92fad2aa6ee2b2cd02ecf1c032a420c 100644 (file)
@@ -33,6 +33,7 @@
 #include "flow/flow.h"
 #include "flow/session.h"
 #include "log/messages.h"
+#include "main/snort.h"
 #include "main/snort_config.h"
 #include "main/thread_config.h"
 #include "protocols/packet.h"
@@ -95,11 +96,19 @@ struct PHClass
     { return ( a->api.type < b->api.type ); }
 };
 
+enum ReloadType {
+    RELOAD_TYPE_NONE = 0,
+    RELOAD_TYPE_REENABLED,
+    RELOAD_TYPE_NEW,
+    RELOAD_TYPE_MAX
+};
+
 struct PHInstance
 {
     PHClass& pp_class;
     Inspector* handler;
     string name;
+    ReloadType reload_type;
 
     PHInstance(PHClass&, SnortConfig*, Module* = nullptr);
     ~PHInstance();
@@ -109,10 +118,21 @@ struct PHInstance
 
     void set_name(const char* s)
     { name = s; }
+
+    void set_reloaded(ReloadType val)
+    { reload_type = val; }
+
+    bool is_reloaded()
+    { return ((reload_type == RELOAD_TYPE_REENABLED) or
+            (reload_type == RELOAD_TYPE_NEW)); }
+
+    ReloadType get_reload_type()
+    { return reload_type; }
 };
 
 PHInstance::PHInstance(PHClass& p, SnortConfig* sc, Module* mod) : pp_class(p)
 {
+    reload_type = RELOAD_TYPE_NONE;
     handler = p.api.ctor(mod);
 
     if ( handler )
@@ -179,6 +199,8 @@ struct FrameworkPolicy
     Inspector* binder;
     Inspector* wizard;
 
+    bool default_binder;
+
     void vectorize();
 };
 
@@ -331,54 +353,51 @@ void InspectorManager::empty_trash()
 // policy stuff
 //-------------------------------------------------------------------------
 
-void InspectorManager::new_policy(InspectionPolicy* pi)
-{
-    pi->framework_policy = new FrameworkPolicy;
-
-    pi->framework_policy->binder = nullptr;
-    pi->framework_policy->wizard = nullptr;
-}
-
-void InspectorManager::delete_policy(InspectionPolicy* pi)
-{
-    for ( auto* p : pi->framework_policy->ilist )
-    {
-        if ( p->handler->get_api()->type == IT_PASSIVE )
-            s_trash2.push_back(p->handler);
-        else
-            s_trash.push_back(p->handler);
-        delete p;
-    }
-    delete pi->framework_policy;
-    pi->framework_policy = nullptr;
-}
-
 // FIXIT-L allowing lookup by name or type or key is kinda hinky
 // would be helpful to have specific lookups
-static PHInstance* get_instance(
-    FrameworkPolicy* fp, const char* keyword, bool dflt_only = false)
+static bool get_instance(
+        FrameworkPolicy* fp, const char* keyword, bool dflt_only, std::vector<PHInstance*>::iterator& it)
 {
-    for ( auto* p : fp->ilist )
+    for ( it = fp->ilist.begin(); it != fp->ilist.end(); ++it )
     {
+        PHInstance* p = *it;
         if ( p->name.size() && p->name == keyword )
-            return p;
+            return true;
 
         else if ( !strcmp(p->pp_class.api.base.name, keyword) )
-            return (!p->name.size() || !dflt_only) ? p : nullptr;
+            return (!p->name.size() || !dflt_only) ? true : false;
 
         else if ( p->pp_class.api.service && !strcmp(p->pp_class.api.service, keyword) )
-            return p;
+            return true;
     }
-    return nullptr;
+    return false;
+}
+
+static PHInstance* get_instance(
+        FrameworkPolicy* fp, const char* keyword, bool dflt_only = false)
+{
+    std::vector<PHInstance*>::iterator it;
+    return get_instance(fp, keyword, dflt_only, it)? *it : nullptr;
 }
 
 static PHInstance* get_new(
     PHClass* ppc, FrameworkPolicy* fp, const char* keyword, Module* mod, SnortConfig* sc)
 {
-    PHInstance* p = get_instance(fp, keyword);
+    PHInstance* p = nullptr;
+    bool reloaded = false;
+    std::vector<PHInstance*>::iterator old_it;
 
-    if ( p )
-        return p;
+    if ( get_instance(fp, keyword, false, old_it) )
+    {
+        if ( Snort::is_reloading() )
+        {
+            (*old_it)->set_reloaded(RELOAD_TYPE_REENABLED);
+            fp->ilist.erase(old_it);
+            reloaded = true;
+        }
+        else
+            return *old_it;
+    }
 
     p = new PHInstance(*ppc, sc, mod);
 
@@ -388,10 +407,59 @@ static PHInstance* get_new(
         return NULL;
     }
 
+    if ( Snort::is_reloading() )
+    {
+        if ( reloaded )
+            p->set_reloaded(RELOAD_TYPE_REENABLED);
+        else
+            p->set_reloaded(RELOAD_TYPE_NEW);
+    }
     fp->ilist.push_back(p);
     return p;
 }
 
+void InspectorManager::new_policy(InspectionPolicy* pi, InspectionPolicy* other_pi)
+{
+    pi->framework_policy = new FrameworkPolicy;
+    bool default_binder = false;
+
+    if ( other_pi )
+    {
+        pi->framework_policy->ilist = other_pi->framework_policy->ilist;
+        default_binder = other_pi->framework_policy->default_binder;
+    }
+
+    pi->framework_policy->default_binder = default_binder;
+    pi->framework_policy->binder = nullptr;
+    pi->framework_policy->wizard = nullptr;
+}
+
+void InspectorManager::delete_policy(InspectionPolicy* pi, bool cloned)
+{
+    for ( auto* p : pi->framework_policy->ilist )
+    {
+        if ( cloned and !(p->is_reloaded()) )
+                continue;
+
+        if ( p->handler->get_api()->type == IT_PASSIVE )
+            s_trash2.push_back(p->handler);
+        else
+            s_trash.push_back(p->handler);
+        delete p;
+    }
+    delete pi->framework_policy;
+    pi->framework_policy = nullptr;
+}
+
+void InspectorManager::update_policy(SnortConfig* sc)
+{
+    if ( sc->policy_map->inspection_policy.size() )
+    {
+        InspectionPolicy* pi = sc->policy_map->inspection_policy[0];
+        for ( auto* p : pi->framework_policy->ilist )
+            p->set_reloaded(RELOAD_TYPE_NONE);
+    }
+}
 // FIXIT-M create a separate list for meta handlers?  is there really more than one?
 void InspectorManager::dispatch_meta(FrameworkPolicy* fp, int type, const uint8_t* data)
 {
@@ -651,14 +719,51 @@ static void instantiate_binder(SnortConfig* sc, FrameworkPolicy* fp)
     InspectorManager::instantiate(api, m, sc);
     fp->binder = get_instance(fp, bind_id)->handler;
     fp->binder->configure(sc);
+    fp->default_binder = true;
 }
 
-static bool configure(SnortConfig* sc, FrameworkPolicy* fp)
+static bool configure(SnortConfig* sc, FrameworkPolicy* fp, bool cloned)
 {
     bool ok = true;
+    bool new_ins = false;
+    bool reenabled_ins = false;
 
     for ( auto* p : fp->ilist )
+    {
+        ReloadType reload_type = p->get_reload_type();
+
+        if ( cloned )
+        {
+            if ( reload_type == RELOAD_TYPE_NEW )
+                new_ins = true;
+            else if ( reload_type == RELOAD_TYPE_REENABLED )
+                reenabled_ins = true;
+            else
+                continue;
+        }
         ok = p->handler->configure(sc) && ok;
+    }
+
+    if ( new_ins or reenabled_ins )
+    {
+        std::vector<PHInstance*>::iterator old_binder;
+        if ( get_instance(fp, "binder", false, old_binder) )
+        {
+            if ( new_ins and fp->default_binder )
+            {
+                if ( !((*old_binder)->is_reloaded()) )
+                {
+                    (*old_binder)->set_reloaded(RELOAD_TYPE_REENABLED);
+                    fp->ilist.erase(old_binder);
+                }
+                fp->default_binder = false;
+            }
+            else if ( reenabled_ins and !((*old_binder)->is_reloaded()) )
+            {
+                (*old_binder)->handler->configure(sc);
+            }
+        }
+    }
 
     sort(fp->ilist.begin(), fp->ilist.end(), PHInstance::comp);
     fp->vectorize();
@@ -688,7 +793,7 @@ void InspectorManager::release(Inspector* pi)
     pi->rem_ref();
 }
 
-bool InspectorManager::configure(SnortConfig* sc)
+bool InspectorManager::configure(SnortConfig* sc, bool cloned)
 {
     if ( !s_sorted )
     {
@@ -699,10 +804,13 @@ bool InspectorManager::configure(SnortConfig* sc)
 
     for ( unsigned idx = 0; idx < sc->policy_map->inspection_policy.size(); ++idx )
     {
+        if ( cloned and idx )
+            break;
+
         set_policies(sc, idx);
         InspectionPolicy* p = sc->policy_map->inspection_policy[idx];
         p->configure();
-        ok = ::configure(sc, p->framework_policy) && ok;
+        ok = ::configure(sc, p->framework_policy, cloned) && ok;
     }
 
     set_policies(sc);
index e726a6b4240c4aea7a832de12f5bab7c19134c4b..d1fe4f0be4b8702321033a6996bd9dda2018722b 100644 (file)
@@ -44,8 +44,9 @@ public:
     static void dump_buffers();
     static void release_plugins();
 
-    static void new_policy(InspectionPolicy*);
-    static void delete_policy(InspectionPolicy*);
+    static void new_policy(InspectionPolicy*, InspectionPolicy*);
+    static void delete_policy(InspectionPolicy*, bool cloned);
+    static void update_policy(SnortConfig* sc);
 
     static void new_config(SnortConfig*);
     static void delete_config(SnortConfig*);
@@ -65,7 +66,7 @@ public:
     SO_PUBLIC static Inspector* acquire(const char* key, SnortConfig*);
     SO_PUBLIC static void release(Inspector*);
 
-    static bool configure(SnortConfig*);
+    static bool configure(SnortConfig*, bool cloned = false);
     static void print_config(SnortConfig*);
 
     static void thread_init(SnortConfig*);
index 9b502f1744ecd26033fd439bfb95cd4ade07375a..993087c9d6d6c17089ccd7810f16b6fd737d85da 100644 (file)
@@ -665,7 +665,8 @@ SO_PUBLIC bool open_table(const char* s, int idx)
         return false;
 
     // FIXIT-M only basic modules and inspectors can be reloaded at present
-    if ( Snort::is_reloading() and h->api and h->api->type != PT_INSPECTOR )
+    if ( ( Snort::is_reloading() )
+            and h->api and h->api->type != PT_INSPECTOR )
         return false;
 
     Module* m = h->mod;
index 1fd0990a8e1f3aa4dccb7f65d901c3c0c6e9a1a8..8c25cb83e862a97f040a90dd3b2a82efd3d33851 100644 (file)
@@ -78,7 +78,7 @@ THREAD_LOCAL SnortConfig* snort_conf = &s_conf;
 
 static SnortState s_state;
 
-SnortConfig::SnortConfig()
+SnortConfig::SnortConfig(SnortConfig*)
 {
     state = &s_state;
     memset(state, 0, sizeof(*state));
index bc185a478f7da049c746a6ee656242a001eaf06d..1c7bf15c0ac3d850482cd2023479e8a884017044 100644 (file)
@@ -47,7 +47,7 @@ THREAD_LOCAL SnortConfig* snort_conf = &s_conf;
 
 static SnortState s_state;
 
-SnortConfig::SnortConfig()
+SnortConfig::SnortConfig(SnortConfig*)
 {
     state = &s_state;
     memset(state, 0, sizeof(*state));
index 83871a38b47735506c8ad1a7f1ed09197f00ba48..67c102424d4cdcdecd6f4d7619b805174bdb5818 100644 (file)
@@ -218,6 +218,7 @@ const PegInfo proc_names[] =
     { "remote_commands", "total remote commands processed" },
     { "signals", "total signals processed" },
     { "conf_reloads", "number of times configuration was reloaded" },
+    { "policy_reloads", "number of times policies were reloaded" },
     { "daq_reloads", "number of times daq configuration was reloaded" },
     { "attribute_table_reloads", "number of times hosts table was reloaded" },
     { "attribute_table_hosts", "total number of hosts in table" },
index 84d9db66d2c480193607a542fe5526fd3ea89267..7e08423d952f663ec0a0e49c0f31c046f33964fe 100644 (file)
@@ -61,6 +61,7 @@ struct ProcessCount
     PegCount remote_commands;
     PegCount signals;
     PegCount conf_reloads;
+    PegCount policy_reloads;
     PegCount daq_reloads;
     PegCount attribute_table_reloads;
     PegCount attribute_table_hosts;