Use correct time_t variables to store ARG_TIME options
[strongswan.git] / src / starter / invokepluto.c
1 /* strongSwan Pluto launcher
2 * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18 #include <signal.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <errno.h>
22 #include <fcntl.h>
23
24 #include <freeswan.h>
25
26 #include "../pluto/constants.h"
27 #include "../pluto/defs.h"
28 #include "../pluto/log.h"
29
30 #include "confread.h"
31 #include "invokepluto.h"
32 #include "files.h"
33 #include "starterwhack.h"
34 #
35 static int _pluto_pid = 0;
36 static int _stop_requested;
37
38 pid_t
39 starter_pluto_pid(void)
40 {
41 return _pluto_pid;
42 }
43
44 void
45 starter_pluto_sigchild(pid_t pid, int status)
46 {
47 if (pid == _pluto_pid)
48 {
49 _pluto_pid = 0;
50 if (status == SS_RC_LIBSTRONGSWAN_INTEGRITY ||
51 status == SS_RC_DAEMON_INTEGRITY)
52 {
53 plog("pluto has quit: integrity test of %s failed",
54 (status == 64) ? "libstrongswan" : "pluto");
55 _stop_requested = 1;
56 }
57 else if (status == SS_RC_INITIALIZATION_FAILED)
58 {
59 plog("pluto has quit: initialization failed");
60 _stop_requested = 1;
61 }
62 if (!_stop_requested)
63 {
64 plog("pluto has died -- restart scheduled (%dsec)"
65 , PLUTO_RESTART_DELAY);
66 alarm(PLUTO_RESTART_DELAY); // restart in 5 sec
67 }
68 unlink(PLUTO_PID_FILE);
69 }
70 }
71
72 int
73 starter_stop_pluto (void)
74 {
75 int i;
76 pid_t pid = _pluto_pid;
77
78 if (pid)
79 {
80 _stop_requested = 1;
81
82 if (starter_whack_shutdown() == 0)
83 {
84 for (i = 0; i < 400; i++)
85 {
86 usleep(20000); /* sleep for 20 ms */
87 if (_pluto_pid == 0)
88 {
89 plog("pluto stopped after %d ms", 20*(i+1));
90 return 0;
91 }
92 }
93 }
94 /* be more and more aggressive */
95 for (i = 0; i < 20 && (pid = _pluto_pid) != 0; i++)
96 {
97
98 if (i < 10)
99 {
100 kill(pid, SIGTERM);
101 }
102 if (i == 10)
103 {
104 kill(pid, SIGKILL);
105 plog("starter_stop_pluto(): pluto does not respond, sending KILL");
106 }
107 else
108 {
109 kill(pid, SIGKILL);
110 }
111 usleep(100000); /* sleep for 100 ms */
112 }
113 if (_pluto_pid == 0)
114 {
115 plog("pluto stopped after %d ms", 8000 + 100*i);
116 return 0;
117 }
118 plog("starter_stop_pluto(): can't stop pluto !!!");
119 return -1;
120 }
121 else
122 {
123 plog("stater_stop_pluto(): pluto is not started...");
124 }
125 return -1;
126 }
127
128 #define ADD_DEBUG(v) { \
129 for (l = cfg->setup.plutodebug; l && *l; l++) if (streq(*l, v)) \
130 arg[argc++] = "--debug-" v; \
131 }
132
133 int
134 starter_start_pluto (starter_config_t *cfg, bool no_fork, bool attach_gdb)
135 {
136 struct stat stb;
137 int i;
138 pid_t pid;
139 char **l;
140 int argc = 2;
141 char *arg[] = {
142 PLUTO_CMD, "--nofork"
143 , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
144 , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
145 , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
146 , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
147 };
148
149 printf ("starter_start_pluto entered\n");
150
151 if (attach_gdb)
152 {
153 argc = 0;
154 arg[argc++] = "/usr/bin/gdb";
155 arg[argc++] = "--args";
156 arg[argc++] = PLUTO_CMD;
157 arg[argc++] = "--nofork";
158 }
159 if (cfg->setup.plutostderrlog || no_fork)
160 {
161 arg[argc++] = "--stderrlog";
162 }
163 if (cfg->setup.uniqueids)
164 {
165 arg[argc++] = "--uniqueids";
166 }
167 ADD_DEBUG("none")
168 ADD_DEBUG("all")
169 ADD_DEBUG("raw")
170 ADD_DEBUG("crypt")
171 ADD_DEBUG("parsing")
172 ADD_DEBUG("emitting")
173 ADD_DEBUG("control")
174 ADD_DEBUG("lifecycle")
175 ADD_DEBUG("klips")
176 ADD_DEBUG("kernel")
177 ADD_DEBUG("dns")
178 ADD_DEBUG("natt")
179 ADD_DEBUG("oppo")
180 ADD_DEBUG("controlmore")
181 ADD_DEBUG("private")
182 if (cfg->setup.crlcheckinterval > 0)
183 {
184 static char buf1[15];
185
186 arg[argc++] = "--crlcheckinterval";
187 snprintf(buf1, sizeof(buf1), "%d", (int)cfg->setup.crlcheckinterval);
188 arg[argc++] = buf1;
189 }
190 if (cfg->setup.cachecrls)
191 {
192 arg[argc++] = "--cachecrls";
193 }
194 if (cfg->setup.strictcrlpolicy)
195 {
196 arg[argc++] = "--strictcrlpolicy";
197 }
198 if (cfg->setup.nocrsend)
199 {
200 arg[argc++] = "--nocrsend";
201 }
202 if (cfg->setup.nat_traversal)
203 {
204 arg[argc++] = "--nat_traversal";
205 }
206 if (cfg->setup.force_keepalive)
207 {
208 arg[argc++] = "--force_keepalive";
209 }
210 if (cfg->setup.keep_alive)
211 {
212 static char buf2[15];
213
214 arg[argc++] = "--keep_alive";
215 snprintf(buf2, sizeof(buf2), "%d", (int)cfg->setup.keep_alive);
216 arg[argc++] = buf2;
217 }
218 if (cfg->setup.virtual_private)
219 {
220 arg[argc++] = "--virtual_private";
221 arg[argc++] = cfg->setup.virtual_private;
222 }
223 if (cfg->setup.pkcs11module)
224 {
225 arg[argc++] = "--pkcs11module";
226 arg[argc++] = cfg->setup.pkcs11module;
227 }
228 if (cfg->setup.pkcs11initargs)
229 {
230 arg[argc++] = "--pkcs11initargs";
231 arg[argc++] = cfg->setup.pkcs11initargs;
232 }
233 if (cfg->setup.pkcs11keepstate)
234 {
235 arg[argc++] = "--pkcs11keepstate";
236 }
237 if (cfg->setup.pkcs11proxy)
238 {
239 arg[argc++] = "--pkcs11proxy";
240 }
241
242 if (_pluto_pid)
243 {
244 plog("starter_start_pluto(): pluto already started...");
245 return -1;
246 }
247 else
248 {
249 unlink(PLUTO_CTL_FILE);
250 _stop_requested = 0;
251
252 if (cfg->setup.prepluto)
253 ignore_result(system(cfg->setup.prepluto));
254
255 pid = fork();
256 switch (pid)
257 {
258 case -1:
259 plog("can't fork(): %s", strerror(errno));
260 return -1;
261 case 0:
262 /* child */
263 if (cfg->setup.plutostderrlog)
264 {
265 int f = creat(cfg->setup.plutostderrlog, 00644);
266
267 /* redirect stderr to file */
268 if (f < 0)
269 {
270 plog("couldn't open stderr redirection file '%s'",
271 cfg->setup.plutostderrlog);
272 }
273 else
274 {
275 dup2(f, 2);
276 }
277 }
278 setsid();
279 sigprocmask(SIG_SETMASK, 0, NULL);
280 /* disable glibc's malloc checker, conflicts with leak detective */
281 setenv("MALLOC_CHECK_", "0", 1);
282 execv(arg[0], arg);
283 plog("can't execv(%s,...): %s", arg[0], strerror(errno));
284 exit(1);
285 default:
286 /* father */
287 _pluto_pid = pid;
288 for (i = 0; i < 500 && _pluto_pid; i++)
289 {
290 /* wait for pluto for a maximum of 500 x 20 ms = 10 s */
291 usleep(20000);
292 if (stat(PLUTO_CTL_FILE, &stb) == 0)
293 {
294 plog("pluto (%d) started after %d ms", _pluto_pid, 20*(i+1));
295 if (cfg->setup.postpluto)
296 {
297 ignore_result(system(cfg->setup.postpluto));
298 }
299 return 0;
300 }
301 }
302 if (_pluto_pid)
303 {
304 /* If pluto is started but with no ctl file, stop it */
305 plog("pluto too long to start... - kill kill");
306 for (i = 0; i < 20 && (pid = _pluto_pid) != 0; i++)
307 {
308 if (i < 10)
309 {
310 kill(pid, SIGTERM);
311 }
312 else
313 {
314 kill(pid, SIGKILL);
315 }
316 usleep(20000); /* sleep for 20 ms */
317 }
318 }
319 else
320 {
321 plog("pluto refused to be started");
322 }
323 return -1;
324 }
325 }
326 return -1;
327 }