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

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2006 Martin Willi
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
        !             5:  * Copyright (C) 2001-2002 Mathieu Lafon
        !             6:  * Arkoon Network Security
        !             7:  *
        !             8:  * Ported from invokepluto.c to fit charons needs.
        !             9:  *
        !            10:  * This program is free software; you can redistribute it and/or modify it
        !            11:  * under the terms of the GNU General Public License as published by the
        !            12:  * Free Software Foundation; either version 2 of the License, or (at your
        !            13:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            14:  *
        !            15:  * This program is distributed in the hope that it will be useful, but
        !            16:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            17:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            18:  * for more details.
        !            19:  */
        !            20: 
        !            21: #include <sys/types.h>
        !            22: #include <sys/stat.h>
        !            23: #include <unistd.h>
        !            24: #include <signal.h>
        !            25: #include <string.h>
        !            26: #include <stdlib.h>
        !            27: #include <errno.h>
        !            28: 
        !            29: #include <library.h>
        !            30: #include <utils/debug.h>
        !            31: 
        !            32: #include "confread.h"
        !            33: #include "invokecharon.h"
        !            34: #include "files.h"
        !            35: 
        !            36: static int _charon_pid = 0;
        !            37: static int _stop_requested;
        !            38: 
        !            39: pid_t starter_charon_pid(void)
        !            40: {
        !            41:        return _charon_pid;
        !            42: }
        !            43: 
        !            44: void starter_charon_sigchild(pid_t pid, int status)
        !            45: {
        !            46:        if (pid == _charon_pid)
        !            47:        {
        !            48:                _charon_pid = 0;
        !            49:                if (status == SS_RC_LIBSTRONGSWAN_INTEGRITY ||
        !            50:                        status == SS_RC_DAEMON_INTEGRITY)
        !            51:                {
        !            52:                        DBG1(DBG_APP, "%s has quit: integrity test of %s failed",
        !            53:                                 daemon_name, (status == 64) ? "libstrongswan" : daemon_name);
        !            54:                        _stop_requested = 1;
        !            55:                }
        !            56:                else if (status == SS_RC_INITIALIZATION_FAILED)
        !            57:                {
        !            58:                        DBG1(DBG_APP, "%s has quit: initialization failed", daemon_name);
        !            59:                        _stop_requested = 1;
        !            60:                }
        !            61:                if (!_stop_requested)
        !            62:                {
        !            63:                        DBG1(DBG_APP, "%s has died -- restart scheduled (%dsec)",
        !            64:                                 daemon_name, CHARON_RESTART_DELAY);
        !            65:                        alarm(CHARON_RESTART_DELAY);   // restart in 5 sec
        !            66:                }
        !            67:                unlink(pid_file);
        !            68:        }
        !            69: }
        !            70: 
        !            71: int starter_stop_charon (void)
        !            72: {
        !            73:        int i;
        !            74:        pid_t pid = _charon_pid;
        !            75: 
        !            76:        if (pid)
        !            77:        {
        !            78:                _stop_requested = 1;
        !            79: 
        !            80:                /* be more and more aggressive */
        !            81:                for (i = 0; i < 50 && (pid = _charon_pid) != 0; i++)
        !            82:                {
        !            83:                        if (i == 0)
        !            84:                        {
        !            85:                                kill(pid, SIGINT);
        !            86:                        }
        !            87:                        else if (i < 40)
        !            88:                        {
        !            89:                                kill(pid, SIGTERM);
        !            90:                        }
        !            91:                        else if (i == 40)
        !            92:                        {
        !            93:                                kill(pid, SIGKILL);
        !            94:                                DBG1(DBG_APP, "starter_stop_charon(): %s does not respond, sending KILL",
        !            95:                                         daemon_name);
        !            96:                        }
        !            97:                        else
        !            98:                        {
        !            99:                                kill(pid, SIGKILL);
        !           100:                        }
        !           101:                        usleep(200000); /* sleep for 200 ms */
        !           102:                }
        !           103:                if (_charon_pid == 0)
        !           104:                {
        !           105:                        DBG1(DBG_APP, "%s stopped after %d ms", daemon_name, 200*i);
        !           106:                        return 0;
        !           107:                }
        !           108:                DBG1(DBG_APP, "starter_stop_charon(): can't stop %s !!!", daemon_name);
        !           109:                return -1;
        !           110:        }
        !           111:        else
        !           112:        {
        !           113:                DBG1(DBG_APP, "stater_stop_charon(): %s was not started...", daemon_name);
        !           114:        }
        !           115:        return -1;
        !           116: }
        !           117: 
        !           118: 
        !           119: int starter_start_charon (starter_config_t *cfg, bool no_fork, bool attach_gdb)
        !           120: {
        !           121:        struct stat stb;
        !           122:        int pid, i;
        !           123:        char buffer[BUF_LEN];
        !           124:        int argc = 1;
        !           125:        char *arg[] = {
        !           126:                cmd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        !           127:                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        !           128:                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        !           129:                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
        !           130:        };
        !           131: 
        !           132:        if (attach_gdb)
        !           133:        {
        !           134:                argc = 0;
        !           135:                arg[argc++] = "/usr/bin/gdb";
        !           136:                arg[argc++] = "--args";
        !           137:                arg[argc++] = cmd;
        !           138:                }
        !           139:        if (!no_fork)
        !           140:        {
        !           141:                arg[argc++] = "--use-syslog";
        !           142:        }
        !           143: 
        !           144:        /* parse debug string */
        !           145:        {
        !           146:                int level;
        !           147:                char type[4];
        !           148:                char *pos = cfg->setup.charondebug;
        !           149:                char *buf_pos = buffer;
        !           150: 
        !           151:                while (pos && sscanf(pos, "%3s %d,", type, &level) == 2)
        !           152:                {
        !           153:                        snprintf(buf_pos, buffer + sizeof(buffer) - buf_pos, "--debug-%s", type);
        !           154:                        arg[argc++] = buf_pos;
        !           155:                        buf_pos += strlen(buf_pos) + 1;
        !           156:                        if (buf_pos >= buffer + sizeof(buffer))
        !           157:                        {
        !           158:                                break;
        !           159:                        }
        !           160:                        snprintf(buf_pos, buffer + sizeof(buffer) - buf_pos, "%d", level);
        !           161:                        arg[argc++] = buf_pos;
        !           162:                        buf_pos += strlen(buf_pos) + 1;
        !           163:                        if (buf_pos >= buffer + sizeof(buffer))
        !           164:                        {
        !           165:                                break;
        !           166:                        }
        !           167: 
        !           168:                        /* get next */
        !           169:                        pos = strchr(pos, ',');
        !           170:                        if (pos)
        !           171:                        {
        !           172:                                pos++;
        !           173:                        }
        !           174:                }
        !           175:        }
        !           176: 
        !           177:        if (_charon_pid)
        !           178:        {
        !           179:                DBG1(DBG_APP, "starter_start_charon(): %s already started...",
        !           180:                         daemon_name);
        !           181:                return -1;
        !           182:        }
        !           183:        else
        !           184:        {
        !           185:                unlink(CHARON_CTL_FILE);
        !           186:                _stop_requested = 0;
        !           187: 
        !           188:                pid = fork();
        !           189:                switch (pid)
        !           190:                {
        !           191:                case -1:
        !           192:                        DBG1(DBG_APP, "can't fork(): %s", strerror(errno));
        !           193:                        return -1;
        !           194:                case 0:
        !           195:                        /* child */
        !           196:                        setsid();
        !           197:                        closefrom(3);
        !           198:                        sigprocmask(SIG_SETMASK, 0, NULL);
        !           199:                        /* disable glibc's malloc checker, conflicts with leak detective */
        !           200:                        setenv("MALLOC_CHECK_", "0", 1);
        !           201:                        execv(arg[0], arg);
        !           202:                        DBG1(DBG_APP, "can't execv(%s,...): %s", arg[0], strerror(errno));
        !           203:                        exit(1);
        !           204:                default:
        !           205:                        /* father */
        !           206:                        _charon_pid = pid;
        !           207:                        while (attach_gdb)
        !           208:                        {
        !           209:                                /* wait indefinitely if gdb is attached */
        !           210:                                usleep(10000);
        !           211:                                if (stat(pid_file, &stb) == 0)
        !           212:                                {
        !           213:                                        return 0;
        !           214:                                }
        !           215:                        }
        !           216:                        for (i = 0; i < 500 && _charon_pid; i++)
        !           217:                        {
        !           218:                                /* wait for charon for a maximum of 500 x 20 ms = 10 s */
        !           219:                                usleep(20000);
        !           220:                                if (stat(pid_file, &stb) == 0)
        !           221:                                {
        !           222:                                        DBG1(DBG_APP, "%s (%d) started after %d ms", daemon_name,
        !           223:                                                 _charon_pid, 20*(i+1));
        !           224:                                        return 0;
        !           225:                                }
        !           226:                        }
        !           227:                        if (_charon_pid)
        !           228:                        {
        !           229:                                /* If charon is started but with no ctl file, stop it */
        !           230:                                DBG1(DBG_APP, "%s too long to start... - kill kill",
        !           231:                                         daemon_name);
        !           232:                                for (i = 0; i < 20 && (pid = _charon_pid) != 0; i++)
        !           233:                                {
        !           234:                                        if (i == 0)
        !           235:                                        {
        !           236:                                                kill(pid, SIGINT);
        !           237:                                        }
        !           238:                                        else if (i < 10)
        !           239:                                        {
        !           240:                                                kill(pid, SIGTERM);
        !           241:                                        }
        !           242:                                        else
        !           243:                                        {
        !           244:                                                kill(pid, SIGKILL);
        !           245:                                        }
        !           246:                                        usleep(20000); /* sleep for 20 ms */
        !           247:                                }
        !           248:                        }
        !           249:                        else
        !           250:                        {
        !           251:                                DBG1(DBG_APP, "%s refused to be started", daemon_name);
        !           252:                        }
        !           253:                        return -1;
        !           254:                }
        !           255:        }
        !           256:        return -1;
        !           257: }

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