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