⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 starter.c

📁 ipsec vpn
💻 C
字号:
/* Openswan IPsec starter (starter.c) * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security * Copyright (C) 2004 Xelerance Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * for more details. * * RCSID $Id: starter.c,v 1.12 2005/01/11 17:52:51 ken Exp $ */#include <sys/types.h>#include <sys/wait.h>#include <sys/stat.h>#include <sys/queue.h>#include <stdlib.h>#include <stdio.h>#include <signal.h>#include <unistd.h>#include <sys/time.h>#include <time.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include "confread.h"#include "confwrite.h"#include "starterlog.h"#include "files.h"#include "starterwhack.h"#include "pluto.h"#include "klips.h"#include "netkey.h"#include "cmp.h"#include "interfaces.h"#include "keywords.h"#define FLAG_ACTION_START_PLUTO   0x01#define FLAG_ACTION_RELOAD        0x02#define FLAG_ACTION_FORCE_RELOAD  0x04#define FLAG_ACTION_QUIT          0x08#define FLAG_ACTION_LISTEN        0x10static unsigned int _action_ = 0;int verbose = 0;int warningsarefatal = 0;char configfile[PATH_MAX];char rootdir[PATH_MAX];       /* when evaluating paths, prefix this to them */int showonly = 0;static void fsig(int signal){	 switch (signal) {	 	case SIGCHLD: {				int status;				pid_t pid;				char *name = NULL;				while ((pid=waitpid(-1,&status,WNOHANG))>0) {					if (pid == starter_pluto_pid()) name = " (Pluto)";					if (WIFSIGNALED(status))						starter_log(LOG_LEVEL_INFO, 							"child %d%s has been killed by sig %d\n",							pid, name?name:"", WTERMSIG(status));					else if (WIFSTOPPED(status))						starter_log(LOG_LEVEL_INFO, 							"child %d%s has been stopped by sig %d\n",							pid, name?name:"", WSTOPSIG(status));					else if (WIFEXITED(status))						starter_log(LOG_LEVEL_INFO, 							"child %d%s has quit (exit code %d)\n",							pid, name?name:"", WEXITSTATUS(status));					else						starter_log(LOG_LEVEL_INFO, 							"child %d%s has quit", pid, name?name:"");					if (pid == starter_pluto_pid())						starter_pluto_sigchild(pid);				}			}			break;		case SIGPIPE:			/** ignore **/			break;		case SIGALRM:			_action_ |= FLAG_ACTION_START_PLUTO;			break;		case SIGHUP:			_action_ |= FLAG_ACTION_RELOAD;			break;		case SIGTERM:		case SIGQUIT:		case SIGINT:			_action_ |= FLAG_ACTION_QUIT;			break;		case SIGUSR1:			_action_ |= FLAG_ACTION_FORCE_RELOAD;			_action_ |= FLAG_ACTION_RELOAD;			break;		default:			starter_log(LOG_LEVEL_ERR, 				"fsig(): unknown signal %d -- investigate", signal);			break;	 }}static void usage(char *name){	fprintf(stderr, "Usage: %s [--debug] [--auto_reload <x sec>]\n", name);	exit(1);}int main (int argc, char **argv){	struct starter_config *cfg = NULL, *new_cfg;	struct starter_conn *conn, *conn2;	struct stat stb;	char *err = NULL;	int i, debug=0, no_fork=0;	struct timeval tv;	unsigned long auto_reload = 0;	time_t last_reload;	int id = 1;	extern int yydebug;	char *confdir;	bool justdump = FALSE;	/* find environment location for /etc */	confdir = getenv(IPSEC_CONFDIR_VAR);	if(confdir == NULL)	{	    confdir = IPSEC_CONFDIR;	}			/* calculate default value for configfile */	configfile[0]='\0';	strncat(configfile, confdir, sizeof(configfile));	if(configfile[strlen(configfile)-1]!='/')	{	    strncat(configfile, "/", sizeof(configfile));	}	strncat(configfile, "ipsec.conf", sizeof(configfile));	/**	 * Parse command line	 */	for (i=1; i<argc; i++) {		if (strcmp(argv[i],"--debug")==0) {			debug = 1;			no_fork = 1;		}		else if (strcmp(argv[i],"--no_fork")==0) {			no_fork = 1;		}		else if (strcmp(argv[i],"--configfile")==0 && (i+1)<argc && argv[i+1]!=NULL) {		    strcpy(configfile, argv[i+1]);		    i++;		}		else if (strcmp(argv[i],"--rootdir")==0 && (i+1)<argc && argv[i+1]!=NULL) {		    strcpy(rootdir, argv[i+1]);		    i++;		}		else if (strcmp(argv[i],"--parsedebug")==0) {  	                yydebug = 1;		}		else if (strcmp(argv[i],"--verbose")==0) {		    verbose = 1;		}		else if (strcmp(argv[i],"-Werror")==0) {		    warningsarefatal = 1;		}		else if (strcmp(argv[i],"--dumpcfg")==0) {		    justdump = TRUE;		}		else if (strcmp(argv[i],"--showonly")==0) {			showonly = 1;			warningsarefatal = 0;		}		else if ((strcmp(argv[i],"--auto_reload")==0) && (i+1 < argc)) {			auto_reload = atoi(argv[++i]);			if (!auto_reload) usage(argv[0]);		}		else {			usage(argv[0]);		}	}	starter_use_log (debug, 1, debug ? 0 : 1);	/**	 * Init	 */	signal(SIGHUP,fsig);	signal(SIGCHLD,fsig);	signal(SIGPIPE,fsig);	signal(SIGINT,fsig);	signal(SIGTERM,fsig);	signal(SIGQUIT,fsig);	signal(SIGALRM,fsig);	signal(SIGUSR1,fsig);	/**	 * Verify that we can start	 */	if (!showonly && getuid()!=0) {		starter_log(LOG_LEVEL_ERR, "ERROR: Must be root (uid=0)");		exit(1);	}	if (!showonly && stat(PID_FILE,&stb)==0) {		starter_log(LOG_LEVEL_ERR,			"ERROR: pluto is already running (%s exists) -- aborting", PID_FILE);		exit(1);	}	if (stat(DEV_RANDOM,&stb)!=0) {		starter_log(LOG_LEVEL_ERR, "ERROR: Unable to start Openswan IPsec, no %s!",			DEV_RANDOM);		exit(1);	}	if (stat(DEV_URANDOM,&stb)!=0) {		starter_log(LOG_LEVEL_ERR, "ERROR: Unable to start Openswan IPsec, no %s!",			DEV_URANDOM);		exit(1);	}	cfg = confread_load(configfile, &err);	if (!cfg) {		starter_log(LOG_LEVEL_ERR, "ERROR: Can't load config: %s", err ? err : "unknown error");		if (err) free(err);		exit(1);	}	if (err) free(err);	if(justdump)	{	    confwrite(cfg,stdout);	    exit(0);	}	/* Need to determine which stack to use here, and if() it */	if ((starter_klips_init()!=0) || (starter_klips_set_config(cfg)!=0)) {		exit(1);	}	starter_ifaces_init();	starter_ifaces_clear();	last_reload = time(NULL);	starter_log(LOG_LEVEL_INFO, "Starting Openswan IPsec %s [starter]...",		ipsec_version_code());	/**	 * Fork if we're not debugging stuff	 */	if (!no_fork) {		switch (fork()) {			case 0:				starter_use_log (0, 0, 1);				{					int fnull;					fnull = open("/dev/null", O_RDWR);					if (fnull >= 0) {						dup2(fnull,STDIN_FILENO);						dup2(fnull,STDOUT_FILENO);						dup2(fnull,STDERR_FILENO);						close(fnull);					}				}				break;			case -1:				starter_log(LOG_LEVEL_ERR, "ERROR: Can't fork: %s", strerror(errno));				break;			default:				exit(0);				break;		}	}	/**	 * Save pid file in /var/run/pluto/starter.pid	 */	{		FILE *f = fopen(MY_PID_FILE, "w");		if (f) {			fprintf(f, "%u\n", getpid());			fclose(f);		}	}	starter_ifaces_load (cfg->setup.interfaces, cfg->setup.options[KBF_OVERRIDEMTU],#ifdef NAT_TRAVERSAL		cfg->setup.nat_traversal ? 1 : 0#else		0#endif		);	_action_ = FLAG_ACTION_START_PLUTO;	for (;;) {		/**		 * Stop pluto (if started) and exit		 */		if (_action_ & FLAG_ACTION_QUIT) {			if (starter_pluto_pid()) {				starter_stop_pluto();			}			starter_ifaces_clear();			/* Need to determine which stack here... */			starter_klips_cleanup();			starter_netkey_cleanup();			confread_free(cfg);			starter_log(LOG_LEVEL_DEBUG, "ipsec starter stopped");			unlink(MY_PID_FILE);			exit(0);		}		/**		 * Delete all connections. Will be added below		 */		if (_action_ & FLAG_ACTION_FORCE_RELOAD) {			if (starter_pluto_pid()) {			    for(conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next)			    {				if (conn->state == STATE_ADDED) {				    starter_whack_del_conn(conn);				    conn->state = STATE_TO_ADD;				}			    }			}			_action_ &= ~FLAG_ACTION_FORCE_RELOAD;		}		/**		 * Reload a new config gile		 */		if (_action_ & FLAG_ACTION_RELOAD) {			err = NULL;			starter_log(LOG_LEVEL_INFO, "Reloading config %s...", configfile);			new_cfg = confread_load(configfile, &err);			if (new_cfg) {				/**				 * Switch to new config. New conn will be loaded below				 */				/* Check stacks here too */				if (starter_cmp_klips(cfg, new_cfg)) {					starter_log(LOG_LEVEL_DEBUG, "Klips has changed");					starter_klips_set_config(new_cfg);				}				if (starter_ifaces_load (new_cfg->setup.interfaces,					new_cfg->setup.options[KBF_OVERRIDEMTU],#ifdef NAT_TRAVERSAL					new_cfg->setup.nat_traversal ? 1 : 0#else					0#endif					)) {					_action_ |= FLAG_ACTION_LISTEN;				}				if (starter_cmp_pluto(cfg, new_cfg)) {					starter_log(LOG_LEVEL_DEBUG, "Pluto has changed");					if (starter_pluto_pid()) {						starter_stop_pluto();					}					_action_ &= ~FLAG_ACTION_LISTEN;					_action_ |= FLAG_ACTION_START_PLUTO;				}				else {				    /**				     * Only reload conns if pluto is not killed				     */				    /**				     * Look for new connections that are already loaded				     */				    for(conn = cfg->conns.tqh_first;					conn != NULL;					conn = conn->link.tqe_next)				    {					if (conn->state == STATE_ADDED)					{					    for(conn2 = cfg->conns.tqh_first; conn2 != NULL; conn2 = conn2->link.tqe_next)					    {						if ((conn2->state == STATE_TO_ADD) &&						    (starter_cmp_conn(conn,conn2)==0)) {						    conn->state = STATE_REPLACED;						    conn2->state = STATE_ADDED;						    conn2->id = conn->id;						    break;						}					    }					}				    }				    /**				     * Remove now unused conn				     */				    for(conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next)				    {					if (conn->state == STATE_ADDED)					{					    starter_whack_del_conn(conn);					}				    }				}				confread_free(cfg);				cfg = new_cfg;			}			else {				starter_log(LOG_LEVEL_ERR,					"can't reload config file: %s -- keeping old one", err);			}			if (err) free(err);			_action_ &= ~FLAG_ACTION_RELOAD;			last_reload = time(NULL);		}		/**		 * Start pluto		 */		if (_action_ & FLAG_ACTION_START_PLUTO) {			if (starter_pluto_pid()==0) {				starter_log(LOG_LEVEL_INFO, "Attempting to start pluto...");				/* Again, check stacks here and if() */				starter_klips_clear();				starter_netkey_clear();				if (starter_start_pluto(cfg,debug)==0) {					starter_whack_listen();				}				else {					/** schedule next try **/					alarm(PLUTO_RESTART_DELAY);				}			}			_action_ &= ~FLAG_ACTION_START_PLUTO;  		        for(conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next)			{			    if (conn->state == STATE_ADDED)				conn->state = STATE_TO_ADD;			}		}		/**		 * Tell pluto to reread its interfaces		 */		if (_action_ & FLAG_ACTION_LISTEN) {			starter_whack_listen();			_action_ &= ~FLAG_ACTION_LISTEN;		}		/**		 * Add stale connections		 */		if (starter_pluto_pid()!=0) {		    for(conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next)		    {			switch(conn->desired_state)			{			case STARTUP_NO:			    break;			case STARTUP_POLICY:			    /* mark conn as not negotiable			     * starter_whack_route_conn(conn);			     */			    break;			    			case STARTUP_ADD:			case STARTUP_START:			case STARTUP_ROUTE:			    if (conn->state == STATE_LOADED)			    {				if (conn->id == 0) {				    /**				     * Affect new unique id				     */				    conn->id = id++;				}				starter_whack_add_conn(conn);				conn->state = STATE_ADDED;			    }			    break;			}						if(conn->state == STATE_ADDED)			{			    switch(conn->desired_state)			    {			    case STARTUP_NO:			    case STARTUP_POLICY:			    case STARTUP_ADD:				break;							    case STARTUP_START:				starter_whack_initiate_conn(conn);				break;							    case STARTUP_ROUTE:				starter_whack_route_conn(conn);				break;			    }			    			    conn->state = STATE_UP;			}		    }		}				/**		 * If auto_reload activated, when to stop select		 */		if (auto_reload) {		    time_t now = time(NULL);		    tv.tv_sec = (now<last_reload+auto_reload) ?			(last_reload+auto_reload-now) : 0;		    tv.tv_usec = 0;		}				/**		 * Wait for something to happend		 */		if (select (0, NULL, NULL, NULL, auto_reload ? &tv : NULL) == 0) {		    /**		     * Timeout -> auto_reload		     */		    _action_ |= FLAG_ACTION_RELOAD;		}}	return 0;}/* * Local Variables: * c-basic-offset:4 * c-style: pluto * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -