Exemplo n.º 1
0
int main(int argc, char **argv)
{
#if 0
	NSS_NoDB_Init(".");
	if (!test_aes_cbc(&algo_aes_cbc)) {
		printf("aes-cbc failed\n");
	}
	if (!test_camellia_cbc(&algo_camellia_cbc)) {
		printf("camellia-cbc failed\n");
	}
	if (!test_aes_ctr(&algo_aes_ctr)) {
		printf("aes-ctr failed\n");
	}
	exit(0);
#endif

	int lockfd;

	/*
	 * We read the intentions for how to log from command line options
	 * and the config file. Then we prepare to be able to log, but until
	 * then log to stderr (better then nothing). Once we are ready to
	 * actually do loggin according to the methods desired, we set the
	 * variables for those methods
	 */
	bool log_to_stderr_desired = FALSE;
	bool log_to_file_desired = FALSE;

	{
		int i;

		/* MUST BE BEFORE ANY allocs */
		for (i = 1; i < argc; ++i) {
			if (streq(argv[i], "--leak-detective"))
				leak_detective = TRUE;
		}
	}

	pluto_name = argv[0];

	coredir = clone_str("/var/run/pluto", "coredir in main()");
	pluto_vendorid = clone_str(ipsec_version_vendorid(), "vendorid in main()");

	unsigned int keep_alive = 0;

	/* Overridden by virtual_private= in ipsec.conf */
	char *virtual_private = NULL;

	libreswan_passert_fail = passert_fail;

	/* handle arguments */
	for (;; ) {
		/*
		 * Note: we don't like the way short options get parsed
		 * by getopt_long, so we simply pass an empty string as
		 * the list.  It could be "hvdenp:l:s:" "NARXPECK".
		 */
		int longindex = -1;
		int c = getopt_long(argc, argv, "", long_opts, &longindex);
		const char *optname = NULL;
		err_t ugh = NULL;	/* complaint from case */
		unsigned long u = 0;	/* scratch for case */

		if (longindex != -1) {
			const char *optmeta;
			optname = long_opts[longindex].name;

			optmeta = optname + strlen(optname) + 1;	/* after '\0' */
			switch (optmeta[0]) {
			case '_':
				libreswan_log("warning: option \"--%s\" with '_' in its name is obsolete; use '-'",
					optname);
				break;
			case '>':
				libreswan_log("warning: option \"--%s\" is obsolete; use \"--%s\"",
					optname, optmeta + 1);
				break;
			case '!':
				libreswan_log("warning: option \"--%s\" is obsolete; ignored",
					optname);
				continue;	/* ignore it! */
			}
		}

		/* Note: "breaking" from case terminates loop */
		switch (c) {
		case EOF:	/* end of flags */
			break;

		case 0:
			/*
			 * Long option already handled by getopt_long.
			 * Not currently used since we always set flag to NULL.
			 */
			continue;

		case ':':	/* diagnostic already printed by getopt_long */
		case '?':	/* diagnostic already printed by getopt_long */
			invocation_fail(NULL);
			break;

		case 'h':	/* --help */
			usage();
			break;	/* not actually reached */

		case 'X':	/* --leak-detective */
			/*
			 * This flag was already processed at the start of main()
			 * because leak_detective must be immutable from before
			 * the first alloc().
			 * If this option is specified, we must have already
			 * set it at the start of main(), so assert it.
			 */
			passert(leak_detective);
			continue;

		case 'C':	/* --coredir */
			pfree(coredir);
			coredir = clone_str(optarg, "coredir via getopt");
			continue;

		case 'V':	/* --vendorid */
			pfree(pluto_vendorid);
			coredir = clone_str(optarg, "pluto_vendorid via getopt");
			continue;

		case 'S':	/* --statsdir */
			pfreeany(pluto_stats_binary);
			pluto_stats_binary = clone_str(optarg, "statsbin");
			continue;

		case 'v':	/* --version */
			printf("%s%s\n", ipsec_version_string(),
				compile_time_interop_options);
			/* not exit_pluto because we are not initialized yet */
			exit(0);
			break;	/* not actually reached */

		case 'j':	/* --nhelpers */
			if (streq(optarg, "-1")) {
				nhelpers = -1;
			} else {
				ugh = ttoulb(optarg, 0, 10, 1000, &u);
				if (ugh != NULL)
					break;

				nhelpers = u;
			}
			continue;
		case 'c':	/* --seedbits */
			pluto_nss_seedbits = atoi(optarg);
			if (pluto_nss_seedbits == 0) {
				printf("pluto: seedbits must be an integer > 0");
				/* not exit_pluto because we are not initialized yet */
				exit(PLUTO_EXIT_NSS_FAIL);
			}
			continue;

#ifdef HAVE_LABELED_IPSEC
		case 'w':	/* --secctx-attr-type */
			ugh = ttoulb(optarg, 0, 0, 0xFFFF, &u);
			if (ugh != NULL)
				break;
			if (u != SECCTX && u != ECN_TUNNEL_or_old_SECCTX) {
				ugh = "must be a positive 32001 (default) or 10 (for backward compatibility)";
				break;
			}
			secctx_attr_type = u;
			continue;
#endif

		case 'd':	/* --nofork*/
			fork_desired = FALSE;
			continue;

		case 'e':	/* --stderrlog */
			log_to_stderr_desired = TRUE;
			continue;

		case 'g':	/* --logfile */
			pluto_log_file = optarg;
			log_to_file_desired = TRUE;
			continue;

		case 't':	/* --log-no-time */
			log_with_timestamp = FALSE;
			continue;

		case '7':	/* --log-no-append */
			log_append = FALSE;
			continue;

		case '8':	/* --drop-oppo-null */
			pluto_drop_oppo_null = TRUE;
			continue;

		case '9':	/* --expire-bare-shunt <interval> */
			ugh = ttoulb(optarg, 0, 10, 1000, &u);
			if (ugh != NULL)
				break;
			bare_shunt_interval = u;
			continue;

		case 'k':	/* --use-klips */
			kern_interface = USE_KLIPS;
			continue;

		case 'L':	/* --listen ip_addr */
		{
			ip_address lip;
			err_t e = ttoaddr(optarg, 0, AF_UNSPEC, &lip);

			if (e != NULL) {
				/*
				 *??? should we continue on failure?
				 * If not, use ugh mechanism.
				 */
				libreswan_log(
					"invalid listen argument ignored: %s\n",
					e);
			} else {
				pluto_listen =
					clone_str(optarg, "pluto_listen");
				libreswan_log(
					"bind() will be filtered for %s\n",
					pluto_listen);
			}
		}
			continue;

		case 'M':	/* --use-mast */
			kern_interface = USE_MASTKLIPS;
			continue;

		case 'F':	/* --use-bsdkame */
			kern_interface = USE_BSDKAME;
			continue;

		case 'K':	/* --use-netkey */
			kern_interface = USE_NETKEY;
			continue;

		case 'n':	/* --use-nostack */
			kern_interface = NO_KERNEL;
			continue;

		case 'D':	/* --force-busy */
			pluto_ddos_mode = DDOS_FORCE_BUSY;
			continue;
		case 'U':	/* --force-unlimited */
			pluto_ddos_mode = DDOS_FORCE_UNLIMITED;
			continue;

		case 'Z':	/* --curl-iface */
			curl_iface = optarg;
			continue;

		case 'I':	/* --curl-timeout */
			ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u);
			if (ugh != NULL)
				break;
			if (u <= 0) {
				ugh = "must not be < 1";
				break;
			}
			curl_timeout = u;
			continue;

		case 'r':	/* --strictcrlpolicy */
			strict_crl_policy = TRUE;
			continue;

		case 'o':
			strict_ocsp_policy = TRUE;
			continue;

		case 'O':
			ocsp_enable = TRUE;
			continue;

		case 'Y':
			ocsp_default_uri = optarg;
			continue;

		case 'J':
			ocsp_trust_name = optarg;
			continue;

		case 'T':	/* --ocsp_timeout <seconds> */
			ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u);
			if (ugh != NULL)
				break;
			if (u == 0) {
				ugh = "must not be 0";
				break;
			}
			ocsp_timeout = u;
			continue;

		case 'x':	/* --crlcheckinterval <seconds> */
			ugh = ttoulb(optarg, 0, 10, TIME_T_MAX, &u);
			if (ugh != NULL)
				break;
			crl_check_interval = deltatime(u);
			continue;

		case 'u':	/* --uniqueids */
			uniqueIDs = TRUE;
			continue;

		case 'i':	/* --interface <ifname|ifaddr> */
			if (!use_interface(optarg)) {
				ugh = "too many --interface specifications";
				break;
			}
			continue;

		/*
		 * This option does not really work, as this is the "left"
		 * site only, you also need --to --ikeport again later on
		 * It will result in: yourport -> 500, still not bypassing
		 * filters
		 */
		case 'p':	/* --ikeport <portnumber> */
			ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u);
			if (ugh != NULL)
				break;
			if (u == 0) {
				ugh = "must not be 0";
				break;
			}
			pluto_port = u;
			continue;

		case 'q':	/* --natikeport <portnumber> */
			ugh = ttoulb(optarg, 0, 10, 0xFFFF, &u);
			if (ugh != NULL)
				break;
			if (u == 0) {
				ugh = "must not be 0";
				break;
			}
			pluto_nat_port = u;
			continue;

		case 'b':	/* --ctlbase <path> */
			/*
			 * ??? work to be done here:
			 *
			 * snprintf returns the required space if there
			 * isn't enough, not -1.
			 * -1 indicates another kind of error.
			 *
			 * This appears to be the only place where the
			 * ctlbase value is used yet it is set elsewhere.
			 * (This isn't clear -- it may be OK.)
			 */
			ctlbase = optarg;
			if (snprintf(ctl_addr.sun_path,
					sizeof(ctl_addr.sun_path),
					"%s%s", ctlbase, CTL_SUFFIX) == -1) {
				ugh = "<path>" CTL_SUFFIX " too long for sun_path";
				break;
			}

			if (snprintf(info_addr.sun_path,
					sizeof(info_addr.sun_path),
					"%s%s", ctlbase, INFO_SUFFIX) == -1) {
				ugh = "<path>" INFO_SUFFIX " too long for sun_path";
				break;
			}

			if (snprintf(pluto_lock, sizeof(pluto_lock),
					"%s%s", ctlbase, LOCK_SUFFIX) == -1) {
				ugh = "<path>" LOCK_SUFFIX " must fit";
				break;
			}
			continue;

		case 's':	/* --secretsfile <secrets-file> */
			lsw_conf_secretsfile(optarg);
			continue;

		case 'f':	/* --ipsecdir <ipsec-dir> */
			lsw_init_ipsecdir(optarg);
			continue;

		case 'N':	/* --debug-none */
			base_debugging = DBG_NONE;
			continue;

		case 'A':	/* --debug-all */
			base_debugging = DBG_ALL;
			continue;

		case 'P':	/* --perpeerlogbase */
			base_perpeer_logdir = optarg;
			continue;

		case 'l':	/* --perpeerlog */
			log_to_perpeer = TRUE;
			continue;

		case '2':	/* --keep-alive <delay_secs> */
			ugh = ttoulb(optarg, 0, 10, secs_per_day, &u);
			if (ugh != NULL)
				break;
			keep_alive = u;
			continue;

		case '5':	/* --debug-nat-t */
			base_debugging |= DBG_NATT;
			continue;
		case '6':	/* --virtual-private */
			virtual_private = optarg;
			continue;

		case 'z':	/* --config */
		{
			/*
			 * Config struct to variables mapper. This will
			 * overwrite all previously set options. Keep this
			 * in the same order as long_opts[] is.
			 */
			struct starter_config *cfg = read_cfg_file(optarg);

			/* leak */
			set_cfg_string(&pluto_log_file,
				cfg->setup.strings[KSF_PLUTOSTDERRLOG]);
			if (pluto_log_file != NULL)
				log_to_syslog = FALSE;
			/* plutofork= no longer supported via config file */
			log_with_timestamp =
				cfg->setup.options[KBF_PLUTOSTDERRLOGTIME];
			log_append = cfg->setup.options[KBF_PLUTOSTDERRLOGAPPEND];
			pluto_drop_oppo_null = cfg->setup.options[KBF_DROP_OPPO_NULL];
			pluto_ddos_mode = cfg->setup.options[KBF_DDOS_MODE];
			if (cfg->setup.options[KBF_FORCEBUSY]) {
				/* force-busy is obsoleted, translate to ddos-mode= */
				pluto_ddos_mode = cfg->setup.options[KBF_DDOS_MODE] = DDOS_FORCE_BUSY;
			}
			/* ddos-ike-threshold and max-halfopen-ike */
			pluto_ddos_threshold = cfg->setup.options[KBF_DDOS_IKE_THRESHOLD];
			pluto_max_halfopen = cfg->setup.options[KBF_MAX_HALFOPEN_IKE];

			strict_crl_policy =
				cfg->setup.options[KBF_STRICTCRLPOLICY];

			pluto_shunt_lifetime = deltatime(cfg->setup.options[KBF_SHUNTLIFETIME]);

			strict_ocsp_policy =
				cfg->setup.options[KBF_STRICTOCSPPOLICY];

			ocsp_enable = cfg->setup.options[KBF_OCSPENABLE];

			set_cfg_string(&ocsp_default_uri,
				       cfg->setup.strings[KSF_OCSPURI]);

			ocsp_timeout = cfg->setup.options[KBF_OCSPTIMEOUT];

			set_cfg_string(&ocsp_trust_name,
				       cfg->setup.strings[KSF_OCSPTRUSTNAME]);

			crl_check_interval = deltatime(
				cfg->setup.options[KBF_CRLCHECKINTERVAL]);
			uniqueIDs = cfg->setup.options[KBF_UNIQUEIDS];
			/*
			 * We don't check interfaces= here because that part
			 * has been dealt with in _stackmanager before we
			 * started
			 */
			set_cfg_string(&pluto_listen,
				cfg->setup.strings[KSF_LISTEN]);

			/* --ikeport */
			pluto_port = cfg->setup.options[KBF_IKEPORT];

			/* --nflog-all */
			/* only causes nflog nmber to show in ipsec status */
			pluto_nflog_group = cfg->setup.options[KBF_NFLOG_ALL];

			/* only causes nflog nmber to show in ipsec status */
			pluto_xfrmlifetime = cfg->setup.options[KBF_XFRMLIFETIME];

			/* no config option: ctlbase */
			/* --secrets */
			if (cfg->setup.strings[KSF_SECRETSFILE] &&
			    *cfg->setup.strings[KSF_SECRETSFILE]) {
				lsw_conf_secretsfile(cfg->setup.strings[KSF_SECRETSFILE]);
			}
			if (cfg->setup.strings[KSF_IPSECDIR] != NULL &&
				*cfg->setup.strings[KSF_IPSECDIR] != 0) {
				/* --ipsecdir */
				lsw_init_ipsecdir(cfg->setup.strings[KSF_IPSECDIR]);
			}

			/* --perpeerlog */
			log_to_perpeer = cfg->setup.options[KBF_PERPEERLOG];
			if (log_to_perpeer) {
				/* --perpeerlogbase */
				if (cfg->setup.strings[KSF_PERPEERDIR]) {
					set_cfg_string(&base_perpeer_logdir,
						cfg->setup.strings[KSF_PERPEERDIR]);
				} else {
					base_perpeer_logdir = clone_str("/var/log/pluto/", "perpeer_logdir");
				}
			}

			if (cfg->setup.strings[KSF_CURLIFACE]) {
				pfreeany(curl_iface);
				/* curl-iface= */
				curl_iface = clone_str(cfg->setup.strings[KSF_CURLIFACE],
						"curl-iface= via --config");
			}

			if (cfg->setup.options[KBF_CURLTIMEOUT])
				curl_timeout = cfg->setup.options[KBF_CURLTIMEOUT];

			if (cfg->setup.strings[KSF_DUMPDIR]) {
				pfree(coredir);
				/* dumpdir= */
				coredir = clone_str(cfg->setup.strings[KSF_DUMPDIR],
						"coredir via --config");
			}
			/* --vendorid */
			if (cfg->setup.strings[KSF_MYVENDORID]) {
				pfree(pluto_vendorid);
				pluto_vendorid = clone_str(cfg->setup.strings[KSF_MYVENDORID],
						"pluto_vendorid via --config");
			}

			/* no config option: pluto_adns_option */

			if (cfg->setup.strings[KSF_STATSBINARY] != NULL) {
				if (access(cfg->setup.strings[KSF_STATSBINARY], X_OK) == 0) {
					pfreeany(pluto_stats_binary);
					/* statsbin= */
					pluto_stats_binary = clone_str(cfg->setup.strings[KSF_STATSBINARY], "statsbin via --config");
					libreswan_log("statsbinary set to %s", pluto_stats_binary);
				} else {
					libreswan_log("statsbinary= '%s' ignored - file does not exist or is not executable",
						pluto_stats_binary);
				}
			}

			pluto_nss_seedbits = cfg->setup.options[KBF_SEEDBITS];
			pluto_nat_port =
				cfg->setup.options[KBF_NATIKEPORT];
			keep_alive = cfg->setup.options[KBF_KEEPALIVE];

			set_cfg_string(&virtual_private,
				cfg->setup.strings[KSF_VIRTUALPRIVATE]);

			nhelpers = cfg->setup.options[KBF_NHELPERS];
#ifdef HAVE_LABELED_IPSEC
			secctx_attr_type = cfg->setup.options[KBF_SECCTX];
#endif
			base_debugging = cfg->setup.options[KBF_PLUTODEBUG];

			char *protostack = cfg->setup.strings[KSF_PROTOSTACK];

			if (protostack == NULL || *protostack == '\0') {
				kern_interface = USE_NETKEY;
			} else if (streq(protostack, "none")) {
				kern_interface = NO_KERNEL;
			} else if (streq(protostack, "auto")) {
				libreswan_log(
					"The option protostack=auto is obsoleted, falling back to protostack=netkey\n");
				kern_interface = USE_NETKEY;
			} else if (streq(protostack, "klips")) {
				kern_interface = USE_KLIPS;
			} else if (streq(protostack, "mast")) {
				kern_interface = USE_MASTKLIPS;
			} else if (streq(protostack, "netkey") ||
				streq(protostack, "native")) {
				kern_interface = USE_NETKEY;
			} else if (streq(protostack, "bsd") ||
				streq(protostack, "kame") ||
				streq(protostack, "bsdkame")) {
				kern_interface = USE_BSDKAME;
			} else if (streq(protostack, "win2k")) {
				kern_interface = USE_WIN2K;
			}

			confread_free(cfg);
			continue;
		}

		default:
			if (DBG_OFFSET <= c &&
			    c < DBG_OFFSET + IMPAIR_roof_IX) {
				base_debugging |= LELEM(c - DBG_OFFSET);
				continue;
			}
			bad_case(c);
		}
		/* if ugh is set, bail with diagnostic */
		if (ugh != NULL) {
			char mess[200];

			if (longindex == -1) {
				snprintf(mess, sizeof(mess), "unknown option: %s",
					ugh);
			} else if (optarg == NULL) {
				snprintf(mess, sizeof(mess), "--%s option: %s",
					optname, ugh);
			} else {
				snprintf(mess, sizeof(mess), "--%s \"%s\" option: %s",
					optname, optarg, ugh);
			}
			invocation_fail(mess);
		}
		break;
	}
	if (optind != argc)
		invocation_fail("unexpected argument");
	reset_debugging();

	if (chdir(coredir) == -1) {
		int e = errno;

		libreswan_log("pluto: warning: chdir(\"%s\") to dumpdir failed (%d: %s)",
			coredir, e, strerror(e));
	}

	oco = lsw_init_options();
	lockfd = create_lock();

	/* select between logging methods */

	if (log_to_stderr_desired || log_to_file_desired)
		log_to_syslog = FALSE;
	if (!log_to_stderr_desired)
		log_to_stderr = FALSE;

#if 0
	if (kernel_ops->set_debug != NULL)
		(*kernel_ops->set_debug)(cur_debugging, DBG_log, DBG_log);

#endif

	/*
	 * create control socket.
	 * We must create it before the parent process returns so that
	 * there will be no race condition in using it.  The easiest
	 * place to do this is before the daemon fork.
	 */
	{
		err_t ugh = init_ctl_socket();

		if (ugh != NULL) {
			fprintf(stderr, "pluto: FATAL: %s", ugh);
			exit_pluto(PLUTO_EXIT_SOCKET_FAIL);
		}
	}

	/* If not suppressed, do daemon fork */
	if (fork_desired) {
#if USE_DAEMON
		if (daemon(TRUE, TRUE) < 0) {
			fprintf(stderr, "pluto: FATAL: daemon failed (%d %s)\n",
				errno, strerror(errno));
			exit_pluto(PLUTO_EXIT_FORK_FAIL);
		}
		/*
		 * Parent just exits, so need to fill in our own PID
		 * file.  This is racy, since the file won't be
		 * created until after the parent has exited.
		 *
		 * Since "ipsec start" invokes pluto with --nofork, it
		 * is probably safer to leave this feature disabled
		 * then implement it using the daemon call.
		 */
		(void) fill_lock(lockfd, getpid());
#elif USE_FORK
		{
			pid_t pid = fork();

			if (pid < 0) {
				int e = errno;

				fprintf(stderr, "pluto: FATAL: fork failed (%d %s)\n",
					errno, strerror(e));
				exit_pluto(PLUTO_EXIT_FORK_FAIL);
			}

			if (pid != 0) {
				/*
				 * parent: die, after filling PID into lock
				 * file.
				 * must not use exit_pluto: lock would be
				 * removed!
				 */
				exit(fill_lock(lockfd, pid) ? 0 : 1);
			}
		}
#else
		fprintf(stderr, "pluto: FATAL: fork/daemon not supported\n");
		exit_pluto(PLUTO_EXIT_FORK_FAIL);		
#endif
		if (setsid() < 0) {
			int e = errno;

			fprintf(stderr,
				"FATAL: setsid() failed in main(). Errno %d: %s\n",
				errno, strerror(e));
			exit_pluto(PLUTO_EXIT_FAIL);
		}
	} else {
		/* no daemon fork: we have to fill in lock file */
		(void) fill_lock(lockfd, getpid());
		if (isatty(fileno(stdout))) {
			fprintf(stdout, "Pluto initialized\n");
			fflush(stdout);
		}
	}

	/*
	 * Close everything but ctl_fd and (if needed) stderr.
	 * There is some danger that a library that we don't know
	 * about is using some fd that we don't know about.
	 * I guess we'll soon find out.
	 */
	{
		int i;

		for (i = getdtablesize() - 1; i >= 0; i--)	/* Bad hack */
			if ((!log_to_stderr || i != 2) &&
				i != ctl_fd)
				close(i);

		/* make sure that stdin, stdout, stderr are reserved */
		if (open("/dev/null", O_RDONLY) != 0)
			lsw_abort();
		if (dup2(0, 1) != 1)
			lsw_abort();
		if (!log_to_stderr && dup2(0, 2) != 2)

			lsw_abort();
	}

	init_constants();
	init_pluto_constants();

	pluto_init_log();

	if (!pluto_init_nss(oco->nssdb)) {
		loglog(RC_LOG_SERIOUS, "FATAL: NSS initialization failure");
		exit_pluto(PLUTO_EXIT_NSS_FAIL);
	}
	libreswan_log("NSS crypto library initialized");

	if (ocsp_enable) {
		if (!init_nss_ocsp(ocsp_default_uri, ocsp_trust_name,
						     ocsp_timeout,
						     strict_ocsp_policy)) {
			loglog(RC_LOG_SERIOUS, "Initializing NSS OCSP failed");
			exit_pluto(PLUTO_EXIT_NSS_FAIL);
		} else {
			libreswan_log("NSS OCSP Enabled");
		}
	}

#ifdef HAVE_LIBCAP_NG
	/*
	 * Drop capabilities - this generates a false positive valgrind warning
	 * See: http://marc.info/?l=linux-security-module&m=125895232029657
	 *
	 * We drop these after creating the pluto socket or else we can't
	 * create a socket if the parent dir is non-root (eg openstack)
	 */
	capng_clear(CAPNG_SELECT_BOTH);

	capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED,
		CAP_NET_BIND_SERVICE, CAP_NET_ADMIN, CAP_NET_RAW,
		CAP_IPC_LOCK, CAP_AUDIT_WRITE,
		/* for google authenticator pam */
		CAP_SETGID, CAP_SETUID,
		CAP_DAC_READ_SEARCH,
		-1);
	/*
	 * We need to retain some capabilities for our children (updown):
	 * CAP_NET_ADMIN to change routes
	 * CAP_NET_RAW for iptables -t mangle
	 * CAP_DAC_READ_SEARCH for pam / google authenticator
	 */
	capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, CAP_NET_RAW,
			CAP_DAC_READ_SEARCH, -1);
	capng_apply(CAPNG_SELECT_BOTH);
	libreswan_log("libcap-ng support [enabled]");
#else
	libreswan_log("libcap-ng support [disabled]");
#endif

#ifdef FIPS_CHECK
	libreswan_log("FIPS HMAC integrity support [enabled]");
	/*
	 * FIPS mode requires two conditions to be true:
	 *  - FIPS Kernel mode: fips=1 kernel boot parameter
	 *  - FIPS Product mode: See FIPSPRODUCTCHECK in Makefile.inc
	 *     (in RHEL/Fedora, dracut-fips installs $FIPSPRODUCTCHECK)
	 *
	 * When FIPS mode, abort on self-check hmac failure. Otherwise, complain
	 */
	{
		if (DBGP(IMPAIR_FORCE_FIPS)) {
			libreswan_log("Forcing FIPS checks to true to emulate FIPS mode");
			lsw_set_fips_mode(LSW_FIPS_ON);
		}

		enum lsw_fips_mode pluto_fips_mode = lsw_get_fips_mode();
		bool nss_fips_mode = PK11_IsFIPS();

		/*
		 * Now verify the consequences.  Always run the tests
		 * as combinations such as NSS in fips mode but as out
		 * of it could be bad.
		 */
		switch (pluto_fips_mode) {
		case LSW_FIPS_UNKNOWN:
			loglog(RC_LOG_SERIOUS, "ABORT: pluto FIPS mode could not be determined");
			exit_pluto(PLUTO_EXIT_FIPS_FAIL);
			break;
		case LSW_FIPS_ON:
			libreswan_log("FIPS mode enabled for pluto daemon");
			if (nss_fips_mode) {
				libreswan_log("NSS library is running in FIPS mode");
			} else {
				loglog(RC_LOG_SERIOUS, "ABORT: pluto in FIPS mode but NSS library is not");
				exit_pluto(PLUTO_EXIT_FIPS_FAIL);
			}
			break;
		case LSW_FIPS_OFF:
			libreswan_log("FIPS mode disabled for pluto daemon");
			if (nss_fips_mode) {
				loglog(RC_LOG_SERIOUS, "Warning: NSS library is running in FIPS mode");
			}
			break;
		case LSW_FIPS_UNSET:
		default:
			bad_case(pluto_fips_mode);
		}

		/* always run hmac check so we can print diagnostic */
		bool fips_files = FIPSCHECK_verify_files(fips_package_files);

		if (fips_files) {
			libreswan_log("FIPS HMAC integrity verification self-test passed");
		} else {
			loglog(RC_LOG_SERIOUS, "FIPS HMAC integrity verification self-test FAILED");
		}
		if (pluto_fips_mode == LSW_FIPS_ON && !fips_files) {
			exit_pluto(PLUTO_EXIT_FIPS_FAIL);
		}
	}
