{
std::string command = next_command;
next_command.append(buf, nl - p);
+ LogMessage("Control: received command, %s\n", next_command.c_str());
pending_commands.push(std::move(next_command));
next_command.clear();
p = nl + 1;
bool is_removed() const { return removed; }
bool has_pending_command() const { return !pending_commands.empty(); }
time_t get_touched() const;
+ std::string get_current_command() const { return pending_commands.front(); }
void configure() const;
int read_commands();
#include "lua/lua.h"
#include "main/analyzer.h"
#include "main/analyzer_command.h"
+#include "main/reload_tracker.h"
#include "main/shell.h"
#include "main/snort.h"
#include "main/snort_config.h"
int main_reload_config(lua_State* L)
{
ControlConn* ctrlcon = ControlConn::query_from_lua(L);
- if ( Swapper::get_reload_in_progress() )
+ if ( !ReloadTracker::start(ctrlcon) )
{
send_response(ctrlcon, "== reload pending; retry\n");
return 0;
}
send_response(ctrlcon, ".. reloading configuration\n");
+ ReloadTracker::update(ctrlcon,"start loading ...");
const SnortConfig* old = SnortConfig::get_conf();
SnortConfig* sc = Snort::get_reload_config(fname, plugin_path, old);
{
std::string response_message = "== reload failed - restart required - ";
response_message += get_reload_errors_description() + "\n";
+ ReloadTracker::failed(ctrlcon, "restart required");
send_response(ctrlcon, response_message.c_str());
reset_reload_errors();
}
else
+ {
+ ReloadTracker::failed(ctrlcon, "bad config");
send_response(ctrlcon, "== reload failed - bad config\n");
+ }
+
HostAttributesManager::load_failure_cleanup();
return 0;
TraceApi::thread_reinit(sc->trace_config);
proc_stats.conf_reloads++;
+ ReloadTracker::update(ctrlcon, "start swapping configuration ...");
send_response(ctrlcon, ".. swapping configuration\n");
main_broadcast_command(new ACSwap(new Swapper(old, sc), ctrlcon), ctrlcon);
int main_reload_policy(lua_State* L)
{
ControlConn* ctrlcon = ControlConn::query_from_lua(L);
- if ( Swapper::get_reload_in_progress() )
+ if ( !ReloadTracker::start(ctrlcon) )
{
send_response(ctrlcon, "== reload pending; retry\n");
return 0;
send_response(ctrlcon, ".. reloading policy\n");
else
{
+ ReloadTracker::failed(ctrlcon, "filename required");
send_response(ctrlcon, "== filename required\n");
return 0;
}
if ( !sc )
{
+ ReloadTracker::failed(ctrlcon, "failed to update policy");
send_response(ctrlcon, "== reload failed\n");
return 0;
}
SnortConfig::set_conf(sc);
proc_stats.policy_reloads++;
+ ReloadTracker::update(ctrlcon, "start swapping configuration ...");
send_response(ctrlcon, ".. swapping policy\n");
main_broadcast_command(new ACSwap(new Swapper(old, sc), ctrlcon), ctrlcon);
int main_reload_module(lua_State* L)
{
ControlConn* ctrlcon = ControlConn::query_from_lua(L);
- if ( Swapper::get_reload_in_progress() )
+ if ( !ReloadTracker::start(ctrlcon) )
{
send_response(ctrlcon, "== reload pending; retry\n");
return 0;
send_response(ctrlcon, ".. reloading module\n");
else
{
+ ReloadTracker::failed(ctrlcon, "module name required");
send_response(ctrlcon, "== module name required\n");
return 0;
}
if ( !sc )
{
+ ReloadTracker::failed(ctrlcon, "failed to update module");
send_response(ctrlcon, "== reload failed\n");
return 0;
}
SnortConfig::set_conf(sc);
proc_stats.policy_reloads++;
+ ReloadTracker::update(ctrlcon, "start swapping configuration ...");
send_response(ctrlcon, ".. swapping module\n");
main_broadcast_command(new ACSwap(new Swapper(old, sc), ctrlcon), ctrlcon);
int main_reload_hosts(lua_State* L)
{
ControlConn* ctrlcon = ControlConn::query_from_lua(L);
- if ( Swapper::get_reload_in_progress() )
+ if ( !ReloadTracker::start(ctrlcon) )
{
- WarningMessage("Reload in progress. Cannot reload host attribute table.\n");
send_response(ctrlcon, "== reload pending; retry\n");
return 0;
}
if ( fname and *fname )
{
- LogMessage("Reloading Host attribute table from %s.\n", fname);
+ std::string msg = "Reloading Host attribute table from ";
+ msg += fname;
+ ReloadTracker::update(ctrlcon, msg.c_str());
send_response(ctrlcon, ".. reloading hosts table\n");
}
else
{
- ErrorMessage("Reload failed. Host attribute table filename required.\n");
+ ReloadTracker::failed(ctrlcon, "host attribute table filename required.");
send_response(ctrlcon, "== filename required\n");
return 0;
}
if ( !HostAttributesManager::load_hosts_file(sc, fname) )
{
- ErrorMessage("Host attribute table reload from %s failed.\n", fname);
+ ReloadTracker::failed(ctrlcon, "failed to load host table.");
send_response(ctrlcon, "== reload failed\n");
return 0;
}
assert( num_hosts >= 0 );
LogMessage("Host attribute table: %d hosts loaded successfully.\n", num_hosts);
+ ReloadTracker::update(ctrlcon, "start swapping configuration ...");
send_response(ctrlcon, ".. swapping hosts table\n");
main_broadcast_command(new ACHostAttributesSwap(ctrlcon), ctrlcon);
int main_delete_inspector(lua_State* L)
{
ControlConn* ctrlcon = ControlConn::query_from_lua(L);
- if ( Swapper::get_reload_in_progress() )
+ if ( !ReloadTracker::start(ctrlcon) )
{
send_response(ctrlcon, "== delete pending; retry\n");
return 0;
send_response(ctrlcon, ".. deleting inspector\n");
else
{
+ ReloadTracker::failed(ctrlcon, "inspector name required.");
send_response(ctrlcon, "== inspector name required\n");
return 0;
}
if ( !sc )
{
+ ReloadTracker::failed(ctrlcon, "failed to update policy");
send_response(ctrlcon, "== reload failed\n");
return 0;
}
SnortConfig::set_conf(sc);
proc_stats.inspector_deletions++;
+ ReloadTracker::update(ctrlcon, "start swapping configuration ...");
send_response(ctrlcon, ".. deleted inspector\n");
main_broadcast_command(new ACSwap(new Swapper(old, sc), ctrlcon), ctrlcon);
set (INCLUDES
analyzer_command.h
policy.h
+ reload_tracker.h
snort.h
snort_config.h
snort_debug.h
oops_handler.cc
oops_handler.h
policy.cc
+ reload_tracker.cc
shell.h
shell.cc
snort.cc
#include "utils/stats.h"
#include "analyzer.h"
+#include "reload_tracker.h"
#include "snort.h"
#include "snort_config.h"
#include "swapper.h"
requested_type_l) { }
ACSwap::ACSwap(Swapper* ps, ControlConn *ctrlcon) : ps(ps), ctrlcon(ctrlcon)
-{
- assert(Swapper::get_reload_in_progress() == false);
- Swapper::set_reload_in_progress(true);
-}
+{ }
bool ACSwap::execute(Analyzer& analyzer, void** ac_state)
{
delete ps;
HostAttributesManager::swap_cleanup();
- Swapper::set_reload_in_progress(false);
+ ReloadTracker::end(ctrlcon);
LogMessage("== reload complete\n");
if (ctrlcon && !ctrlcon->is_local())
ctrlcon->respond("== reload complete\n");
ACHostAttributesSwap::ACHostAttributesSwap(ControlConn *ctrlcon)
: ctrlcon(ctrlcon)
-{
- assert(Swapper::get_reload_in_progress() == false);
- Swapper::set_reload_in_progress(true);
-}
+{ }
bool ACHostAttributesSwap::execute(Analyzer&, void**)
{
ACHostAttributesSwap::~ACHostAttributesSwap()
{
HostAttributesManager::swap_cleanup();
- Swapper::set_reload_in_progress(false);
+ ReloadTracker::end(ctrlcon);
LogMessage("== reload host attributes complete\n");
if (ctrlcon && !ctrlcon->is_local())
ctrlcon->respond("== reload host attributes complete\n");
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// reload_tracker.cc author Steven Baigal <sbaigal@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "reload_tracker.h"
+
+#include <cassert>
+
+#include "control/control.h"
+#include "log/messages.h"
+
+using namespace snort;
+
+bool ReloadTracker::reload_in_progress = false;
+std::string ReloadTracker::current_command;
+ControlConn* ReloadTracker::ctrl = nullptr;
+
+bool ReloadTracker::start(ControlConn* ctrlcon)
+{
+ if (reload_in_progress)
+ {
+ LogMessage("Reload in progress [%s], attempting command: [%s]\n",
+ current_command.c_str(),
+ ctrlcon ? ctrlcon->get_current_command().substr(0, 50).c_str() : "signal");
+ return false;
+ }
+ reload_in_progress = true;
+ current_command = (ctrlcon ? ctrlcon->get_current_command().substr(0, 50) : "signal");
+ LogMessage("Reload started. [%s]\n", current_command.c_str());
+ ctrl = ctrlcon;
+ return true;
+}
+
+void ReloadTracker::end(ControlConn* ctrlcon)
+{
+ if (ctrl == ctrlcon and reload_in_progress)
+ LogMessage("Reload ended. [%s]\n", current_command.c_str());
+ else
+ ErrorMessage("Reload session mismatched for ending tracker\n");
+ current_command.clear();
+ ctrl = nullptr;
+ reload_in_progress = false;
+}
+
+void ReloadTracker::failed(ControlConn* ctrlcon, const char* reason)
+{
+ if (ctrl == ctrlcon and reload_in_progress)
+ LogMessage("Reload failed! %s [%s]\n", reason, current_command.c_str());
+ else
+ ErrorMessage("Reload session mismatched for failing tracker\n");
+ current_command.clear();
+ ctrl = nullptr;
+ reload_in_progress = false;
+}
+
+void ReloadTracker::update(ControlConn* ctrlcon, const char* status)
+{
+ if (ctrl == ctrlcon and reload_in_progress)
+ LogMessage("Reload update: %s [%s]\n", status, current_command.c_str());
+ else
+ ErrorMessage("Reload session mismatched for updating tracker\n");
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2021-2021 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// reload_tracker.h author Steven Baigal <sbaigal@cisco.com>
+
+#ifndef RELOAD_TRACKER_H
+#define RELOAD_TRACKER_H
+
+#include <string>
+
+#include "main/snort_types.h"
+
+class ControlConn;
+
+namespace snort
+{
+
+class SO_PUBLIC ReloadTracker
+{
+public:
+ ReloadTracker() = delete;
+ static bool start(ControlConn* ctrlcon);
+ static void end(ControlConn* ctrlcon);
+ static void failed(ControlConn* ctrlcon, const char* reason);
+ static void update(ControlConn* ctrlcon, const char* status);
+
+private:
+ static bool reload_in_progress;
+ static std::string current_command;
+ static ControlConn* ctrl;
+};
+
+}
+
+#endif
using namespace snort;
-bool Swapper::reload_in_progress = false;
-
Swapper::Swapper(SnortConfig* s)
{
old_conf = nullptr;
void finish(Analyzer&);
snort::SnortConfig* get_new_conf() { return new_conf; }
- static bool get_reload_in_progress() { return reload_in_progress; }
- static void set_reload_in_progress(bool rip) { reload_in_progress = rip; }
-
private:
const snort::SnortConfig* old_conf;
snort::SnortConfig* new_conf;
-
- static bool reload_in_progress;
};
#endif
#include "log/messages.h"
#include "main/analyzer.h"
#include "main/analyzer_command.h"
+#include "main/reload_tracker.h"
#include "main/snort.h"
#include "main/swapper.h"
#include "managers/inspector_manager.h"
{
public:
bool execute(Analyzer&, void**) override;
- ACThirdPartyAppIdContextSwap(const AppIdInspector& inspector): inspector(inspector)
+ ACThirdPartyAppIdContextSwap(const AppIdInspector& inspector, ControlConn* conn)
+ : inspector(inspector), tracker_ref(conn)
{
LogMessage("== swapping third-party configuration\n");
}
const char* stringify() override { return "THIRD-PARTY_CONTEXT_SWAP"; }
private:
const AppIdInspector& inspector;
+ ControlConn* tracker_ref;
};
bool ACThirdPartyAppIdContextSwap::execute(Analyzer&, void**)
std::string file_path = ctxt.get_tp_appid_ctxt()->get_user_config();
ctxt.get_odp_ctxt().get_app_info_mgr().dump_appid_configurations(file_path);
LogMessage("== third-party configuration swap complete\n");
+ ReloadTracker::end(tracker_ref);
}
class ACThirdPartyAppIdContextUnload : public AnalyzerCommand
delete tp_ctxt;
AppIdContext& ctxt = inspector.get_ctxt();
ctxt.create_tp_appid_ctxt();
- main_broadcast_command(new ACThirdPartyAppIdContextSwap(inspector));
+ main_broadcast_command(new ACThirdPartyAppIdContextSwap(inspector, ctrlcon));
LogMessage("== reload third-party complete\n");
- ctrlcon->respond("== reload third-party complete\n");
- Swapper::set_reload_in_progress(false);
+ if (ctrlcon && !ctrlcon->is_local())
+ ctrlcon->respond("== reload third-party complete\n");
+ ReloadTracker::update(ctrlcon, "unload old third-party complete, start swapping to new configuration.");
}
class ACOdpContextSwap : public AnalyzerCommand
file_path = std::string(ctxt.config.app_detector_dir) + "/../userappid.conf";
ctxt.get_odp_ctxt().get_app_info_mgr().dump_appid_configurations(file_path);
}
- LogMessage("== reload detectors complete\n");
+ ReloadTracker::end(ctrlcon);
ctrlcon->respond("== reload detectors complete\n");
- Swapper::set_reload_in_progress(false);
}
static int enable_debug(lua_State* L)
static int reload_third_party(lua_State* L)
{
ControlConn* ctrlcon = ControlConn::query_from_lua(L);
- if (Swapper::get_reload_in_progress())
+ if (!ReloadTracker::start(ctrlcon))
{
ctrlcon->respond("== reload pending; retry\n");
return 0;
}
+
AppIdInspector* inspector = (AppIdInspector*) InspectorManager::get_inspector(MOD_NAME);
if (!inspector)
{
+ ReloadTracker::failed(ctrlcon, "appid not enabled");
ctrlcon->respond("== reload third-party failed - appid not enabled\n");
return 0;
}
ThirdPartyAppIdContext* old_ctxt = ctxt.get_tp_appid_ctxt();
if (!old_ctxt)
{
+ ReloadTracker::failed(ctrlcon, "third-party module doesn't exist");
ctrlcon->respond("== reload third-party failed - third-party module doesn't exist\n");
return 0;
}
- Swapper::set_reload_in_progress(true);
+
+ ReloadTracker::update(ctrlcon, "unloading old third-party configuration");
ctrlcon->respond("== unloading old third-party configuration\n");
main_broadcast_command(new ACThirdPartyAppIdContextUnload(*inspector, old_ctxt, ctrlcon), ctrlcon);
return 0;
static int reload_detectors(lua_State* L)
{
ControlConn* ctrlcon = ControlConn::query_from_lua(L);
- if (Swapper::get_reload_in_progress())
+ if ( !ReloadTracker::start(ctrlcon) )
{
ctrlcon->respond("== reload pending; retry\n");
return 0;
if (!inspector)
{
ctrlcon->respond("== reload detectors failed - appid not enabled\n");
+ ReloadTracker::failed(ctrlcon, "appid not enabled");
return 0;
}
- Swapper::set_reload_in_progress(true);
+
ctrlcon->respond(".. reloading detectors\n");
AppIdContext& ctxt = inspector->get_ctxt();
odp_ctxt.initialize(*inspector);
ctrlcon->respond("== swapping detectors configuration\n");
+ ReloadTracker::update(ctrlcon, "swapping detectors configuration");
main_broadcast_command(new ACOdpContextSwap(*inspector, old_odp_ctxt, ctrlcon), ctrlcon);
return 0;
}