Return to starter.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / starter |
1.1 ! misho 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: ! 15: #define _GNU_SOURCE ! 16: ! 17: #include <sys/select.h> ! 18: #include <sys/types.h> ! 19: #include <sys/wait.h> ! 20: #include <sys/stat.h> ! 21: #include <stdlib.h> ! 22: #include <stdio.h> ! 23: #include <signal.h> ! 24: #include <syslog.h> ! 25: #include <unistd.h> ! 26: #include <sys/time.h> ! 27: #include <time.h> ! 28: #include <string.h> ! 29: #include <errno.h> ! 30: #include <fcntl.h> ! 31: #include <pwd.h> ! 32: #include <grp.h> ! 33: #include <pthread.h> ! 34: ! 35: #include <library.h> ! 36: #include <utils/backtrace.h> ! 37: #include <threading/thread.h> ! 38: #include <utils/debug.h> ! 39: ! 40: #include "confread.h" ! 41: #include "files.h" ! 42: #include "starterstroke.h" ! 43: #include "invokecharon.h" ! 44: #include "cmp.h" ! 45: ! 46: #ifndef LOG_AUTHPRIV ! 47: #define LOG_AUTHPRIV LOG_AUTH ! 48: #endif ! 49: ! 50: #define CHARON_RESTART_DELAY 5 ! 51: ! 52: static const char* cmd_default = IPSEC_DIR "/charon"; ! 53: static const char* pid_file_default = IPSEC_PIDDIR "/charon.pid"; ! 54: static const char* starter_pid_file_default = IPSEC_PIDDIR "/starter.pid"; ! 55: ! 56: char *daemon_name = NULL; ! 57: char *cmd = NULL; ! 58: char *pid_file = NULL; ! 59: char *starter_pid_file = NULL; ! 60: ! 61: static char *config_file = NULL; ! 62: ! 63: /* logging */ ! 64: static bool log_to_stderr = TRUE; ! 65: static bool log_to_syslog = TRUE; ! 66: static level_t current_loglevel = 1; ! 67: ! 68: /** ! 69: * logging function for scepclient ! 70: */ ! 71: static void starter_dbg(debug_t group, level_t level, char *fmt, ...) ! 72: { ! 73: char buffer[8192]; ! 74: char *current = buffer, *next; ! 75: va_list args; ! 76: ! 77: if (level <= current_loglevel) ! 78: { ! 79: if (log_to_stderr) ! 80: { ! 81: va_start(args, fmt); ! 82: vfprintf(stderr, fmt, args); ! 83: va_end(args); ! 84: fprintf(stderr, "\n"); ! 85: } ! 86: if (log_to_syslog) ! 87: { ! 88: /* write in memory buffer first */ ! 89: va_start(args, fmt); ! 90: vsnprintf(buffer, sizeof(buffer), fmt, args); ! 91: va_end(args); ! 92: ! 93: /* do a syslog with every line */ ! 94: while (current) ! 95: { ! 96: next = strchr(current, '\n'); ! 97: if (next) ! 98: { ! 99: *(next++) = '\0'; ! 100: } ! 101: syslog(LOG_INFO, "%s\n", current); ! 102: current = next; ! 103: } ! 104: } ! 105: } ! 106: } ! 107: ! 108: /** ! 109: * Initialize logging to stderr/syslog ! 110: */ ! 111: static void init_log(const char *program) ! 112: { ! 113: dbg = starter_dbg; ! 114: ! 115: if (log_to_stderr) ! 116: { ! 117: setbuf(stderr, NULL); ! 118: } ! 119: if (log_to_syslog) ! 120: { ! 121: openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV); ! 122: } ! 123: } ! 124: ! 125: /** ! 126: * Deinitialize logging to syslog ! 127: */ ! 128: static void close_log() ! 129: { ! 130: if (log_to_syslog) ! 131: { ! 132: closelog(); ! 133: } ! 134: } ! 135: ! 136: /** ! 137: * Return codes defined by Linux Standard Base Core Specification 3.1 ! 138: * in section 20.2. Init Script Actions ! 139: */ ! 140: #define LSB_RC_SUCCESS 0 /* success */ ! 141: #define LSB_RC_FAILURE 1 /* generic or unspecified error */ ! 142: #define LSB_RC_INVALID_ARGUMENT 2 /* invalid or excess argument(s) */ ! 143: #define LSB_RC_NOT_IMPLEMENTED 3 /* unimplemented feature (reload) */ ! 144: #define LSB_RC_NOT_ALLOWED 4 /* user had insufficient privilege */ ! 145: #define LSB_RC_NOT_INSTALLED 5 /* program is not installed */ ! 146: #define LSB_RC_NOT_CONFIGURED 6 /* program is not configured */ ! 147: #define LSB_RC_NOT_RUNNING 7 /* program is not running */ ! 148: ! 149: #define FLAG_ACTION_START_PLUTO 0x01 ! 150: #define FLAG_ACTION_UPDATE 0x02 ! 151: #define FLAG_ACTION_RELOAD 0x04 ! 152: #define FLAG_ACTION_QUIT 0x08 ! 153: #define FLAG_ACTION_LISTEN 0x10 ! 154: #define FLAG_ACTION_START_CHARON 0x20 ! 155: ! 156: static unsigned int _action_ = 0; ! 157: ! 158: /** ! 159: * Handle signals in the main thread ! 160: */ ! 161: static void signal_handler(int signal) ! 162: { ! 163: switch (signal) ! 164: { ! 165: case SIGCHLD: ! 166: { ! 167: int status, exit_status = 0; ! 168: pid_t pid; ! 169: char *name = NULL; ! 170: ! 171: while ((pid = waitpid(-1, &status, WNOHANG)) > 0) ! 172: { ! 173: if (pid == starter_charon_pid()) ! 174: { ! 175: if (asprintf(&name, " (%s)", daemon_name) < 0) ! 176: { ! 177: name = NULL; ! 178: } ! 179: } ! 180: if (WIFSIGNALED(status)) ! 181: { ! 182: DBG2(DBG_APP, "child %d%s has been killed by sig %d\n", ! 183: pid, name?name:"", WTERMSIG(status)); ! 184: } ! 185: else if (WIFSTOPPED(status)) ! 186: { ! 187: DBG2(DBG_APP, "child %d%s has been stopped by sig %d\n", ! 188: pid, name?name:"", WSTOPSIG(status)); ! 189: } ! 190: else if (WIFEXITED(status)) ! 191: { ! 192: exit_status = WEXITSTATUS(status); ! 193: if (exit_status >= SS_RC_FIRST && exit_status <= SS_RC_LAST) ! 194: { ! 195: _action_ = FLAG_ACTION_QUIT; ! 196: } ! 197: DBG2(DBG_APP, "child %d%s has quit (exit code %d)\n", ! 198: pid, name?name:"", exit_status); ! 199: } ! 200: else ! 201: { ! 202: DBG2(DBG_APP, "child %d%s has quit", pid, name?name:""); ! 203: } ! 204: if (pid == starter_charon_pid()) ! 205: { ! 206: starter_charon_sigchild(pid, exit_status); ! 207: } ! 208: } ! 209: ! 210: if (name) ! 211: { ! 212: free(name); ! 213: } ! 214: } ! 215: break; ! 216: ! 217: case SIGALRM: ! 218: _action_ |= FLAG_ACTION_START_CHARON; ! 219: break; ! 220: ! 221: case SIGHUP: ! 222: _action_ |= FLAG_ACTION_UPDATE; ! 223: break; ! 224: ! 225: case SIGTERM: ! 226: case SIGQUIT: ! 227: case SIGINT: ! 228: _action_ |= FLAG_ACTION_QUIT; ! 229: break; ! 230: ! 231: case SIGUSR1: ! 232: _action_ |= FLAG_ACTION_RELOAD; ! 233: _action_ |= FLAG_ACTION_UPDATE; ! 234: break; ! 235: ! 236: default: ! 237: DBG1(DBG_APP, "fsig(): unknown signal %d -- investigate", signal); ! 238: break; ! 239: } ! 240: } ! 241: ! 242: /** ! 243: * Handle fatal signals raised by threads ! 244: */ ! 245: static void fatal_signal_handler(int signal) ! 246: { ! 247: backtrace_t *backtrace; ! 248: ! 249: DBG1(DBG_APP, "thread %u received %d", thread_current_id(), signal); ! 250: backtrace = backtrace_create(2); ! 251: backtrace->log(backtrace, stderr, TRUE); ! 252: backtrace->destroy(backtrace); ! 253: ! 254: DBG1(DBG_APP, "killing ourself, received critical signal"); ! 255: abort(); ! 256: } ! 257: ! 258: static bool check_pid(char *file) ! 259: { ! 260: struct stat stb; ! 261: FILE *pidfile; ! 262: ! 263: if (stat(file, &stb) == 0) ! 264: { ! 265: pidfile = fopen(file, "r"); ! 266: if (pidfile) ! 267: { ! 268: char buf[64]; ! 269: pid_t pid = 0; ! 270: memset(buf, 0, sizeof(buf)); ! 271: if (fread(buf, 1, sizeof(buf), pidfile)) ! 272: { ! 273: buf[sizeof(buf) - 1] = '\0'; ! 274: pid = atoi(buf); ! 275: } ! 276: fclose(pidfile); ! 277: if (pid && pid != getpid() && kill(pid, 0) == 0) ! 278: { /* such a process is running */ ! 279: return TRUE; ! 280: } ! 281: } ! 282: DBG1(DBG_APP, "removing pidfile '%s', process not running", file); ! 283: unlink(file); ! 284: } ! 285: return FALSE; ! 286: } ! 287: ! 288: /* Set daemon name and adjust command and pid filenames accordingly */ ! 289: static bool set_daemon_name() ! 290: { ! 291: if (!daemon_name) ! 292: { ! 293: daemon_name = "charon"; ! 294: } ! 295: ! 296: if (asprintf(&cmd, IPSEC_DIR"/%s", daemon_name) < 0) ! 297: { ! 298: cmd = (char*)cmd_default; ! 299: } ! 300: ! 301: if (asprintf(&pid_file, IPSEC_PIDDIR"/%s.pid", daemon_name) < 0) ! 302: { ! 303: pid_file = (char*)pid_file_default; ! 304: } ! 305: ! 306: if (asprintf(&starter_pid_file, IPSEC_PIDDIR"/starter.%s.pid", ! 307: daemon_name) < 0) ! 308: { ! 309: starter_pid_file = (char*)starter_pid_file_default; ! 310: } ! 311: ! 312: return TRUE; ! 313: } ! 314: ! 315: static void cleanup() ! 316: { ! 317: if (cmd != cmd_default) ! 318: { ! 319: free(cmd); ! 320: } ! 321: ! 322: if (pid_file != pid_file_default) ! 323: { ! 324: free(pid_file); ! 325: } ! 326: ! 327: if (starter_pid_file != starter_pid_file_default) ! 328: { ! 329: free(starter_pid_file); ! 330: } ! 331: } ! 332: ! 333: static void usage(char *name) ! 334: { ! 335: fprintf(stderr, "Usage: starter [--nofork] [--auto-update <sec>]\n" ! 336: " [--debug|--debug-more|--debug-all|--nolog]\n" ! 337: " [--attach-gdb] [--daemon <name>]\n" ! 338: " [--conf <path to ipsec.conf>]\n"); ! 339: exit(LSB_RC_INVALID_ARGUMENT); ! 340: } ! 341: ! 342: int main (int argc, char **argv) ! 343: { ! 344: starter_config_t *cfg = NULL; ! 345: starter_config_t *new_cfg; ! 346: starter_conn_t *conn, *conn2; ! 347: starter_ca_t *ca, *ca2; ! 348: ! 349: struct sigaction action; ! 350: struct stat stb; ! 351: ! 352: int i; ! 353: int id = 1; ! 354: struct timespec ts; ! 355: unsigned long auto_update = 0; ! 356: time_t last_reload; ! 357: bool no_fork = FALSE; ! 358: bool attach_gdb = FALSE; ! 359: bool load_warning = FALSE; ! 360: bool conftest = FALSE; ! 361: ! 362: library_init(NULL, "starter"); ! 363: atexit(library_deinit); ! 364: ! 365: /* parse command line */ ! 366: for (i = 1; i < argc; i++) ! 367: { ! 368: if (streq(argv[i], "--debug")) ! 369: { ! 370: current_loglevel = 2; ! 371: } ! 372: else if (streq(argv[i], "--debug-more")) ! 373: { ! 374: current_loglevel = 3; ! 375: } ! 376: else if (streq(argv[i], "--debug-all")) ! 377: { ! 378: current_loglevel = 4; ! 379: } ! 380: else if (streq(argv[i], "--nolog")) ! 381: { ! 382: current_loglevel = 0; ! 383: } ! 384: else if (streq(argv[i], "--nofork")) ! 385: { ! 386: no_fork = TRUE; ! 387: } ! 388: else if (streq(argv[i], "--attach-gdb")) ! 389: { ! 390: no_fork = TRUE; ! 391: attach_gdb = TRUE; ! 392: } ! 393: else if (streq(argv[i], "--auto-update") && i+1 < argc) ! 394: { ! 395: auto_update = atoi(argv[++i]); ! 396: if (!auto_update) ! 397: usage(argv[0]); ! 398: } ! 399: else if (streq(argv[i], "--daemon") && i+1 < argc) ! 400: { ! 401: daemon_name = argv[++i]; ! 402: } ! 403: else if (streq(argv[i], "--conf") && i+1 < argc) ! 404: { ! 405: config_file = argv[++i]; ! 406: } ! 407: else if (streq(argv[i], "--conftest")) ! 408: { ! 409: conftest = TRUE; ! 410: } ! 411: else ! 412: { ! 413: usage(argv[0]); ! 414: } ! 415: } ! 416: ! 417: if (!set_daemon_name()) ! 418: { ! 419: DBG1(DBG_APP, "unable to set daemon name"); ! 420: exit(LSB_RC_FAILURE); ! 421: } ! 422: if (!config_file) ! 423: { ! 424: config_file = lib->settings->get_str(lib->settings, ! 425: "starter.config_file", CONFIG_FILE); ! 426: } ! 427: ! 428: init_log("ipsec_starter"); ! 429: ! 430: if (conftest) ! 431: { ! 432: int status = LSB_RC_SUCCESS; ! 433: ! 434: cfg = confread_load(config_file); ! 435: if (cfg == NULL || cfg->err > 0) ! 436: { ! 437: DBG1(DBG_APP, "config invalid!"); ! 438: status = LSB_RC_INVALID_ARGUMENT; ! 439: } ! 440: else ! 441: { ! 442: DBG1(DBG_APP, "config OK"); ! 443: } ! 444: if (cfg) ! 445: { ! 446: confread_free(cfg); ! 447: } ! 448: cleanup(); ! 449: exit(status); ! 450: } ! 451: ! 452: if (stat(cmd, &stb) != 0) ! 453: { ! 454: DBG1(DBG_APP, "IKE daemon '%s' not found", cmd); ! 455: cleanup(); ! 456: exit(LSB_RC_FAILURE); ! 457: } ! 458: ! 459: DBG1(DBG_APP, "Starting %sSwan "VERSION" IPsec [starter]...", ! 460: lib->settings->get_bool(lib->settings, ! 461: "charon.i_dont_care_about_security_and_use_aggressive_mode_psk", ! 462: FALSE) ? "weak" : "strong"); ! 463: ! 464: #ifdef LOAD_WARNING ! 465: load_warning = TRUE; ! 466: #endif ! 467: ! 468: if (lib->settings->get_bool(lib->settings, "starter.load_warning", load_warning)) ! 469: { ! 470: if (lib->settings->get_str(lib->settings, "charon.load", NULL)) ! 471: { ! 472: DBG1(DBG_APP, "!! Your strongswan.conf contains manual plugin load options for charon."); ! 473: DBG1(DBG_APP, "!! This is recommended for experts only, see"); ! 474: DBG1(DBG_APP, "!! http://wiki.strongswan.org/projects/strongswan/wiki/PluginLoad"); ! 475: } ! 476: } ! 477: ! 478: #ifndef STARTER_ALLOW_NON_ROOT ! 479: /* verify that we can start */ ! 480: if (getuid() != 0) ! 481: { ! 482: DBG1(DBG_APP, "permission denied (must be superuser)"); ! 483: cleanup(); ! 484: exit(LSB_RC_NOT_ALLOWED); ! 485: } ! 486: #endif ! 487: ! 488: if (check_pid(pid_file)) ! 489: { ! 490: DBG1(DBG_APP, "%s is already running (%s exists) -- skipping daemon start", ! 491: daemon_name, pid_file); ! 492: } ! 493: else ! 494: { ! 495: _action_ |= FLAG_ACTION_START_CHARON; ! 496: } ! 497: if (stat(DEV_RANDOM, &stb) != 0) ! 498: { ! 499: DBG1(DBG_APP, "unable to start strongSwan IPsec -- no %s!", DEV_RANDOM); ! 500: cleanup(); ! 501: exit(LSB_RC_FAILURE); ! 502: } ! 503: ! 504: if (stat(DEV_URANDOM, &stb)!= 0) ! 505: { ! 506: DBG1(DBG_APP, "unable to start strongSwan IPsec -- no %s!", DEV_URANDOM); ! 507: cleanup(); ! 508: exit(LSB_RC_FAILURE); ! 509: } ! 510: ! 511: cfg = confread_load(config_file); ! 512: if (cfg == NULL || cfg->err > 0) ! 513: { ! 514: DBG1(DBG_APP, "unable to start strongSwan -- fatal errors in config"); ! 515: if (cfg) ! 516: { ! 517: confread_free(cfg); ! 518: } ! 519: cleanup(); ! 520: exit(LSB_RC_INVALID_ARGUMENT); ! 521: } ! 522: ! 523: last_reload = time_monotonic(NULL); ! 524: ! 525: if (check_pid(starter_pid_file)) ! 526: { ! 527: DBG1(DBG_APP, "starter is already running (%s exists) -- no fork done", ! 528: starter_pid_file); ! 529: confread_free(cfg); ! 530: cleanup(); ! 531: exit(LSB_RC_SUCCESS); ! 532: } ! 533: ! 534: /* fork if we're not debugging stuff */ ! 535: if (!no_fork) ! 536: { ! 537: log_to_stderr = FALSE; ! 538: ! 539: switch (fork()) ! 540: { ! 541: case 0: ! 542: { ! 543: int fnull; ! 544: ! 545: close_log(); ! 546: ! 547: fnull = open("/dev/null", O_RDWR); ! 548: if (fnull >= 0) ! 549: { ! 550: dup2(fnull, STDIN_FILENO); ! 551: dup2(fnull, STDOUT_FILENO); ! 552: dup2(fnull, STDERR_FILENO); ! 553: close(fnull); ! 554: } ! 555: ! 556: setsid(); ! 557: init_log("ipsec_starter"); ! 558: } ! 559: break; ! 560: case -1: ! 561: DBG1(DBG_APP, "can't fork: %s", strerror(errno)); ! 562: break; ! 563: default: ! 564: confread_free(cfg); ! 565: cleanup(); ! 566: exit(LSB_RC_SUCCESS); ! 567: } ! 568: } ! 569: ! 570: /* save pid file in /var/run/starter[.daemon_name].pid */ ! 571: { ! 572: FILE *fd = fopen(starter_pid_file, "w"); ! 573: ! 574: if (fd) ! 575: { ! 576: fprintf(fd, "%u\n", getpid()); ! 577: fclose(fd); ! 578: } ! 579: } ! 580: ! 581: /* we handle these signals only in pselect() */ ! 582: memset(&action, 0, sizeof(action)); ! 583: sigemptyset(&action.sa_mask); ! 584: sigaddset(&action.sa_mask, SIGHUP); ! 585: sigaddset(&action.sa_mask, SIGINT); ! 586: sigaddset(&action.sa_mask, SIGTERM); ! 587: sigaddset(&action.sa_mask, SIGQUIT); ! 588: sigaddset(&action.sa_mask, SIGALRM); ! 589: sigaddset(&action.sa_mask, SIGUSR1); ! 590: pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL); ! 591: ! 592: /* install a handler for fatal signals */ ! 593: action.sa_handler = fatal_signal_handler; ! 594: sigaction(SIGSEGV, &action, NULL); ! 595: sigaction(SIGILL, &action, NULL); ! 596: sigaction(SIGBUS, &action, NULL); ! 597: action.sa_handler = SIG_IGN; ! 598: sigaction(SIGPIPE, &action, NULL); ! 599: ! 600: /* install main signal handler */ ! 601: action.sa_handler = signal_handler; ! 602: sigaction(SIGHUP, &action, NULL); ! 603: sigaction(SIGINT, &action, NULL); ! 604: sigaction(SIGTERM, &action, NULL); ! 605: sigaction(SIGQUIT, &action, NULL); ! 606: sigaction(SIGALRM, &action, NULL); ! 607: sigaction(SIGUSR1, &action, NULL); ! 608: /* this is not blocked above as we want to receive it asynchronously */ ! 609: sigaction(SIGCHLD, &action, NULL); ! 610: ! 611: /* empty mask for pselect() call below */ ! 612: sigemptyset(&action.sa_mask); ! 613: ! 614: for (;;) ! 615: { ! 616: /* ! 617: * Stop charon (if started) and exit ! 618: */ ! 619: if (_action_ & FLAG_ACTION_QUIT) ! 620: { ! 621: if (starter_charon_pid()) ! 622: { ! 623: starter_stop_charon(); ! 624: } ! 625: confread_free(cfg); ! 626: unlink(starter_pid_file); ! 627: cleanup(); ! 628: DBG1(DBG_APP, "ipsec starter stopped"); ! 629: close_log(); ! 630: exit(LSB_RC_SUCCESS); ! 631: } ! 632: ! 633: /* ! 634: * Delete all connections. Will be added below ! 635: */ ! 636: if (_action_ & FLAG_ACTION_RELOAD) ! 637: { ! 638: _action_ &= ~FLAG_ACTION_RELOAD; ! 639: if (starter_charon_pid()) ! 640: { ! 641: for (conn = cfg->conn_first; conn; conn = conn->next) ! 642: { ! 643: if (conn->state == STATE_ADDED) ! 644: { ! 645: if (starter_charon_pid()) ! 646: { ! 647: if (conn->startup == STARTUP_ROUTE) ! 648: { ! 649: starter_stroke_unroute_conn(conn); ! 650: } ! 651: starter_stroke_del_conn(conn); ! 652: } ! 653: conn->state = STATE_TO_ADD; ! 654: } ! 655: } ! 656: for (ca = cfg->ca_first; ca; ca = ca->next) ! 657: { ! 658: if (ca->state == STATE_ADDED) ! 659: { ! 660: if (starter_charon_pid()) ! 661: { ! 662: starter_stroke_del_ca(ca); ! 663: } ! 664: ca->state = STATE_TO_ADD; ! 665: } ! 666: } ! 667: } ! 668: } ! 669: ! 670: /* ! 671: * Update configuration ! 672: */ ! 673: if (_action_ & FLAG_ACTION_UPDATE) ! 674: { ! 675: _action_ &= ~FLAG_ACTION_UPDATE; ! 676: DBG2(DBG_APP, "Reloading config..."); ! 677: new_cfg = confread_load(config_file); ! 678: ! 679: if (new_cfg && (new_cfg->err == 0)) ! 680: { ! 681: /* Switch to new config. New conn will be loaded below */ ! 682: ! 683: /* Look for new connections that are already loaded */ ! 684: for (conn = cfg->conn_first; conn; conn = conn->next) ! 685: { ! 686: if (conn->state == STATE_ADDED) ! 687: { ! 688: for (conn2 = new_cfg->conn_first; conn2; conn2 = conn2->next) ! 689: { ! 690: if (conn2->state == STATE_TO_ADD && starter_cmp_conn(conn, conn2)) ! 691: { ! 692: conn->state = STATE_REPLACED; ! 693: conn2->state = STATE_ADDED; ! 694: conn2->id = conn->id; ! 695: break; ! 696: } ! 697: } ! 698: } ! 699: } ! 700: ! 701: /* Remove conn sections that have become unused */ ! 702: for (conn = cfg->conn_first; conn; conn = conn->next) ! 703: { ! 704: if (conn->state == STATE_ADDED) ! 705: { ! 706: if (starter_charon_pid()) ! 707: { ! 708: if (conn->startup == STARTUP_ROUTE) ! 709: { ! 710: starter_stroke_unroute_conn(conn); ! 711: } ! 712: starter_stroke_del_conn(conn); ! 713: } ! 714: } ! 715: } ! 716: ! 717: /* Look for new ca sections that are already loaded */ ! 718: for (ca = cfg->ca_first; ca; ca = ca->next) ! 719: { ! 720: if (ca->state == STATE_ADDED) ! 721: { ! 722: for (ca2 = new_cfg->ca_first; ca2; ca2 = ca2->next) ! 723: { ! 724: if (ca2->state == STATE_TO_ADD && starter_cmp_ca(ca, ca2)) ! 725: { ! 726: ca->state = STATE_REPLACED; ! 727: ca2->state = STATE_ADDED; ! 728: break; ! 729: } ! 730: } ! 731: } ! 732: } ! 733: ! 734: /* Remove ca sections that have become unused */ ! 735: for (ca = cfg->ca_first; ca; ca = ca->next) ! 736: { ! 737: if (ca->state == STATE_ADDED) ! 738: { ! 739: if (starter_charon_pid()) ! 740: { ! 741: starter_stroke_del_ca(ca); ! 742: } ! 743: } ! 744: } ! 745: confread_free(cfg); ! 746: cfg = new_cfg; ! 747: } ! 748: else ! 749: { ! 750: DBG1(DBG_APP, "can't reload config file due to errors -- keeping old one"); ! 751: if (new_cfg) ! 752: { ! 753: confread_free(new_cfg); ! 754: } ! 755: } ! 756: last_reload = time_monotonic(NULL); ! 757: } ! 758: ! 759: /* ! 760: * Start daemon ! 761: */ ! 762: if (_action_ & FLAG_ACTION_START_CHARON) ! 763: { ! 764: _action_ &= ~FLAG_ACTION_START_CHARON; ! 765: if (!starter_charon_pid()) ! 766: { ! 767: DBG2(DBG_APP, "Attempting to start %s...", daemon_name); ! 768: if (starter_start_charon(cfg, no_fork, attach_gdb)) ! 769: { ! 770: /* schedule next try */ ! 771: alarm(CHARON_RESTART_DELAY); ! 772: } ! 773: starter_stroke_configure(cfg); ! 774: } ! 775: ! 776: for (ca = cfg->ca_first; ca; ca = ca->next) ! 777: { ! 778: if (ca->state == STATE_ADDED) ! 779: { ! 780: ca->state = STATE_TO_ADD; ! 781: } ! 782: } ! 783: ! 784: for (conn = cfg->conn_first; conn; conn = conn->next) ! 785: { ! 786: if (conn->state == STATE_ADDED) ! 787: { ! 788: conn->state = STATE_TO_ADD; ! 789: } ! 790: } ! 791: } ! 792: ! 793: /* ! 794: * Add stale conn and ca sections ! 795: */ ! 796: if (starter_charon_pid()) ! 797: { ! 798: for (ca = cfg->ca_first; ca; ca = ca->next) ! 799: { ! 800: if (ca->state == STATE_TO_ADD) ! 801: { ! 802: if (starter_charon_pid()) ! 803: { ! 804: starter_stroke_add_ca(ca); ! 805: } ! 806: ca->state = STATE_ADDED; ! 807: } ! 808: } ! 809: ! 810: for (conn = cfg->conn_first; conn; conn = conn->next) ! 811: { ! 812: if (conn->state == STATE_TO_ADD) ! 813: { ! 814: if (conn->id == 0) ! 815: { ! 816: /* affect new unique id */ ! 817: conn->id = id++; ! 818: } ! 819: if (starter_charon_pid()) ! 820: { ! 821: starter_stroke_add_conn(cfg, conn); ! 822: } ! 823: conn->state = STATE_ADDED; ! 824: ! 825: if (conn->startup == STARTUP_START) ! 826: { ! 827: if (starter_charon_pid()) ! 828: { ! 829: starter_stroke_initiate_conn(conn); ! 830: } ! 831: } ! 832: else if (conn->startup == STARTUP_ROUTE) ! 833: { ! 834: if (starter_charon_pid()) ! 835: { ! 836: starter_stroke_route_conn(conn); ! 837: } ! 838: } ! 839: } ! 840: } ! 841: } ! 842: ! 843: /* ! 844: * If auto_update activated, when to stop select ! 845: */ ! 846: if (auto_update) ! 847: { ! 848: time_t now = time_monotonic(NULL); ! 849: ! 850: ts.tv_sec = (now < last_reload + auto_update) ? ! 851: (last_reload + auto_update - now) : 0; ! 852: ts.tv_nsec = 0; ! 853: } ! 854: ! 855: /* ! 856: * Wait for something to happen ! 857: */ ! 858: if (!_action_ && ! 859: pselect(0, NULL, NULL, NULL, auto_update ? &ts : NULL, ! 860: &action.sa_mask) == 0) ! 861: { ! 862: /* timeout -> auto_update */ ! 863: _action_ |= FLAG_ACTION_UPDATE; ! 864: } ! 865: } ! 866: exit(LSB_RC_SUCCESS); ! 867: }