#else
	libreswan_log("FIPS HMAC integrity support [disabled]");
#endif

#ifdef USE_LINUX_AUDIT
	linux_audit_init();
#else
	libreswan_log("Linux audit support [disabled]");
#endif

	{
		const char *vc = ipsec_version_code();
		libreswan_log("Starting Pluto (Libreswan Version %s%s) pid:%u",
			vc, compile_time_interop_options, getpid());
	}

	libreswan_log("core dump dir: %s", coredir);
	if (oco->secretsfile && *oco->secretsfile)
		libreswan_log("secrets file: %s", oco->secretsfile);

	libreswan_log(leak_detective ?
		"leak-detective enabled" : "leak-detective disabled");

	/* Check for SAREF support */
#ifdef KLIPS_MAST
#include <ipsec_saref.h>
	{
		int e, sk, saref;
		saref = 1;
		errno = 0;

		sk = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
		e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_REFINFO, &saref,
			sizeof(saref));
		if (e == -1 )
			libreswan_log("SAref support [disabled]: %s",
				strerror(errno));
		else
			libreswan_log("SAref support [enabled]");
		errno = 0;
		e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_BINDREF, &saref,
			sizeof(saref));
		if (e == -1 )
			libreswan_log("SAbind support [disabled]: %s",
				strerror(errno));
		else
			libreswan_log("SAbind support [enabled]");

		close(sk);
	}
