suricata
util-daemon.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Gerardo Iglesias Galvan <iglesiasg@gmail.com>
22  *
23  * Daemonization process
24  */
25 
26 #include "suricata.h"
27 #include "suricata-common.h"
28 #include "runmodes.h"
29 #include "util-daemon.h"
30 #include "util-debug.h"
31 #include "conf.h"
32 
33 #ifndef OS_WIN32
34 
35 #include <sys/wait.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 
39 static volatile sig_atomic_t sigflag = 0;
40 
41 /**
42  * \brief Signal handler used to take the parent process out of stand-by
43  */
44 static void SignalHandlerSigusr1 (int signo)
45 {
46  sigflag = 1;
47 }
48 
49 /**
50  * \brief Tell the parent process the child is ready
51  *
52  * \param pid pid of the parent process to signal
53  */
54 static void TellWaitingParent (pid_t pid)
55 {
56  kill(pid, SIGUSR1);
57 }
58 
59 /**
60  * \brief Set the parent on stand-by until the child is ready
61  *
62  * \param pid pid of the child process to wait
63  */
64 static void WaitForChild (pid_t pid)
65 {
66  int status;
67  SCLogDebug("Daemon: Parent waiting for child to be ready...");
68  /* Wait until child signals is ready */
69  while (sigflag == 0) {
70  if (waitpid(pid, &status, WNOHANG)) {
71  /* Check if the child is still there, otherwise the parent should exit */
72  if (WIFEXITED(status) || WIFSIGNALED(status)) {
73  FatalError(SC_ERR_FATAL, "Child died unexpectedly");
74  }
75  }
76  /* sigsuspend(); */
77  sleep(1);
78  }
79 }
80 
81 /**
82  * \brief Close stdin, stdout, stderr.Redirect logging info to syslog
83  *
84  */
85 static void SetupLogging (void)
86 {
87  /* Redirect stdin, stdout, stderr to /dev/null */
88  int fd = open("/dev/null", O_RDWR);
89  if (fd < 0)
90  return;
91  (void)dup2(fd, 0);
92  (void)dup2(fd, 1);
93  (void)dup2(fd, 2);
94  close(fd);
95 }
96 
97 /**
98  * \brief Daemonize the process
99  *
100  */
101 void Daemonize (void)
102 {
103  pid_t pid, sid;
104 
105  /* Register the signal handler */
106  signal(SIGUSR1, SignalHandlerSigusr1);
107 
108  /** \todo We should check if wie allow more than 1 instance
109  to run simultaneously. Maybe change the behaviour
110  through conf file */
111 
112  /* Creates a new process */
113  pid = fork();
114 
115  if (pid < 0) {
116  /* Fork error */
117  FatalError(SC_ERR_FATAL, "Error forking the process");
118  } else if (pid == 0) {
119  /* Child continues here */
120  const char *daemondir;
121 
122  sid = setsid();
123  if (sid < 0) {
124  FatalError(SC_ERR_FATAL, "Error creating new session");
125  }
126 
127  if (ConfGet("daemon-directory", &daemondir) == 1) {
128  if ((chdir(daemondir)) < 0) {
130  "Error changing to working directory");
131  }
132  }
133 #ifndef OS_WIN32
134  else {
135  if (chdir("/") < 0) {
136  SCLogError(SC_ERR_DAEMON, "Error changing to working directory '/'");
137  }
138  }
139 #endif
140 
141  SetupLogging();
142 
143  /* Child is ready, tell its parent */
144  TellWaitingParent(getppid());
145 
146  /* Daemon is up and running */
147  SCLogDebug("Daemon is running");
148  return;
149  }
150  /* Parent continues here, waiting for child to be ready */
151  SCLogDebug("Parent is waiting for child to be ready");
152  WaitForChild(pid);
153 
154  /* Parent exits */
155  SCLogDebug("Child is ready, parent exiting");
156  exit(EXIT_SUCCESS);
157 
158 }
159 
160 #endif /* ifndef OS_WIN32 */
161 
162 /**
163  * \brief Check for a valid combination daemon/mode
164  *
165  * \param daemon daemon on or off
166  * \param mode selected mode
167  *
168  * \retval 1 valid combination
169  * \retval 0 invalid combination
170  */
171 int CheckValidDaemonModes (int daemon, int mode)
172 {
173  if (daemon) {
174  switch (mode) {
175  case RUNMODE_PCAP_FILE:
176  SCLogError(SC_ERR_INVALID_RUNMODE, "ERROR: pcap offline mode cannot run as daemon");
177  return 0;
178  case RUNMODE_UNITTEST:
179  SCLogError(SC_ERR_INVALID_RUNMODE, "ERROR: unittests cannot run as daemon");
180  return 0;
181  default:
182  SCLogDebug("Allowed mode");
183  break;
184  }
185  }
186  return 1;
187 }
RUNMODE_UNITTEST
@ RUNMODE_UNITTEST
Definition: runmodes.h:39
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
Daemonize
void Daemonize(void)
Daemonize the process.
Definition: util-daemon.c:101
CheckValidDaemonModes
int CheckValidDaemonModes(int daemon, int mode)
Check for a valid combination daemon/mode.
Definition: util-daemon.c:171
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:330
util-debug.h
conf.h
SC_ERR_INVALID_RUNMODE
@ SC_ERR_INVALID_RUNMODE
Definition: util-error.h:49
runmodes.h
SC_ERR_DAEMON
@ SC_ERR_DAEMON
Definition: util-error.h:117
suricata-common.h
util-daemon.h
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
FatalError
#define FatalError(x,...)
Definition: util-debug.h:532
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
suricata.h
RUNMODE_PCAP_FILE
@ RUNMODE_PCAP_FILE
Definition: runmodes.h:30