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("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 we 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("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("Error creating new session");
132  }
133 
134  if (ConfGet("daemon-directory", &daemondir) == 1) {
135  if ((chdir(daemondir)) < 0) {
136  FatalError("Error changing to working directory");
137  }
138  }
139 #ifndef OS_WIN32
140  else {
141  if (chdir("/") < 0) {
142  SCLogError("Error changing to working directory '/'");
143  }
144  }
145 #endif
146 
147  SetupLogging();
148 
149  /* Child is ready, tell its parent */
150  TellWaitingParent(getppid());
151 
152  /* Daemon is up and running */
153  SCLogDebug("Daemon is running");
154  return;
155  }
156  /* Parent continues here, waiting for child to be ready */
157  SCLogDebug("Parent is waiting for child to be ready");
158  WaitForChild(pid);
159 
160  /* Parent exits */
161  SCLogDebug("Child is ready, parent exiting");
162  exit(EXIT_SUCCESS);
163 
164 }
165 
166 #endif /* ifndef OS_WIN32 */
167 
168 /**
169  * \brief Check for a valid combination daemon/mode
170  *
171  * \param daemon daemon on or off
172  * \param mode selected mode
173  *
174  * \retval 1 valid combination
175  * \retval 0 invalid combination
176  */
177 int CheckValidDaemonModes (int daemon, int mode)
178 {
179  if (daemon) {
180  switch (mode) {
181  case RUNMODE_PCAP_FILE:
182  SCLogError("ERROR: pcap offline mode cannot run as daemon");
183  return 0;
184  case RUNMODE_UNITTEST:
185  SCLogError("ERROR: unittests cannot run as daemon");
186  return 0;
187  default:
188  SCLogDebug("Allowed mode");
189  break;
190  }
191  }
192  return 1;
193 }
RUNMODE_UNITTEST
@ RUNMODE_UNITTEST
Definition: runmodes.h:41
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
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:177
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:335
util-debug.h
conf.h
runmodes.h
suricata-common.h
util-daemon.h
FatalError
#define FatalError(...)
Definition: util-debug.h:502
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
suricata.h
RUNMODE_PCAP_FILE
@ RUNMODE_PCAP_FILE
Definition: runmodes.h:30