windows: reload rules with service control code

Windows has no SIGUSR2 and no unix socket, so rules could not be reloaded
without restarting Suricata. When running as a service, a rule reload can now
be requested with the user-defined control code 128, for example:

    sc.exe control Suricata 128

The service control handler only records the request; the main loop then
handles it the same as SIGUSR2.

Ticket: 7756
pull/16512/head
Jason Ish 2 weeks ago committed by Victor Julien
parent f57cacd3b3
commit f303d50441

@ -45,6 +45,9 @@ SIGHUP
used to re-open log files after they may have been moved away by
log rotation utilities.
On Windows, when running as a service, the service control code 128 is the
equivalent of SIGUSR2.
FILES AND DIRECTORIES
---------------------

@ -41,6 +41,30 @@ This will cause Suricata to reload rules without the caller blocking or waiting.
suricatasc -c ruleset-reload-nonblocking
.. _rule-reload-windows-service:
Via Windows service control
---------------------------
Windows does not support the ``USR2`` signal or the UNIX domain socket.
Instead, when Suricata is running as a Windows service, a rule reload can be
requested by sending the service the user-defined control code ``128``::
sc.exe control Suricata 128
This is a non-blocking reload. ``sc.exe`` does not report the result of the
reload; it is logged by Suricata.
When installed with ``--service-install``, only SYSTEM and Administrators may
send control codes to the Suricata service. A service installed by older
versions of Suricata, or by other tools, may allow any interactive user to
send control codes. This can be restricted with::
sc.exe sdset Suricata "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLORC;;;IU)(A;;CCLCSWLORC;;;SU)"
.. note:: In PowerShell, ``sc`` is an alias for ``Set-Content``, so
``sc.exe`` must be used.
Resources Reloaded
~~~~~~~~~~~~~~~~~~

@ -3040,6 +3040,18 @@ void SuricataMainLoop(void)
TmThreadCheckThreadState();
#ifdef OS_WIN32
/* Service control requests are handled like their signal equivalents,
* SC_SERVICE_REQUEST_RELOAD_RULES like SIGUSR2. */
uint32_t requests = SCServiceTakeRequests();
if (requests & SC_SERVICE_REQUEST_RELOAD_RULES) {
SCLogNotice("Rule reload requested by service control");
if (DetectEngineEnabled() && sigusr2_count < 2) {
sigusr2_count++;
}
}
#endif
if (sighup_count > 0) {
OutputNotifyFileRotation();
sighup_count--;

@ -137,6 +137,9 @@ static bool SCServiceGetCommandLine(
static SERVICE_STATUS_HANDLE service_status_handle = 0;
/* Pending SC_SERVICE_REQUEST_* flags, handled by the main loop. */
static SC_ATOMIC_DECLARE(uint32_t, service_requests);
static int service_argc = 0;
static char **service_argv = NULL;
@ -185,11 +188,27 @@ static void SCAtExitHandler(void)
}
}
/**
* \brief Get and clear the pending service control requests.
*
* \retval SC_SERVICE_REQUEST_* flags
*/
uint32_t SCServiceTakeRequests(void)
{
return SC_ATOMIC_AND(service_requests, 0);
}
/**
* \brief Service handler
*/
static DWORD WINAPI SCServiceCtrlHandlerEx(DWORD code, DWORD etype, LPVOID edata, LPVOID context)
{
if (code == SC_SERVICE_CONTROL_RELOAD_RULES) {
/* Defer logging to the main loop, after logging initialization. */
SC_ATOMIC_OR(service_requests, SC_SERVICE_REQUEST_RELOAD_RULES);
return NO_ERROR;
}
if (code == SERVICE_CONTROL_SHUTDOWN || code == SERVICE_CONTROL_STOP) {
SERVICE_STATUS status = {
SERVICE_WIN32,

@ -25,6 +25,13 @@
#define SURICATA_WIN32_SERVICE_H
#ifdef OS_WIN32
/* User-defined service control codes, must be in the range 128-255. */
#define SC_SERVICE_CONTROL_RELOAD_RULES 128
/* Requests returned by SCServiceTakeRequests(). */
#define SC_SERVICE_REQUEST_RELOAD_RULES BIT_U32(0)
uint32_t SCServiceTakeRequests(void);
int SCRunningAsService(void);
int SCServiceInit(int argc, char **argv);
int SCServiceInstall(int argc, char **argv);

Loading…
Cancel
Save