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  */
SignalHandlerSigusr1(int signo)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  */
TellWaitingParent(pid_t pid)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  */
WaitForChild(pid_t pid)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  */
SetupLogging(void)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  */
Daemonize(void)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) {
129                 FatalError(SC_ERR_FATAL,
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  */
CheckValidDaemonModes(int daemon,int mode)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 }
188