#endif

	libreswan_log("NSS crypto [enabled]");

#ifdef XAUTH_HAVE_PAM
	libreswan_log("XAUTH PAM support [enabled]");
#else
	libreswan_log("XAUTH PAM support [disabled]");
#endif

/* Log various impair-* functions if they were enabled */

	if (DBGP(IMPAIR_BUST_MI2))
		libreswan_log("Warning: IMPAIR_BUST_MI2 enabled");
	if (DBGP(IMPAIR_BUST_MR2))
		libreswan_log("Warning: IMPAIR_BUST_MR2 enabled");
	if (DBGP(IMPAIR_SA_CREATION))
		libreswan_log("Warning: IMPAIR_SA_CREATION enabled");
	if (DBGP(IMPAIR_JACOB_TWO_TWO))
		libreswan_log("Warning: IMPAIR_JACOB_TWO_TWO enabled");
	if (DBGP(IMPAIR_DIE_ONINFO))
		libreswan_log("Warning: IMPAIR_DIE_ONINFO enabled");
	if (DBGP(IMPAIR_MAJOR_VERSION_BUMP))
		libreswan_log("Warning: IMPAIR_MAJOR_VERSION_BUMP enabled");
	if (DBGP(IMPAIR_MINOR_VERSION_BUMP))
		libreswan_log("Warning: IMPAIR_MINOR_VERSION_BUMP enabled");
	if (DBGP(IMPAIR_RETRANSMITS))
		libreswan_log("Warning: IMPAIR_RETRANSMITS enabled");
	if (DBGP(IMPAIR_SEND_BOGUS_ISAKMP_FLAG))
		libreswan_log("Warning: IMPAIR_SEND_BOGUS_ISAKMP_FLAG enabled");
	if (DBGP(IMPAIR_SEND_BOGUS_PAYLOAD_FLAG))
		libreswan_log("Warning: IMPAIR_SEND_BOGUS_PAYLOAD_FLAG enabled");
	if (DBGP(IMPAIR_SEND_IKEv2_KE))
		libreswan_log("Warning: IMPAIR_SEND_IKEv2_KE enabled");
	if (DBGP(IMPAIR_SEND_KEY_SIZE_CHECK))
		libreswan_log("Warning: IMPAIR_SEND_KEY_SIZE_CHECK enabled");
	if (DBGP(IMPAIR_SEND_NO_DELETE))
		libreswan_log("Warning: IMPAIR_SEND_NO_DELETE enabled");
	if (DBGP(IMPAIR_FORCE_FIPS))
		libreswan_log("Warning: IMPAIR_FORCE_FIPS enabled");
	if (DBGP(IMPAIR_SEND_NO_IKEV2_AUTH))
		libreswan_log("Warning: IMPAIR_SEND_NO_IKEV2_AUTH enabled");
	if (DBGP(IMPAIR_SEND_ZERO_GX))
		libreswan_log("Warning: IMPAIR_SEND_ZERO_GX enabled");
	if (DBGP(IMPAIR_SEND_BOGUS_DCOOKIE))
		libreswan_log("Warning: IMPAIR_SEND_BOGUS_DCOOKIE enabled");

