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 #if defined(OS_DARWIN) && defined(__clang__)
114 #pragma clang diagnostic push
115 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
116 #endif
117  pid = fork();
118 #if defined(OS_DARWIN) && defined(__clang__)
119 #pragma clang diagnostic pop
120 #endif
121 
122  if (pid < 0) {
123  /* Fork error */
124  FatalError(SC_ERR_FATAL, "Error forking the process");
125  } else if (pid == 0) {
126  /* Child continues here */
127  const char *daemondir;
128 
129  sid = setsid();
130  if (sid < 0) {
131  FatalError(SC_ERR_FATAL, "Error creating new session");
132  }
133 
134  if (ConfGet("daemon-directory", &daemondir) == 1) {
135  if ((chdir(daemondir)) < 0) {
137  "Error changing to working directory");
138  }
139  }
140 #ifndef OS_WIN32
141  else {
142  if (chdir("/") < 0) {
143  SCLogError(SC_ERR_DAEMON, "Error changing to working directory '/'");
144  }
145  }
146 #endif
147 
148  SetupLogging();
149 
150  /* Child is ready, tell its parent */
151  TellWaitingParent(getppid());
152 
153  /* Daemon is up and running */
154  SCLogDebug("Daemon is running");
155  return;
156  }
157  /* Parent continues here, waiting for child to be ready */
158  SCLogDebug("Parent is waiting for child to be ready");
159  WaitForChild(pid);
160 
161  /* Parent exits */
162  SCLogDebug("Child is ready, parent exiting");
163  exit(EXIT_SUCCESS);
164 
165 }
166 
167 #endif /* ifndef OS_WIN32 */
168 
169 /**
170  * \brief Check for a valid combination daemon/mode
171  *
172  * \param daemon daemon on or off
173  * \param mode selected mode
174  *
175  * \retval 1 valid combination
176  * \retval 0 invalid combination
177  */
178 int CheckValidDaemonModes (int daemon, int mode)
179 {
180  if (daemon) {
181  switch (mode) {
182  case RUNMODE_PCAP_FILE:
183  SCLogError(SC_ERR_INVALID_RUNMODE, "ERROR: pcap offline mode cannot run as daemon");
184  return 0;
185  case RUNMODE_UNITTEST:
186  SCLogError(SC_ERR_INVALID_RUNMODE, "ERROR: unittests cannot run as daemon");
187  return 0;
188  default:
189  SCLogDebug("Allowed mode");
190  break;
191  }
192  }
193  return 1;
194 }
RUNMODE_UNITTEST
@ RUNMODE_UNITTEST
Definition: runmodes.h:40
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:296
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:178
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:255
FatalError
#define FatalError(x,...)
Definition: util-debug.h:530
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
suricata.h
RUNMODE_PCAP_FILE
@ RUNMODE_PCAP_FILE
Definition: runmodes.h:30