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