/* Initialize all of the various features */

	init_nat_traversal(keep_alive);

	init_virtual_ip(virtual_private);
	/* obsoleted by nss code init_rnd_pool(); */
	init_event_base();
	init_secret();
	init_states();
	init_connections();
	init_crypto();
	init_crypto_helpers(nhelpers);
	init_demux();
	init_kernel();
	init_id();
	init_vendorid();
#if defined(LIBCURL) || defined(LDAP_VER)
	init_fetch();
#endif
	load_crls();
#ifdef HAVE_LABELED_IPSEC
	init_avc();
#endif
	daily_log_event();
#ifdef USE_SYSTEMD_WATCHDOG
	pluto_sd_init();
#endif

	call_server();
	return -1;	/* Shouldn't ever reach this */
}
Exemplo n.º 2
0
int main(int argc, char **argv)
{
	int lockfd;
    bool restore_vrf_pluto = 0;
	
	/*此开关必须放在所有动态内存分配之前*/
	leak_detective=0;
	
	debug_info_control* dic=alloc_bytes(sizeof(debug_info_control), "malloc debug_info_control in main");

	openswan_passert_fail = passert_fail;

	/*设备类型初始化*/
	ipsec_device_type_init();
	{
		u32 pseudo_start_pluto = 0;

		for (;;)
		{
#define DBG_OFFSET 256
			static const struct option long_opts[] = {
				/* name, has_arg, flag, val */
				{ "help", no_argument, NULL, 'h' },
				{ "version", no_argument, NULL, 'v' },
				{ "start", no_argument, NULL, 'B' },
                { "quit", no_argument, NULL, 'D' },    
				{ "user", no_argument, NULL, 'u' },
				{ "krl", no_argument, NULL, 'K' },
				{ "debug-nat", no_argument, NULL, '5' },
				{ "debug-none", no_argument, NULL, 'N' },
				{ "debug-all", no_argument, NULL, 'A' },
				{ "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET },	
				{ "debug-crypto", no_argument, NULL, DBG_CRYPT + DBG_OFFSET },
				{ "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET },
				{ "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET },
				{ "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET },
				{ "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET },
				{ "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET },
				{ "debug-netkey", no_argument, NULL, DBG_NETKEY + DBG_OFFSET },
				{ "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET },
				{ "debug-oppoinfo", no_argument, NULL, DBG_OPPOINFO + DBG_OFFSET },
				{ "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET },
				{ "debug-dpd", no_argument, NULL, DBG_DPD + DBG_OFFSET },
				{ "debug-xauth", no_argument, NULL, DBG_XAUTH+ DBG_OFFSET },
				{ "debug-x509", no_argument, NULL, DBG_X509 + DBG_OFFSET },
				{ "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET },
				{ "debug-pfkey", no_argument, NULL, DBG_PFKEY + DBG_OFFSET },
                { "debug-ifchange", no_argument, NULL, DBG_IF_CHANGE + DBG_OFFSET },
                
				{ "log-openinfo", no_argument, NULL, 'i' },
				{ "log-openwar", no_argument, NULL, 'w' },
				{ "log-openerr", no_argument, NULL, 'r' },
				{ "log-openuserlog", no_argument, NULL, 'e' },				
				{ "log-openradiuslog", no_argument, NULL, 'c' },
				{ "log-openpri", no_argument, NULL, 'p' },
				{ "log-opensyserr", no_argument, NULL, 'q' },
				{ "log-closeall", no_argument, NULL, 'a' },

				{ "debug-connection", required_argument, NULL, 'O' },
				{ "debug-host", required_argument, NULL, 'H' },
				{ "debug-stop", no_argument, NULL, 'S' },
				{ "counter", no_argument, NULL, 'b' },				
				{ "isa-counter", no_argument, NULL, 'x' },

				{ "krc", no_argument, NULL, 'E'},
				{ "kss", required_argument, NULL, 'F'},
				{ "kpc", no_argument, NULL, 'G'},
				{ "kprt", required_argument, NULL, 'L'},
				{ "kspi", required_argument, NULL, 'M' },
				{ "kdst", required_argument, NULL, 'P' },
				{ "kdnet", required_argument, NULL, 'R' },
				{ "kid",  required_argument, NULL, 'Q' },
				{ "restore-vrf", no_argument, NULL, 'V' },	
				{ 0,0,0,0 }
			};

			int c = getopt_long(argc, argv, "", long_opts, NULL);
			ip_address dst_tmp;
			ip_subnet subnet_tmp;

			switch (c)
			{
				case EOF:	/* end of flags */
					break;

				case 0: /* long option already handled */
					continue;

				case ':':	/* diagnostic already printed by getopt_long */
				case '?':	/* diagnostic already printed by getopt_long */
					usage("");
					break;   

				case 'h':	
					usage(NULL);
					break;	

				case 'v':	
				{
					const char **sp = ipsec_copyright_notice();

					printf("%s%s\n", ipsec_version_string(),compile_time_interop_options);
					for (; *sp != NULL; sp++)
					{
						puts(*sp);
					}
				}
					exit(0);	
					break;	

				case 'i':
					dic->public_info.log_falg = 1;
					dic->public_info.log_level_info |= IPSEC_LOGLEVEL_INFO;
					continue;

				case 'w':
					dic->public_info.log_falg = 1;
					dic->public_info.log_level_info |= IPSEC_LOGLEVEL_WARNING;
					continue;

				case 'r':
					dic->public_info.log_falg = 1;
					dic->public_info.log_level_info |= IPSEC_LOGLEVEL_ERROR;
					continue;

				case 'e':
					dic->public_info.log_falg = 1;
					dic->public_info.log_level_info |= IPSEC_LOGLEVEL_USER_LOG;
					continue;
					
				case 'c':
					dic->public_info.log_falg = 1;
					dic->public_info.log_level_info |= IPSEC_LOGLEVEL_RADIUS_LOG;
					continue;
					
				case 'p':
					dic->public_info.log_falg = 1;
					dic->public_info.log_level_info |= IPSEC_LOGLEVEL_PRIVATE;
					continue;
					
				case 'q':
					dic->public_info.log_falg = 1;
					dic->public_info.log_level_info |= IPSEC_LOGLEVEL_SYSERROR;
					continue;

				case 'a':
					dic->public_info.log_falg = 1;
					dic->public_info.log_level_info=IPSEC_LOGLEVEL_CLOSE;
					continue;
                    
				case 'B': 				    
					dic->com_type=IPSEC_DEBUG_STAR_HANDLE;
					continue;                   

                case 'D':
                    dic->com_type=IPSEC_DEBUG_QUIT_HANDLE;
					continue;

				case 'u':                    
					dic->com_type=IPSEC_DEBUG_USER_HANDLE;
					continue;

				case 'K':	
					dic->com_type=IPSEC_DEBUG_KERNEL_HANDLE;
					continue;

				case 'N':	/* --debug-none */
					dic->public_info.public_info_flag=1;
					dic->public_info.public_info_value=DBG_NONE;
					continue;

				case 'A':	/* --debug-all */
					dic->public_info.public_info_flag=1;
					dic->public_info.public_info_value=DBG_ALL;
					continue;

				case 'O':
					if(optarg != NULL)
					{
						strcpy(dic->child_info.child_info_optarg,optarg);
						dic->child_info.child_info_type=IPSEC_CHILD_DEBUG_INFO_CON_NAME;
					}
					else
					{
						return 0;
					}
					break;

				case 'H':
					if(optarg != NULL)
					{
						strcpy(dic->child_info.child_info_optarg,optarg);
						dic->child_info.child_info_type=IPSEC_CHILD_DEBUG_INFO_HOST;
					}
					else
					{
						return 0;
					}
					break;

				case 'S':
					dic->child_info.child_info_type=IPSEC_CHILD_DEBUG_INFO_STOP;
					break;
				case 'b':
					dic->child_info.child_info_type=IPSEC_CHILD_DEBUG_INFO_PRINT_COUNTER;
					break;
                case 'x':
					dic->child_info.child_info_type=IPSEC_CHILD_DEBUG_INFO_PRINT_ISA_COUNTER;
					break;
				case 'E':	
					pseudo_start_pluto = 1;
					dic->kernel_info.flag= IPSEC_RESET_COUNTER;
					continue;

				case 'F':
					pseudo_start_pluto = 1;
					dic->kernel_info.flag = IPSEC_SET_DEBUG_SIP;
					dic->kernel_info.sip =inet_addr(optarg);
					continue;

				case 'G':
					pseudo_start_pluto = 1;
					dic->kernel_info.flag = IPSEC_DUMP_COUNTER;
					continue;
					
				case 'L':
					pseudo_start_pluto = 1;
					dic->kernel_info.flag=IPSEC_PRINT_INTERFACE_TEMP;
					if_get_index_by_name(optarg, (s32*)(&dic->kernel_info.ifindex));
					continue;	
					
				case 'M':	
					pseudo_start_pluto = 1;
					dic->kernel_info.flag=IPSEC_PRINT_INTERFACE_TEMP;

				    dic->kernel_info.spi = (u32)chartoint(optarg,strlen(optarg));
					if((int)dic->kernel_info.spi < 0)
					{
						fprintf(stderr,"%s IS ERROR INPUT(For Example:0x123...)\n",optarg);
						pfree(dic);
						return 0;
					}
				    continue;
					
				case 'P':
					pseudo_start_pluto = 1;
					dic->kernel_info.flag=IPSEC_PRINT_INTERFACE_TEMP;
					if(ttoaddr(optarg, 0, AF_INET, &dst_tmp))
					{
					    fprintf(stderr,"you must input right IP\n");
						pfree(dic);
						return 0;					    
					}
					else{
						dic->kernel_info.dsc.a4 = dst_tmp.u.v4.sin_addr.s_addr;
					    continue;
					}
				case 'R':
					pseudo_start_pluto = 1;
					dic->kernel_info.flag=IPSEC_PRINT_INTERFACE_TEMP;
					if(ttosubnet(optarg, 0, AF_INET, &subnet_tmp))
					{
					    fprintf(stderr,"you must input right subnet\n");
						pfree(dic);
						return 0;					    
					}
					else{
					    dic->kernel_info.net.a4 = subnet_tmp.addr.u.v4.sin_addr.s_addr;
					    continue;
					}

				case 'Q':	
					pseudo_start_pluto = 1;
					dic->kernel_info.flag=IPSEC_PRINT_INTERFACE_TEMP;
					dic->kernel_info.connid = atoi(optarg);
					continue;

				case 'V':
		        {
					restore_vrf_pluto = 1;
			    }		
				continue;
				
				default:
					if (c >= DBG_OFFSET)
					{
                        dic->public_info.public_info_flag=1;
						dic->public_info.public_info_value |= c - DBG_OFFSET;						
					}
					continue;
				bad_case(c);
			}
			break;

		}
		/**
		if(restore_vrf_pluto)
   	    {
   		   ipsec_restore_vrf_pluto();	   
   	    }
   	    **/
   		ipsec_restore_vrf_pluto();

	{
		u32 err;
		conplat_syscall(MODULEID_OSBASIC, OSBASIC_GET_VRF_ID, &g_ipsec_vrf_id, sizeof(g_ipsec_vrf_id), (s32*)(&err));	
		if(err != 0)
		{
			g_ipsec_vrf_id = 0;
		}

		sprintf(pluto_lock + strlen(pluto_lock), "_%d", g_ipsec_vrf_id);
		sprintf(ctl_addr.sun_path+ strlen(ctl_addr.sun_path), "_%d", g_ipsec_vrf_id);	
		sprintf(ws_ctl_addr.sun_path+ strlen(ws_ctl_addr.sun_path), "_%d", g_ipsec_vrf_id);			
	}

		switch(dic->com_type)
		{
			case IPSEC_DEBUG_STAR_HANDLE:
				if(dic->public_info.public_info_flag)
				{
					cur_debugging = dic->public_info.public_info_value;
				}

				if(dic->public_info.log_falg)
				{				    
					g_log_level = dic->public_info.log_level_info;					
				}
				break;

			case IPSEC_DEBUG_USER_HANDLE:
				send_connection_debug(dic, IPSEC_DEBUG_USER_HANDLE);
				pfree(dic);
				return 0;

			case IPSEC_DEBUG_KERNEL_HANDLE:
				if(pseudo_start_pluto == 1)
				{
					u32 syscall_result = 0;
					if((dic->kernel_info.flag==IPSEC_PRINT_INTERFACE_TEMP)&&(0 == dic->kernel_info.ifindex))
					{
						fprintf(stderr,"you must input the if name\n");
						pfree(dic);
						return 0;
					}
					
					conplat_syscall(MODULEID_IPSEC_POLICY, IPSEC_MODULE_DEBUG_PART, (void *)(&dic->kernel_info), sizeof(struct ipsec_user_debug_info), (s32 *)(&syscall_result));

					if(g_ipsec_device_is_dpx)
					{
						(u32)conplat_syscall(FW_MODULEID_IPSEC | FW_BOARD, IPSEC_MODULE_DEBUG_PART, (void *)(&dic->kernel_info), sizeof(struct ipsec_user_debug_info), (s32 *)(&syscall_result));
					}

				}
				else
				{
					fprintf(stderr,"after --kernel ,you must input the right command\n");
				}
				pfree(dic);
				return 0;
             case IPSEC_DEBUG_QUIT_HANDLE:
                send_connection_debug(dic, IPSEC_DEBUG_QUIT_HANDLE);
                pfree(dic);
                return 0;
			default:
				fprintf(stderr,"you must input --start --quit --user or --kernel\n");
				exit(0);
		}
		pfree(dic);
	}
	
	if (optind != argc)
	{
		usage("unexpected argument");
	}


	//如果你想再重启设备后默认打开调试开关
#if 0
	cur_debugging = DBG_ALL;
#endif

	lockfd = create_lock();
		

    g_log_level |= ws_get_log_level(); //获得显示级别

    g_ipsec_multiout = ws_get_multiOut(); //获取多接口转发标志位

	if(g_ipsec_multiout)
	{
	    int res;
	    conplat_syscall(MODULEID_IPSEC_POLICY, IPSEC_MODULE_MULTI_OUT, &(g_ipsec_multiout), sizeof(g_ipsec_multiout), &res);
	}

	ipsec_restore_tunnel_ipsec();

	ipsec_init_lv2_switch();
	ipsec_init_route_mode();
	ipsec_init_user_syn();
	ipsec_init_compress_enable();
	
	ipsec_init_udp_checksum_switch();

	ipsec_init_cookie();

	ipsec_esp_alg_init();
	
	init_vendorid();
	//daemon之前销毁缓冲池中的数据库句柄,使用make_daemon不用加此函数
	sqlite3_clear_buffer_ex();  
	{
		{
			pid_t pid = fork();

			if (pid < 0)
			{
				int e = errno;
				fprintf(stderr, "pluto: fork failed (%d %s)\n",errno, strerror(e));
				exit_pluto(1);
			}

			if (pid != 0)
			{
				/* parent: die, after filling PID into lock file.
				* must not use exit_pluto: lock would be removed!
				*/
				exit(fill_lock(lockfd, pid)? 0 : 1);
			}
		}

		if (setsid() < 0)
		{
			int e = errno;
			fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n",errno, strerror(e));
			exit_pluto(1);	
		}
	}

	/** Close everything but  and (if needed) stderr.
	* There is some danger that a library that we don't know
	* about is using some fd that we don't know about.
	* I guess we'll soon find out.
	*/
	{
		int i;

		for (i = getdtablesize() - 1; i >= 0; i--)  /* Bad hack */
		{
			close(i);
		}

		/* make sure that stdin, stdout, stderr are reserved */
		if (open("/dev/null", O_RDONLY) != 0)
		{
			IPSEC_abort();
		}

		if (dup2(0, 1) != 1)
		{
			IPSEC_abort();
		}
	}
	init_constants();	

	init_pluto_vendorid();
	ipsec_version_code();

    ipsec_get_slot_bit();   // 需要放在ipsec_template_delete_all 前面
    
    ipsec_template_delete_all();    
    
    ipsec_enable_flag(1);
	ipsec_init_nat_traversal();

	init_rnd_pool();

	init_states();
	init_connections();//添加到elist链中phase2 pending timer
	init_crypto();
	ipsec_drv_rsa_para_init();   //初始化使用硬件模幂运算时的固定参数
	load_oswcrypto();
	init_demux();

	/* loading X.509 CA certificates */
	load_authcerts("CA cert", "/config/sys/certificate/cacerts", AUTH_CA);
	/* loading X.509 CRLs */
	load_crls();   
    
	fflush(stderr);
	fflush(stdout);
	
	IPSEC_dbg("listening for IKE messages");	

    init_ws_ctl_socket(); 
    
    /*初始化dpdns守护进程*/
    ipsec_dpdns_init_helper();   

    /*读取DPVPN相关配置并初始化*/
    //ipsec_dpvpn_init_cfg();

    /*该操作放在操作数据库之后的主进程处理不能再数据操作*/
	sqlite3_clear_buffer_ex();      
	/*初始化子进程*/
	ipsec_child_init_helpers();  	

	ipsec_main_call_server();

	return -1;	/* Shouldn't ever reach this */
}