mirror of https://github.com/OISF/suricata
Add support for daemon, checking for valid combination of modes
parent
8490208ba1
commit
e917065e26
@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Copyright (c) 2009 Open Information Security Foundation
|
||||
*
|
||||
* \file util-daemon.c
|
||||
* \author Gerardo Iglesias Galvan <iglesiasg@gmail.com>
|
||||
*
|
||||
* Daemonization process
|
||||
*/
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "eidps-common.h"
|
||||
#include "util-daemon.h"
|
||||
#include "util-debug.h"
|
||||
|
||||
static volatile sig_atomic_t sigflag = 0;
|
||||
|
||||
/**
|
||||
* \brief Signal handler used to take the parent process out of stand-by
|
||||
*/
|
||||
static void SignalHandlerSigusr1 (int signo) {
|
||||
sigflag = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Tell the parent process the child is ready
|
||||
*
|
||||
* \param pid pid of the parent process to signal
|
||||
*/
|
||||
static void TellWaitingParent (pid_t pid) {
|
||||
kill(pid, SIGUSR1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the parent on stand-by until the child is ready
|
||||
*
|
||||
* \param pid pid of the child process to wait
|
||||
*/
|
||||
static void WaitForChild (pid_t pid) {
|
||||
int status;
|
||||
SCLogDebug("Daemon: Parent waiting for child to be ready...");
|
||||
/* Wait until child signals is ready */
|
||||
while (sigflag == 0) {
|
||||
if (waitpid(pid, &status, WNOHANG)) {
|
||||
/* Check if the child is still there, otherwise the parent should exit */
|
||||
if (WIFEXITED(status) || WIFSIGNALED(status)) {
|
||||
SCLogError(SC_ERR_DAEMON, "Child died unexpectedly");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
/* sigsuspend(); */
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Close stdin, stdout, stderr.Redirect logging info to syslog
|
||||
*
|
||||
*/
|
||||
static void SetupLogging () {
|
||||
int fd0, fd1, fd2;
|
||||
|
||||
SCLogInitData *sc_lid = NULL;
|
||||
SCLogOPIfaceCtx *sc_iface_ctx = NULL;
|
||||
|
||||
sc_lid = SCLogAllocLogInitData();
|
||||
sc_lid->startup_message = "Daemon started";
|
||||
sc_lid->global_log_level = SC_LOG_INFO;
|
||||
sc_iface_ctx = SCLogInitOPIfaceCtx("syslog", "%l", SC_LOG_INFO, "local5");
|
||||
SCLogAppendOPIfaceCtx(sc_iface_ctx, sc_lid);
|
||||
|
||||
/* Close stdin, stdout, stderr */
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
|
||||
/* Redirect stdin, stdout, stderr to /dev/null */
|
||||
fd0 = open("/dev/null", O_RDWR);
|
||||
fd1 = dup(0);
|
||||
fd2 = dup(0);
|
||||
|
||||
SCLogInitLogModule(sc_lid);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check for a valid combination daemon/mode
|
||||
*
|
||||
* \param daemon daemon on or off
|
||||
* \param mode selected mode
|
||||
*
|
||||
* \retval 1 valid combination
|
||||
* \retval 0 invalid combination
|
||||
*/
|
||||
int CheckValidDaemonModes (int daemon, int mode) {
|
||||
if (daemon) {
|
||||
switch (mode) {
|
||||
case 1:
|
||||
SCLogDebug("ERROR: pcap live mode cannot run as daemon");
|
||||
return 0;
|
||||
case 2:
|
||||
SCLogDebug("ERROR: pcap offline mode cannot run as daemon");
|
||||
return 0;
|
||||
case 5:
|
||||
SCLogDebug("ERROR: unittests cannot run as daemon");
|
||||
return 0;
|
||||
default:
|
||||
SCLogDebug("Allowed mode");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Daemonize the process
|
||||
*
|
||||
*/
|
||||
void Daemonize (void) {
|
||||
pid_t pid, sid;
|
||||
|
||||
/* Register the signal handler */
|
||||
signal(SIGUSR1, SignalHandlerSigusr1);
|
||||
|
||||
/** \todo We should check if wie allow more than 1 instance
|
||||
to run simultaneously. Maybe change the behaviour
|
||||
through conf file */
|
||||
|
||||
/* Creates a new process */
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
/* Fork error */
|
||||
SCLogError(SC_ERR_DAEMON, "Error forking the process");
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (pid == 0) {
|
||||
/* Child continues here */
|
||||
|
||||
umask(027);
|
||||
|
||||
sid = setsid();
|
||||
if (sid < 0) {
|
||||
SCLogError(SC_ERR_DAEMON, "Error creating new session");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/** \todo The daemon runs on the current directory, but later we'll want
|
||||
to allow through the configuration file (or other means) to
|
||||
change the running directory */
|
||||
/* if ((chdir(DAEMON_WORKING_DIRECTORY)) < 0) {
|
||||
SCLogError(SC_ERR_DAEMON, "Error changing to working directory");
|
||||
exit(EXIT_FAILURE);
|
||||
} */
|
||||
|
||||
SetupLogging();
|
||||
|
||||
/* Child is ready, tell its parent */
|
||||
TellWaitingParent(getppid());
|
||||
|
||||
/* Daemon is up and running */
|
||||
SCLogDebug("Daemon is running");
|
||||
return;
|
||||
}
|
||||
/* Parent continues here, waiting for child to be ready */
|
||||
SCLogDebug("Parent is waiting for child to be ready");
|
||||
WaitForChild(pid);
|
||||
|
||||
/* Parent exits */
|
||||
SCLogDebug("Child is ready, parent exiting");
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) 2009 Open Information Security Foundation
|
||||
*
|
||||
* \file util-daemon.h
|
||||
* \author Gerardo Iglesias Galvan <iglesiasg@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_DAEMON_H__
|
||||
#define __UTIL_DAEMON_H__
|
||||
|
||||
/** \todo Adjust path */
|
||||
#define DAEMON_WORKING_DIRECTORY "/"
|
||||
|
||||
int CheckValidDaemonModes (int, int);
|
||||
void Daemonize (void);
|
||||
|
||||
#endif /* __UTIL_DAEMON_H__ */
|
Loading…
Reference in New Issue