Rebuild library.lo after changing ./configure 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("dns")
177 ADD_DEBUG("natt")
178 ADD_DEBUG("oppo")
179 ADD_DEBUG("controlmore")
180 ADD_DEBUG("private")
181 if (cfg->setup.crlcheckinterval > 0)
182 {
183 static char buf1[15];
184
185 arg[argc++] = "--crlcheckinterval";
186 snprintf(buf1, sizeof(buf1), "%u", cfg->setup.crlcheckinterval);
187 arg[argc++] = buf1;
188 }
189 if (cfg->setup.cachecrls)
190 {
191 arg[argc++] = "--cachecrls";
192 }
193 if (cfg->setup.strictcrlpolicy)
194 {
195 arg[argc++] = "--strictcrlpolicy";
196 }
197 if (cfg->setup.nocrsend)
198 {
199 arg[argc++] = "--nocrsend";
200 }
201 if (cfg->setup.nat_traversal)
202 {
203 arg[argc++] = "--nat_traversal";
204 }
205 if (cfg->setup.force_keepalive)
206 {
207 arg[argc++] = "--force_keepalive";
208 }
209 if (cfg->setup.keep_alive)
210 {
211 static char buf2[15];
212
213 arg[argc++] = "--keep_alive";
214 snprintf(buf2, sizeof(buf2), "%u", cfg->setup.keep_alive);
215 arg[argc++] = buf2;
216 }
217 if (cfg->setup.virtual_private)
218 {
219 arg[argc++] = "--virtual_private";
220 arg[argc++] = cfg->setup.virtual_private;
221 }
222 if (cfg->setup.pkcs11module)
223 {
224 arg[argc++] = "--pkcs11module";
225 arg[argc++] = cfg->setup.pkcs11module;
226 }
227 if (cfg->setup.pkcs11initargs)
228 {
229 arg[argc++] = "--pkcs11initargs";
230 arg[argc++] = cfg->setup.pkcs11initargs;
231 }
232 if (cfg->setup.pkcs11keepstate)
233 {
234 arg[argc++] = "--pkcs11keepstate";
235 }
236 if (cfg->setup.pkcs11proxy)
237 {
238 arg[argc++] = "--pkcs11proxy";
239 }
240
241 if (_pluto_pid)
242 {
243 plog("starter_start_pluto(): pluto already started...");
244 return -1;
245 }
246 else
247 {
248 unlink(PLUTO_CTL_FILE);
249 _stop_requested = 0;
250
251 if (cfg->setup.prepluto)
252 ignore_result(system(cfg->setup.prepluto));
253
254 pid = fork();
255 switch (pid)
256 {
257 case -1:
258 plog("can't fork(): %s", strerror(errno));
259 return -1;
260 case 0:
261 /* child */
262 if (cfg->setup.plutostderrlog)
263 {
264 int f = creat(cfg->setup.plutostderrlog, 00644);
265
266 /* redirect stderr to file */
267 if (f < 0)
268 {
269 plog("couldn't open stderr redirection file '%s'",
270 cfg->setup.plutostderrlog);
271 }
272 else
273 {
274 dup2(f, 2);
275 }
276 }
277 setsid();
278 sigprocmask(SIG_SETMASK, 0, NULL);
279 /* disable glibc's malloc checker, conflicts with leak detective */
280 setenv("MALLOC_CHECK_", "0", 1);
281 execv(arg[0], arg);
282 plog("can't execv(%s,...): %s", arg[0], strerror(errno));
283 exit(1);
284 default:
285 /* father */
286 _pluto_pid = pid;
287 for (i = 0; i < 500 && _pluto_pid; i++)
288 {
289 /* wait for pluto for a maximum of 500 x 20 ms = 10 s */
290 usleep(20000);
291 if (stat(PLUTO_CTL_FILE, &stb) == 0)
292 {
293 plog("pluto (%d) started after %d ms", _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 plog("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 plog("pluto refused to be started");
321 }
322 return -1;
323 }
324 }
325 return -1;
326 }