Return to invokecharon.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / starter |
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: }