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