Add support for daemon, checking for valid combination of modes

remotes/origin/master-1.0.x
Gerardo Iglesias Galvan 16 years ago committed by Victor Julien
parent 8490208ba1
commit e917065e26

@ -113,6 +113,7 @@ util-radix-tree.c util-radix-tree.h \
util-host-os-info.c util-host-os-info.h \
util-rule-vars.c util-rule-vars.h \
util-fix_checksum.c util-fix_checksum.h \
util-daemon.c util-daemon.h \
tm-modules.c tm-modules.h \
tm-queues.c tm-queues.h \
tm-queuehandlers.c tm-queuehandlers.h \

@ -83,6 +83,7 @@
#include "util-debug.h"
#include "util-error.h"
#include "detect-engine-siggroup.h"
#include "util-daemon.h"
/*
* we put this here, because we only use it here in main.
@ -275,6 +276,7 @@ void usage(const char *progname)
printf("\t-q <qid> : run in inline nfqueue mode\n");
printf("\t-s <path> : path to signature file (optional)\n");
printf("\t-l <dir> : default log directory\n");
printf("\t-D : run as daemon\n");
#ifdef UNITTESTS
printf("\t-u : run the unittests and exit\n");
printf("\t-U, --unittest-filter=REGEX : filter unittests with a regex\n");
@ -298,6 +300,7 @@ int main(int argc, char **argv)
char *regex_arg = NULL;
int dump_config = 0;
int list_unittests = 0;
int daemon = 0;
/* initialize the logging subsys */
SCLogInitLogModule(NULL);
@ -319,7 +322,7 @@ int main(int argc, char **argv)
/* getopt_long stores the option index here. */
int option_index = 0;
char short_opts[] = "c:hi:l:q:r:us:U:";
char short_opts[] = "c:Dhi:l:q:r:us:U:";
while ((opt = getopt_long(argc, argv, short_opts, long_opts, &option_index)) != -1) {
switch (opt) {
@ -368,6 +371,9 @@ int main(int argc, char **argv)
case 'c':
conf_filename = optarg;
break;
case 'D':
daemon = 1;
break;
case 'h':
usage(argv[0]);
exit(EXIT_SUCCESS);
@ -415,6 +421,10 @@ int main(int argc, char **argv)
}
}
if (!CheckValidDaemonModes(daemon, mode)) {
exit(EXIT_FAILURE);
}
/* Initializations for global vars, queues, etc (memsets, mutex init..) */
GlobalInits();
@ -548,6 +558,8 @@ int main(int argc, char **argv)
}
#endif /* UNITTESTS */
if (daemon) Daemonize();
/* registering signals we use */
SignalHandlerSetup(SIGINT, SignalHandlerSigint);
SignalHandlerSetup(SIGTERM, SignalHandlerSigterm);

@ -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__ */

@ -59,6 +59,7 @@ typedef enum {
SC_NFQ_HANDLE_PKT,
SC_NFQ_SET_VERDICT,
SC_NFQ_THREAD_INIT,
SC_ERR_DAEMON,
} SCError;
const char *SCErrorToString(SCError);

Loading…
Cancel
Save