File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / starter / invokecharon.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:43 2020 UTC (4 years, 4 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    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>