Annotation of embedaddon/strongswan/src/starter/starter.c, revision 1.1

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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>