Annotation of embedaddon/strongswan/src/starter/invokecharon.c, revision 1.1.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>