make starter behave more gracefully in the presence of non-fatal errors
[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 if (pid == starter_pluto_pid())
92 starter_pluto_sigchild(pid);
93 if (pid == starter_charon_pid())
94 starter_charon_sigchild(pid);
95 }
96 }
97 break;
98
99 case SIGPIPE:
100 /** ignore **/
101 break;
102
103 case SIGALRM:
104 _action_ |= FLAG_ACTION_START_PLUTO;
105 _action_ |= FLAG_ACTION_START_CHARON;
106 break;
107
108 case SIGHUP:
109 _action_ |= FLAG_ACTION_UPDATE;
110 break;
111
112 case SIGTERM:
113 case SIGQUIT:
114 case SIGINT:
115 _action_ |= FLAG_ACTION_QUIT;
116 break;
117
118 case SIGUSR1:
119 _action_ |= FLAG_ACTION_RELOAD;
120 _action_ |= FLAG_ACTION_UPDATE;
121 break;
122
123 default:
124 plog("fsig(): unknown signal %d -- investigate", signal);
125 break;
126 }
127 }
128
129 static void
130 usage(char *name)
131 {
132 fprintf(stderr, "Usage: starter [--nofork] [--auto-update <sec>] "
133 "[--debug|--debug-more|--debug-all]\n");
134 exit(1);
135 }
136
137 int main (int argc, char **argv)
138 {
139 starter_config_t *cfg = NULL;
140 starter_config_t *new_cfg;
141 starter_conn_t *conn, *conn2;
142 starter_ca_t *ca, *ca2;
143
144 struct stat stb;
145
146 char *err = NULL;
147 int i;
148 int id = 1;
149 struct timeval tv;
150 unsigned long auto_update = 0;
151 time_t last_reload;
152 bool no_fork = FALSE;
153
154 /* global variables defined in log.h */
155 log_to_stderr = TRUE;
156 base_debugging = DBG_NONE;
157
158 /* parse command line */
159 for (i = 1; i < argc; i++)
160 {
161 if (streq(argv[i], "--debug"))
162 {
163 base_debugging |= DBG_CONTROL;
164 }
165 else if (streq(argv[i], "--debug-more"))
166 {
167 base_debugging |= DBG_CONTROLMORE;
168 }
169 else if (streq(argv[i], "--debug-all"))
170 {
171 base_debugging |= DBG_ALL;
172 }
173 else if (streq(argv[i], "--nofork"))
174 {
175 no_fork = TRUE;
176 }
177 else if (streq(argv[i], "--auto-update") && i+1 < argc)
178 {
179 auto_update = atoi(argv[++i]);
180 if (!auto_update)
181 usage(argv[0]);
182 }
183 else
184 {
185 usage(argv[0]);
186 }
187 }
188
189 /* Init */
190 init_log("ipsec_starter");
191 cur_debugging = base_debugging;
192
193 signal(SIGHUP, fsig);
194 signal(SIGCHLD, fsig);
195 signal(SIGPIPE, fsig);
196 signal(SIGINT, fsig);
197 signal(SIGTERM, fsig);
198 signal(SIGQUIT, fsig);
199 signal(SIGALRM, fsig);
200 signal(SIGUSR1, fsig);
201
202 plog("Starting strongSwan %s IPsec [starter]...", ipsec_version_code());
203
204 /* verify that we can start */
205 if (getuid() != 0)
206 {
207 plog("permission denied (must be superuser)");
208 exit(1);
209 }
210
211 if (stat(PLUTO_PID_FILE, &stb) == 0)
212 {
213 plog("pluto is already running (%s exists) -- skipping pluto start", PLUTO_PID_FILE);
214 }
215 else
216 {
217 _action_ |= FLAG_ACTION_START_PLUTO;
218 }
219 if (stat(CHARON_PID_FILE, &stb) == 0)
220 {
221 plog("charon is already running (%s exists) -- skipping charon start", CHARON_PID_FILE);
222 }
223 else
224 {
225 _action_ |= FLAG_ACTION_START_CHARON;
226 }
227 if (stat(DEV_RANDOM, &stb) != 0)
228 {
229 plog("unable to start strongSwan IPsec -- no %s!", DEV_RANDOM);
230 exit(1);
231 }
232
233 if (stat(DEV_URANDOM, &stb)!= 0)
234 {
235 plog("unable to start strongSwan IPsec -- no %s!", DEV_URANDOM);
236 exit(1);
237 }
238
239 cfg = confread_load(CONFIG_FILE);
240 if (cfg->err > 0)
241 {
242 plog("unable to start strongSwan -- fatal errors in config");
243 confread_free(cfg);
244 exit(1);
245 }
246
247 /* determine if we have a native netkey IPsec stack */
248 if (!starter_netkey_init())
249 {
250 plog("no 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 setsid();
281 }
282 break;
283 case -1:
284 plog("can't fork: %s", strerror(errno));
285 break;
286 default:
287 exit(0);
288 }
289 }
290
291 /* save pid file in /var/run/starter.pid */
292 {
293 FILE *fd = fopen(STARTER_PID_FILE, "w");
294
295 if (fd)
296 {
297 fprintf(fd, "%u\n", getpid());
298 fclose(fd);
299 }
300 }
301
302 for (;;)
303 {
304 /*
305 * Stop pluto/charon (if started) and exit
306 */
307 if (_action_ & FLAG_ACTION_QUIT)
308 {
309 if (starter_pluto_pid())
310 starter_stop_pluto();
311 if (starter_charon_pid())
312 starter_stop_charon();
313 starter_netkey_cleanup();
314 confread_free(cfg);
315 unlink(STARTER_PID_FILE);
316 unlink(INFO_FILE);
317 #ifdef LEAK_DETECTIVE
318 report_leaks();
319 #endif /* LEAK_DETECTIVE */
320 close_log();
321 plog("ipsec starter stopped");
322 exit(0);
323 }
324
325 /*
326 * Delete all connections. Will be added below
327 */
328 if (_action_ & FLAG_ACTION_RELOAD)
329 {
330 if (starter_pluto_pid() || starter_charon_pid())
331 {
332 for (conn = cfg->conn_first; conn; conn = conn->next)
333 {
334 if (conn->state == STATE_ADDED)
335 {
336 if (starter_charon_pid())
337 {
338 starter_stroke_del_conn(conn);
339 }
340 if (starter_pluto_pid())
341 {
342 starter_whack_del_conn(conn);
343 }
344 conn->state = STATE_TO_ADD;
345 }
346 }
347 for (ca = cfg->ca_first; ca; ca = ca->next)
348 {
349 if (ca->state == STATE_ADDED)
350 {
351 if (starter_charon_pid())
352 {
353 starter_stroke_del_ca(ca);
354 }
355 if (starter_pluto_pid())
356 {
357 starter_whack_del_ca(ca);
358 }
359 ca->state = STATE_TO_ADD;
360 }
361 }
362 }
363 _action_ &= ~FLAG_ACTION_RELOAD;
364 }
365
366 /*
367 * Update configuration
368 */
369 if (_action_ & FLAG_ACTION_UPDATE)
370 {
371 err = NULL;
372 DBG(DBG_CONTROL,
373 DBG_log("Reloading config...")
374 );
375 new_cfg = confread_load(CONFIG_FILE);
376
377 if (new_cfg->err + new_cfg->non_fatal_err == 0)
378 {
379 /* Switch to new config. New conn will be loaded below */
380 if (!starter_cmp_defaultroute(&new_cfg->defaultroute
381 , &cfg->defaultroute))
382 {
383 _action_ |= FLAG_ACTION_LISTEN;
384 }
385
386 if (!starter_cmp_pluto(cfg, new_cfg))
387 {
388 plog("Pluto has changed");
389 if (starter_pluto_pid())
390 starter_stop_pluto();
391 _action_ &= ~FLAG_ACTION_LISTEN;
392 _action_ |= FLAG_ACTION_START_PLUTO;
393 }
394 else
395 {
396 /* Only reload conn and ca sections if pluto is not killed */
397
398 /* Look for new connections that are already loaded */
399 for (conn = cfg->conn_first; conn; conn = conn->next)
400 {
401 if (conn->state == STATE_ADDED)
402 {
403 for (conn2 = new_cfg->conn_first; conn2; conn2 = conn2->next)
404 {
405 if (conn2->state == STATE_TO_ADD && starter_cmp_conn(conn, conn2))
406 {
407 conn->state = STATE_REPLACED;
408 conn2->state = STATE_ADDED;
409 conn2->id = conn->id;
410 break;
411 }
412 }
413 }
414 }
415
416 /* Remove conn sections that have become unused */
417 for (conn = cfg->conn_first; conn; conn = conn->next)
418 {
419 if (conn->state == STATE_ADDED)
420 {
421 if (starter_charon_pid())
422 {
423 starter_stroke_del_conn(conn);
424 }
425 if (starter_pluto_pid())
426 {
427 starter_whack_del_conn(conn);
428 }
429 }
430 }
431
432 /* Look for new ca sections that are already loaded */
433 for (ca = cfg->ca_first; ca; ca = ca->next)
434 {
435 if (ca->state == STATE_ADDED)
436 {
437 for (ca2 = new_cfg->ca_first; ca2; ca2 = ca2->next)
438 {
439 if (ca2->state == STATE_TO_ADD && starter_cmp_ca(ca, ca2))
440 {
441 ca->state = STATE_REPLACED;
442 ca2->state = STATE_ADDED;
443 break;
444 }
445 }
446 }
447 }
448
449 /* Remove ca sections that have become unused */
450 for (ca = cfg->ca_first; ca; ca = ca->next)
451 {
452 if (ca->state == STATE_ADDED)
453 {
454 if (starter_charon_pid())
455 {
456 starter_stroke_del_ca(ca);
457 }
458 if (starter_pluto_pid())
459 {
460 starter_whack_del_ca(ca);
461 }
462 }
463 }
464 }
465 confread_free(cfg);
466 cfg = new_cfg;
467 }
468 else
469 {
470 plog("can't reload config file due to errors -- keeping old one");
471 confread_free(new_cfg);
472 }
473 _action_ &= ~FLAG_ACTION_UPDATE;
474 last_reload = time(NULL);
475 }
476
477 /*
478 * Start pluto
479 */
480 if (_action_ & FLAG_ACTION_START_PLUTO)
481 {
482 if (cfg->setup.plutostart && !starter_pluto_pid())
483 {
484 DBG(DBG_CONTROL,
485 DBG_log("Attempting to start pluto...")
486 );
487
488 if (starter_start_pluto(cfg, no_fork) == 0)
489 {
490 starter_whack_listen();
491 }
492 else
493 {
494 /* schedule next try */
495 alarm(PLUTO_RESTART_DELAY);
496 }
497 }
498 _action_ &= ~FLAG_ACTION_START_PLUTO;
499
500 for (ca = cfg->ca_first; ca; ca = ca->next)
501 {
502 if (ca->state == STATE_ADDED)
503 ca->state = STATE_TO_ADD;
504 }
505
506 for (conn = cfg->conn_first; conn; conn = conn->next)
507 {
508 if (conn->state == STATE_ADDED)
509 conn->state = STATE_TO_ADD;
510 }
511 }
512
513 /*
514 * Start charon
515 */
516 if (_action_ & FLAG_ACTION_START_CHARON)
517 {
518 if (cfg->setup.charonstart && !starter_charon_pid())
519 {
520 DBG(DBG_CONTROL,
521 DBG_log("Attempting to start charon...")
522 );
523 if (starter_start_charon(cfg, no_fork))
524 {
525 /* schedule next try */
526 alarm(PLUTO_RESTART_DELAY);
527 }
528 }
529 _action_ &= ~FLAG_ACTION_START_CHARON;
530 }
531
532 /*
533 * Tell pluto to reread its interfaces
534 */
535 if (_action_ & FLAG_ACTION_LISTEN)
536 {
537 if (starter_pluto_pid())
538 {
539 starter_whack_listen();
540 _action_ &= ~FLAG_ACTION_LISTEN;
541 }
542 }
543
544 /*
545 * Add stale conn and ca sections
546 */
547 if (starter_pluto_pid() || starter_charon_pid())
548 {
549 for (ca = cfg->ca_first; ca; ca = ca->next)
550 {
551 if (ca->state == STATE_TO_ADD)
552 {
553 if (starter_charon_pid())
554 {
555 starter_stroke_add_ca(ca);
556 }
557 if (starter_pluto_pid())
558 {
559 starter_whack_add_ca(ca);
560 }
561 ca->state = STATE_ADDED;
562 }
563 }
564
565 for (conn = cfg->conn_first; conn; conn = conn->next)
566 {
567 if (conn->state == STATE_TO_ADD)
568 {
569 if (conn->id == 0)
570 {
571 /* affect new unique id */
572 conn->id = id++;
573 }
574 if (starter_charon_pid())
575 {
576 starter_stroke_add_conn(conn);
577 }
578 if (starter_pluto_pid())
579 {
580 starter_whack_add_conn(conn);
581 }
582 conn->state = STATE_ADDED;
583
584 if (conn->startup == STARTUP_START)
585 {
586 if (conn->keyexchange == KEY_EXCHANGE_IKEV2)
587 {
588 if (starter_charon_pid())
589 {
590 starter_stroke_initiate_conn(conn);
591 }
592 }
593 else
594 {
595 if (starter_pluto_pid())
596 {
597 starter_whack_initiate_conn(conn);
598 }
599 }
600 }
601 else if (conn->startup == STARTUP_ROUTE)
602 {
603 if (conn->keyexchange == KEY_EXCHANGE_IKEV2)
604 {
605 if (starter_charon_pid())
606 {
607 starter_stroke_route_conn(conn);
608 }
609 }
610 else
611 {
612 if (starter_pluto_pid())
613 {
614 starter_whack_route_conn(conn);
615 }
616 }
617 }
618 }
619 }
620 }
621
622 /*
623 * If auto_update activated, when to stop select
624 */
625 if (auto_update)
626 {
627 time_t now = time(NULL);
628
629 tv.tv_sec = (now < last_reload + auto_update)
630 ? (last_reload + auto_update-now) : 0;
631 tv.tv_usec = 0;
632 }
633
634 /*
635 * Wait for something to happen
636 */
637 if (select(0, NULL, NULL, NULL, auto_update ? &tv : NULL) == 0)
638 {
639 /* timeout -> auto_update */
640 _action_ |= FLAG_ACTION_UPDATE;
641 }
642 }
643
644 return 0;
645 }
646