- introduced autotools
[strongswan.git] / src / starter / starter.c
1 /* strongSwan IPsec starter
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 * RCSID $Id: starter.c,v 1.23 2006/02/15 18:37:46 as Exp $
15 */
16
17 #include <sys/types.h>
18 #include <sys/wait.h>
19 #include <sys/stat.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <signal.h>
23 #include <unistd.h>
24 #include <sys/time.h>
25 #include <time.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <fcntl.h>
29
30 #include <freeswan.h>
31
32 #include "../pluto/constants.h"
33 #include "../pluto/defs.h"
34 #include "../pluto/log.h"
35
36 #include "confread.h"
37 #include "files.h"
38 #include "starterwhack.h"
39 #include "starterstroke.h"
40 #include "invokepluto.h"
41 #include "invokecharon.h"
42 #include "netkey.h"
43 #include "cmp.h"
44 #include "interfaces.h"
45
46 #define FLAG_ACTION_START_PLUTO 0x01
47 #define FLAG_ACTION_UPDATE 0x02
48 #define FLAG_ACTION_RELOAD 0x04
49 #define FLAG_ACTION_QUIT 0x08
50 #define FLAG_ACTION_LISTEN 0x10
51 #define FLAG_ACTION_START_CHARON 0x20
52
53 static unsigned int _action_ = 0;
54
55 static void
56 fsig(int signal)
57 {
58 switch (signal)
59 {
60 case SIGCHLD:
61 {
62 int status;
63 pid_t pid;
64 char *name = NULL;
65
66 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
67 {
68 if (pid == starter_pluto_pid())
69 name = " (Pluto)";
70 if (pid == starter_charon_pid())
71 name = " (Charon)";
72 if (WIFSIGNALED(status))
73 DBG(DBG_CONTROL,
74 DBG_log("child %d%s has been killed by sig %d\n",
75 pid, name?name:"", WTERMSIG(status))
76 )
77 else if (WIFSTOPPED(status))
78 DBG(DBG_CONTROL,
79 DBG_log("child %d%s has been stopped by sig %d\n",
80 pid, name?name:"", WSTOPSIG(status))
81 )
82 else if (WIFEXITED(status))
83 DBG(DBG_CONTROL,
84 DBG_log("child %d%s has quit (exit code %d)\n",
85 pid, name?name:"", WEXITSTATUS(status))
86 )
87 else
88 DBG(DBG_CONTROL,
89 DBG_log("child %d%s has quit", pid, name?name:"")
90 )
91
92 if (pid == starter_pluto_pid())
93 starter_pluto_sigchild(pid);
94 if (pid == starter_charon_pid())
95 starter_charon_sigchild(pid);
96 }
97 }
98 break;
99
100 case SIGPIPE:
101 /** ignore **/
102 break;
103
104 case SIGALRM:
105 _action_ |= FLAG_ACTION_START_PLUTO;
106 _action_ |= FLAG_ACTION_START_CHARON;
107 break;
108
109 case SIGHUP:
110 _action_ |= FLAG_ACTION_UPDATE;
111 break;
112
113 case SIGTERM:
114 case SIGQUIT:
115 case SIGINT:
116 _action_ |= FLAG_ACTION_QUIT;
117 break;
118
119 case SIGUSR1:
120 _action_ |= FLAG_ACTION_RELOAD;
121 _action_ |= FLAG_ACTION_UPDATE;
122 break;
123
124 default:
125 plog("fsig(): unknown signal %d -- investigate", signal);
126 break;
127 }
128 }
129
130 static void
131 usage(char *name)
132 {
133 fprintf(stderr, "Usage: starter [--nofork] [--auto-update <sec>] "
134 "[--debug|--debug-more|--debug-all]\n");
135 exit(1);
136 }
137
138 int main (int argc, char **argv)
139 {
140 starter_config_t *cfg = NULL;
141 starter_config_t *new_cfg;
142 starter_conn_t *conn, *conn2;
143 starter_ca_t *ca, *ca2;
144
145 struct stat stb;
146
147 char *err = NULL;
148 int i;
149 int id = 1;
150 struct timeval tv;
151 unsigned long auto_update = 0;
152 time_t last_reload;
153 bool no_fork = FALSE;
154
155 /* global variables defined in log.h */
156 log_to_stderr = TRUE;
157 base_debugging = DBG_NONE;
158
159 /* parse command line */
160 for (i = 1; i < argc; i++)
161 {
162 if (streq(argv[i], "--debug"))
163 {
164 base_debugging |= DBG_CONTROL;
165 }
166 else if (streq(argv[i], "--debug-more"))
167 {
168 base_debugging |= DBG_CONTROLMORE;
169 }
170 else if (streq(argv[i], "--debug-all"))
171 {
172 base_debugging |= DBG_ALL;
173 }
174 else if (streq(argv[i], "--nofork"))
175 {
176 no_fork = TRUE;
177 }
178 else if (streq(argv[i], "--auto-update") && i+1 < argc)
179 {
180 auto_update = atoi(argv[++i]);
181 if (!auto_update)
182 usage(argv[0]);
183 }
184 else
185 {
186 usage(argv[0]);
187 }
188 }
189
190 /* Init */
191 init_log("ipsec_starter");
192 cur_debugging = base_debugging;
193
194 signal(SIGHUP, fsig);
195 signal(SIGCHLD, fsig);
196 signal(SIGPIPE, fsig);
197 signal(SIGINT, fsig);
198 signal(SIGTERM, fsig);
199 signal(SIGQUIT, fsig);
200 signal(SIGALRM, fsig);
201 signal(SIGUSR1, fsig);
202
203 plog("Starting strongSwan %s IPsec [starter]...", ipsec_version_code());
204
205 /* verify that we can start */
206 if (getuid() != 0)
207 {
208 plog("permission denied (must be superuser)");
209 exit(1);
210 }
211
212 if (stat(PLUTO_PID_FILE, &stb) == 0)
213 {
214 plog("pluto is already running (%s exists) -- skipping pluto start", PLUTO_PID_FILE);
215 }
216 else
217 {
218 _action_ |= FLAG_ACTION_START_PLUTO;
219 }
220 if (stat(CHARON_PID_FILE, &stb) == 0)
221 {
222 plog("charon is already running (%s exists) -- skipping charon start", CHARON_PID_FILE);
223 }
224 else
225 {
226 _action_ |= FLAG_ACTION_START_CHARON;
227 }
228 if (stat(DEV_RANDOM, &stb) != 0)
229 {
230 plog("unable to start strongSwan IPsec -- no %s!", DEV_RANDOM);
231 exit(1);
232 }
233
234 if (stat(DEV_URANDOM, &stb)!= 0)
235 {
236 plog("unable to start strongSwan IPsec -- no %s!", DEV_URANDOM);
237 exit(1);
238 }
239
240 cfg = confread_load(CONFIG_FILE);
241 if (!cfg)
242 {
243 plog("unable to start strongSwan -- errors in config");
244 exit(1);
245 }
246
247 /* determine if we have a native netkey IPsec stack */
248 if (!starter_netkey_init())
249 {
250 plog("nor netkey IPSec stack detected");
251 exit(1);
252 }
253
254 last_reload = time(NULL);
255
256 if (stat(STARTER_PID_FILE, &stb) == 0)
257 {
258 plog("starter is already running (%s exists) -- no fork done", STARTER_PID_FILE);
259 exit(0);
260 }
261
262 /* fork if we're not debugging stuff */
263 if (!no_fork)
264 {
265 log_to_stderr = FALSE;
266
267 switch (fork())
268 {
269 case 0:
270 {
271 int fnull = open("/dev/null", O_RDWR);
272
273 if (fnull >= 0)
274 {
275 dup2(fnull, STDIN_FILENO);
276 dup2(fnull, STDOUT_FILENO);
277 dup2(fnull, STDERR_FILENO);
278 close(fnull);
279 }
280 }
281 break;
282 case -1:
283 plog("can't fork: %s", strerror(errno));
284 break;
285 default:
286 exit(0);
287 }
288 }
289
290 /* save pid file in /var/run/starter.pid */
291 {
292 FILE *fd = fopen(STARTER_PID_FILE, "w");
293
294 if (fd)
295 {
296 fprintf(fd, "%u\n", getpid());
297 fclose(fd);
298 }
299 }
300
301 for (;;)
302 {
303 /*
304 * Stop pluto/charon (if started) and exit
305 */
306 if (_action_ & FLAG_ACTION_QUIT)
307 {
308 if (starter_pluto_pid())
309 starter_stop_pluto();
310 if (starter_charon_pid())
311 starter_stop_charon();
312 starter_netkey_cleanup();
313 confread_free(cfg);
314 unlink(STARTER_PID_FILE);
315 unlink(INFO_FILE);
316 #ifdef LEAK_DETECTIVE
317 report_leaks();
318 #endif /* LEAK_DETECTIVE */
319 close_log();
320 plog("ipsec starter stopped");
321 exit(0);
322 }
323
324 /*
325 * Delete all connections. Will be added below
326 */
327 if (_action_ & FLAG_ACTION_RELOAD)
328 {
329 if (starter_pluto_pid() || starter_charon_pid())
330 {
331 for (conn = cfg->conn_first; conn; conn = conn->next)
332 {
333 if (conn->state == STATE_ADDED)
334 {
335 if (conn->keyexchange == KEY_EXCHANGE_IKEV2)
336 starter_stroke_del_conn(conn);
337 else
338 starter_whack_del_conn(conn);
339 conn->state = STATE_TO_ADD;
340 }
341 }
342 for (ca = cfg->ca_first; ca; ca = ca->next)
343 {
344 if (ca->state == STATE_ADDED)
345 {
346 starter_whack_del_ca(ca);
347 ca->state = STATE_TO_ADD;
348 }
349 }
350 }
351 _action_ &= ~FLAG_ACTION_RELOAD;
352 }
353
354 /*
355 * Update configuration
356 */
357 if (_action_ & FLAG_ACTION_UPDATE)
358 {
359 err = NULL;
360 DBG(DBG_CONTROL,
361 DBG_log("Reloading config...")
362 )
363 new_cfg = confread_load(CONFIG_FILE);
364
365 if (new_cfg)
366 {
367 /* Switch to new config. New conn will be loaded below */
368 if (!starter_cmp_defaultroute(&new_cfg->defaultroute
369 , &cfg->defaultroute))
370 {
371 _action_ |= FLAG_ACTION_LISTEN;
372 }
373
374 if (!starter_cmp_pluto(cfg, new_cfg))
375 {
376 plog("Pluto has changed");
377 if (starter_pluto_pid())
378 starter_stop_pluto();
379 _action_ &= ~FLAG_ACTION_LISTEN;
380 _action_ |= FLAG_ACTION_START_PLUTO;
381 }
382 else
383 {
384 /* Only reload conn and ca sections if pluto is not killed */
385
386 /* Look for new connections that are already loaded */
387 for (conn = cfg->conn_first; conn; conn = conn->next)
388 {
389 if (conn->state == STATE_ADDED)
390 {
391 for (conn2 = new_cfg->conn_first; conn2; conn2 = conn2->next)
392 {
393 if (conn2->state == STATE_TO_ADD
394 && starter_cmp_conn(conn, conn2))
395 {
396 conn->state = STATE_REPLACED;
397 conn2->state = STATE_ADDED;
398 conn2->id = conn->id;
399 break;
400 }
401 }
402 }
403 }
404
405 /* Remove conn sections that have become unused */
406 for (conn = cfg->conn_first; conn; conn = conn->next)
407 {
408 if (conn->state == STATE_ADDED)
409 {
410 if (conn->keyexchange == KEY_EXCHANGE_IKEV2)
411 starter_stroke_del_conn(conn);
412 else
413 starter_whack_del_conn(conn);
414 }
415 }
416
417 /* Look for new ca sections that are already loaded */
418 for (ca = cfg->ca_first; ca; ca = ca->next)
419 {
420 if (ca->state == STATE_ADDED)
421 {
422 for (ca2 = new_cfg->ca_first; ca2; ca2 = ca2->next)
423 {
424 if (ca2->state == STATE_TO_ADD
425 && starter_cmp_ca(ca, ca2))
426 {
427 ca->state = STATE_REPLACED;
428 ca2->state = STATE_ADDED;
429 break;
430 }
431 }
432 }
433 }
434
435 /* Remove ca sections that have become unused */
436 for (ca = cfg->ca_first; ca; ca = ca->next)
437 {
438 if (ca->state == STATE_ADDED)
439 starter_whack_del_ca(ca);
440 }
441 }
442 confread_free(cfg);
443 cfg = new_cfg;
444 }
445 else
446 {
447 plog("can't reload config file: %s -- keeping old one");
448 }
449 _action_ &= ~FLAG_ACTION_UPDATE;
450 last_reload = time(NULL);
451 }
452
453 /*
454 * Start pluto
455 */
456 if (_action_ & FLAG_ACTION_START_PLUTO)
457 {
458 if (cfg->setup.plutostart && !starter_pluto_pid())
459 {
460 DBG(DBG_CONTROL,
461 DBG_log("Attempting to start pluto...")
462 )
463
464 if (starter_start_pluto(cfg, no_fork) == 0)
465 {
466 starter_whack_listen();
467 }
468 else
469 {
470 /* schedule next try */
471 alarm(PLUTO_RESTART_DELAY);
472 }
473 }
474 _action_ &= ~FLAG_ACTION_START_PLUTO;
475
476 for (ca = cfg->ca_first; ca; ca = ca->next)
477 {
478 if (ca->state == STATE_ADDED)
479 ca->state = STATE_TO_ADD;
480 }
481
482 for (conn = cfg->conn_first; conn; conn = conn->next)
483 {
484 if (conn->state == STATE_ADDED)
485 conn->state = STATE_TO_ADD;
486 }
487 }
488
489 /*
490 * Start charon
491 */
492 if (_action_ & FLAG_ACTION_START_CHARON)
493 {
494 if (cfg->setup.charonstart && !starter_charon_pid())
495 {
496 DBG(DBG_CONTROL,
497 DBG_log("Attempting to start charon...")
498 )
499 if (starter_start_charon(cfg, no_fork))
500 {
501 /* schedule next try */
502 alarm(PLUTO_RESTART_DELAY);
503 }
504 }
505 _action_ &= ~FLAG_ACTION_START_CHARON;
506 }
507
508 /*
509 * Tell pluto to reread its interfaces
510 */
511 if (_action_ & FLAG_ACTION_LISTEN)
512 {
513 starter_whack_listen();
514 _action_ &= ~FLAG_ACTION_LISTEN;
515 }
516
517 /*
518 * Add stale conn and ca sections
519 */
520 if (starter_pluto_pid() || starter_charon_pid())
521 {
522 for (ca = cfg->ca_first; ca; ca = ca->next)
523 {
524 if (ca->state == STATE_TO_ADD)
525 {
526 starter_whack_add_ca(ca);
527 ca->state = STATE_ADDED;
528 }
529 }
530
531 for (conn = cfg->conn_first; conn; conn = conn->next)
532 {
533 if (conn->state == STATE_TO_ADD)
534 {
535 if (conn->id == 0)
536 {
537 /* affect new unique id */
538 conn->id = id++;
539 }
540 if (conn->keyexchange == KEY_EXCHANGE_IKEV2)
541 starter_stroke_add_conn(conn);
542 else
543 starter_whack_add_conn(conn);
544 conn->state = STATE_ADDED;
545
546 if (conn->startup == STARTUP_START)
547 {
548 if (conn->keyexchange == KEY_EXCHANGE_IKEV2)
549 starter_stroke_initiate_conn(conn);
550 else
551 starter_whack_initiate_conn(conn);
552 }
553 else if (conn->startup == STARTUP_ROUTE)
554 {
555 if (conn->keyexchange == KEY_EXCHANGE_IKEV2)
556 starter_stroke_route_conn(conn);
557 else
558 starter_whack_route_conn(conn);
559 }
560 }
561 }
562 }
563
564 /*
565 * If auto_update activated, when to stop select
566 */
567 if (auto_update)
568 {
569 time_t now = time(NULL);
570
571 tv.tv_sec = (now < last_reload + auto_update)
572 ? (last_reload + auto_update-now) : 0;
573 tv.tv_usec = 0;
574 }
575
576 /*
577 * Wait for something to happen
578 */
579 if (select(0, NULL, NULL, NULL, auto_update ? &tv : NULL) == 0)
580 {
581 /* timeout -> auto_update */
582 _action_ |= FLAG_ACTION_UPDATE;
583 }
584 }
585
586 return 0;
587 }
588