int main(int argc, char **argv) { bool fork_desired = TRUE; bool log_to_stderr_desired = FALSE; int lockfd; #ifdef NAT_TRAVERSAL bool nat_traversal = FALSE; unsigned int keep_alive = 0; #endif #ifdef VIRTUAL_IP char *virtual_private = NULL; #endif char *ipsec0 = NULL; char *ipsec1 = NULL; char *ipsec2 = NULL; char *ipsec3 = NULL; /* handle arguments */ for (;;) { static const struct option long_opts[] = { /* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'v' }, { "optionsfrom", required_argument, NULL, '+' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "noklips", no_argument, NULL, 'n' }, { "nocrsend", no_argument, NULL, 'c' }, { "uniqueids", no_argument, NULL, 'u' }, { "interface", required_argument, NULL, 'i' }, { "ikeport", required_argument, NULL, 'p' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "adns", required_argument, NULL, 'a' }, #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all]", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, 'R' }, { "debug-crypt", no_argument, NULL, 'X' }, { "debug-parsing", no_argument, NULL, 'P' }, { "debug-emitting", no_argument, NULL, 'E' }, { "debug-control", no_argument, NULL, 'C' }, { "debug-lifecycle", no_argument, NULL, 'L' }, { "debug-klips", no_argument, NULL, 'K' }, { "debug-dns", no_argument, NULL, 'D' }, { "debug-private", no_argument, NULL, 'Z' }, #endif #ifdef NAT_TRAVERSAL { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, #endif #ifdef VIRTUAL_IP { "virtual_private", required_argument, NULL, '3' }, #endif { "ipsec0", required_argument, NULL, '4' }, { "ipsec1", required_argument, NULL, '5' }, { "ipsec2", required_argument, NULL, '6' }, { "ipsec3", required_argument, NULL, '7' }, { 0,0,0,0 } }; /* 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 c = getopt_long(argc, argv, "", long_opts, NULL); /* Note: "breaking" from case terminates loop */ 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; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'v': /* --version */ { const char **sp = ipsec_copyright_notice(); printf("%s\n", ipsec_version_string()); for (; *sp != NULL; sp++) puts(*sp); } exit_pluto(0); break; /* not actually reached */ case '+': /* --optionsfrom <filename> */ optionsfrom(optarg, &argc, &argv, optind, stderr); /* does not return on error */ continue; case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'n': /* --noklips */ no_klips = TRUE; continue; case 'c': /* --nocrsend */ no_cr_send = TRUE; continue ; case 'u': /* --uniquids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname> */ if (!use_interface(optarg)) usage("too many --interface specifications"); continue; case 'p': /* --port <portnumber> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; case 'b': /* --ctlbase <path> */ if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", optarg, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", optarg, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ shared_secrets_file = optarg; continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; case 'R': /* --debug-raw */ base_debugging |= DBG_RAW; continue; case 'X': /* --debug-crypt */ base_debugging |= DBG_CRYPT; continue; case 'P': /* --debug-parsing */ base_debugging |= DBG_PARSING; continue; case 'E': /* --debug-emitting */ base_debugging |= DBG_EMITTING; continue; case 'C': /* --debug-control */ base_debugging |= DBG_CONTROL; continue; case 'L': /* --debug-lifecycle */ base_debugging |= DBG_LIFECYCLE; continue; case 'K': /* --debug-klips */ base_debugging |= DBG_KLIPS; continue; case 'D': /* --debug-dns */ base_debugging |= DBG_DNS; continue; case 'Z': /* --debug-private */ base_debugging |= DBG_PRIVATE; continue; #endif #ifdef NAT_TRAVERSAL case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; #endif #ifdef VIRTUAL_IP case '3': /* --virtual_private */ virtual_private = optarg; continue; #endif case '4': /* --ipsec0 */ ipsec0 = optarg; continue; case '5': /* --ipsec1 */ ipsec1 = optarg; continue; case '6': /* --ipsec2 */ ipsec2 = optarg; continue; case '7': /* --ipsec3 */ ipsec3 = optarg; continue; default: impossible(); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired) log_to_syslog = FALSE; else log_to_stderr = FALSE; /* 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: %s", ugh); exit_pluto(1); } } /* If not suppressed, do daemon fork */ #ifndef EMBED if (fork_desired) { { 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 ctl_fd and (if needed) stderr. */ { 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) abort(); if (dup2(0, 1) != 1) abort(); if (!log_to_stderr && dup2(0, 2) != 2) abort(); } } else #endif { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); fprintf(stdout, "Pluto initialized\n"); fflush(stdout); } init_constants(); init_log(); /* Note: some scripts may look for this exact message -- don't change */ log("Starting Pluto (FreeS/WAN Version %s)", ipsec_version_code()); log(" including X.509 patch (Version %s)", x509patch_version); #ifdef NAT_TRAVERSAL init_nat_traversal(nat_traversal,keep_alive); #endif #ifdef VIRTUAL_IP init_virtual_ip(virtual_private); #endif init_interfaces(ipsec0, ipsec1, ipsec2, ipsec3); init_rnd_pool(); init_secret(); init_states(); init_crypto(); init_demux(); init_kernel(); init_adns(); /* loading CA certificates */ load_cacerts(); /* loading CRLs */ load_crls(); /* loading my X.509 or OpenPGP certificate */ load_mycert(); call_server(); return -1; /* Shouldn't ever reach this */ }
int main(int argc, char **argv) { bool fork_desired = TRUE; int lockfd; char* ocspuri = NULL; int nhelpers = -1; char *coredir; const struct osw_conf_options *oco; #ifdef NAT_TRAVERSAL /** Overridden by nat_traversal= in ipsec.conf */ bool nat_traversal = FALSE; bool nat_t_spf = TRUE; /* support port floating */ unsigned int keep_alive = 0; bool force_keepalive = FALSE; #endif /** Overridden by virtual_private= in ipsec.conf */ char *virtual_private = NULL; #ifdef LEAK_DETECTIVE leak_detective=1; #else leak_detective=0; #endif #ifdef HAVE_LIBCAP_NG /* Drop capabilities */ 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, -1); /* our children must be able to CAP_NET_ADMIN to change routes. */ capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET, CAP_NET_ADMIN, -1); capng_apply(CAPNG_SELECT_BOTH); #endif global_argv = argv; global_argc = argc; #ifdef DEBUG openswan_passert_fail = passert_fail; #endif /* see if there is an environment variable */ coredir = getenv("PLUTO_CORE_DIR"); if(getenv("PLUTO_WAIT_FOR_GDB")) { sleep(120); } /* handle arguments */ 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' }, { "optionsfrom", required_argument, NULL, '+' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "noklips", no_argument, NULL, 'n' }, { "use-nostack", no_argument, NULL, 'n' }, { "use-none", no_argument, NULL, 'n' }, { "force_busy", no_argument, NULL, 'D' }, { "nocrsend", no_argument, NULL, 'c' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, { "crlcheckinterval", required_argument, NULL, 'x'}, { "ocsprequestcert", required_argument, NULL, 'q'}, { "ocspuri", required_argument, NULL, 'o'}, { "uniqueids", no_argument, NULL, 'u' }, { "useklips", no_argument, NULL, 'k' }, { "use-klips", no_argument, NULL, 'k' }, { "use-auto", no_argument, NULL, 'G' }, { "usenetkey", no_argument, NULL, 'K' }, { "use-netkey", no_argument, NULL, 'K' }, { "use-mast", no_argument, NULL, 'M' }, { "use-mastklips", no_argument, NULL, 'M' }, { "use-bsdkame", no_argument, NULL, 'F' }, { "interface", required_argument, NULL, 'i' }, { "listen", required_argument, NULL, 'L' }, { "ikeport", required_argument, NULL, 'p' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "foodgroupsdir", required_argument, NULL, 'f' }, { "perpeerlogbase", required_argument, NULL, 'P' }, { "perpeerlog", no_argument, NULL, 'l' }, { "noretransmits", no_argument, NULL, 'R' }, { "coredir", required_argument, NULL, 'C' }, { "ipsecdir", required_argument, NULL, 'f' }, { "ipsec_dir", required_argument, NULL, 'f' }, #ifdef USE_LWRES { "lwdnsq", required_argument, NULL, 'a' }, #else /* !USE_LWRES */ { "adns", required_argument, NULL, 'a' }, #endif /* !USE_LWRES */ #ifdef NAT_TRAVERSAL { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, { "force_keepalive", no_argument, NULL, '3' }, { "disable_port_floating", no_argument, NULL, '4' }, { "debug-nat_t", no_argument, NULL, '5' }, { "debug-nattraversal", no_argument, NULL, '5' }, { "debug-nat-t", no_argument, NULL, '5' }, #endif { "virtual_private", required_argument, NULL, '6' }, { "nhelpers", required_argument, NULL, 'j' }, #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, { "debug-crypt", no_argument, NULL, DBG_CRYPT + 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-oppo", no_argument, NULL, DBG_OPPO + 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-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 }, { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, { "impair-sa-creation", no_argument, NULL, IMPAIR_SA_CREATION + DBG_OFFSET }, { "impair-die-oninfo", no_argument, NULL, IMPAIR_DIE_ONINFO + DBG_OFFSET }, { "impair-jacob-two-two", no_argument, NULL, IMPAIR_JACOB_TWO_TWO + DBG_OFFSET }, #endif { 0,0,0,0 } }; /* 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 c = getopt_long(argc, argv, "", long_opts, NULL); /** Note: "breaking" from case terminates loop */ 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; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'C': coredir = clone_str(optarg, "coredir"); break; case 'v': /* --version */ { 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); /* not exit_pluto because we are not initialized yet */ break; /* not actually reached */ case '+': /* --optionsfrom <filename> */ optionsfrom(optarg, &argc, &argv, optind, stderr); /* does not return on error */ continue; case 'j': /* --nhelpers */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing number of pluto helpers"); { char *endptr; long count = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || count < -1) usage("<nhelpers> must be a positive number, 0 or -1"); nhelpers = count; } continue; case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'G': /* --use-auto */ kern_interface = AUTO_PICK; continue; case 'k': /* --use-klips */ kern_interface = USE_KLIPS; continue; case 'L': /* --listen ip_addr */ { ip_address lip; err_t e = ttoaddr(optarg,0,0,&lip); if(e) { openswan_log("invalid listen argument ignored: %s\n",e); } else { pluto_listen = clone_str(optarg, "pluto_listen"); openswan_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 */ force_busy = TRUE; continue ; case 'c': /* --nocrsend */ no_cr_send = TRUE; continue ; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue ; case 'R': no_retransmits = TRUE; continue; case 'x': /* --crlcheckinterval <time>*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing interval time"); { char *endptr; long interval = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || interval <= 0) usage("<interval-time> must be a positive number"); crl_check_interval = interval; } continue ; case 'o': /* --ocspuri */ ocspuri = optarg; continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname|ifaddr> */ if (!use_interface(optarg)) usage("too many --interface specifications"); 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> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; case 'b': /* --ctlbase <path> */ ctlbase = optarg; if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", ctlbase, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path) , "%s%s", ctlbase, INFO_SUFFIX) == -1) usage("<path>" INFO_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", ctlbase, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ pluto_shared_secrets_file = optarg; continue; case 'f': /* --ipsecdir <ipsec-dir> */ (void)osw_init_ipsecdir(optarg); continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; #endif case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': log_to_perpeer = TRUE; continue; #ifdef NAT_TRAVERSAL case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; case '3': /* --force_keepalive */ force_keepalive = TRUE; continue; case '4': /* --disable_port_floating */ nat_t_spf = FALSE; continue; #ifdef DEBUG case '5': /* --debug-nat_t */ base_debugging |= DBG_NATT; continue; #endif #endif case '6': /* --virtual_private */ virtual_private = optarg; continue; default: #ifdef DEBUG if (c >= DBG_OFFSET) { base_debugging |= c - DBG_OFFSET; continue; } # undef DBG_OFFSET #endif bad_case(c); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); #ifdef HAVE_NO_FORK fork_desired = FALSE; nhelpers = 0; #endif /* if a core dir was set, chdir there */ if(coredir) if(chdir(coredir) == -1) { int e = errno; openswan_log("pluto: chdir() do dumpdir failed (%d %s)\n", e, strerror(e)); } oco = osw_init_options(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired) log_to_syslog = FALSE; else log_to_stderr = FALSE; #ifdef DEBUG #if 0 if(kernel_ops->set_debug) { (*kernel_ops->set_debug)(cur_debugging, DBG_log, DBG_log); } #endif #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: %s", ugh); exit_pluto(1); } } #ifdef IPSECPOLICY /* create info socket. */ { err_t ugh = init_info_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } #endif /* If not suppressed, do daemon fork */ if (fork_desired) { { 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); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); 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) #ifdef IPSECPOLICY && i != info_fd #endif && i != ctl_fd) close(i); /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) osw_abort(); if (dup2(0, 1) != 1) osw_abort(); if (!log_to_stderr && dup2(0, 2) != 2) osw_abort(); } init_constants(); pluto_init_log(); #ifdef HAVE_LIBNSS char buf[100]; snprintf(buf, sizeof(buf), "%s",oco->confddir); loglog(RC_LOG_SERIOUS,"nss directory plutomain: %s",buf); SECStatus nss_init_status= NSS_InitReadWrite(buf); if (nss_init_status != SECSuccess) { loglog(RC_LOG_SERIOUS, "NSS initialization failed (err %d)\n", PR_GetError()); exit_pluto(10); } else { loglog(RC_LOG_SERIOUS, "NSS Initialized"); PK11_SetPasswordFunc(getNSSPassword); #ifdef FIPS_CHECK const char *package_files[]= { IPSECLIBDIR"/setup", IPSECLIBDIR"/addconn", IPSECLIBDIR"/auto", IPSECLIBDIR"/barf", IPSECLIBDIR"/_copyright", IPSECLIBDIR"/eroute", IPSECLIBDIR"/ikeping", IPSECLIBDIR"/_include", IPSECLIBDIR"/_keycensor", IPSECLIBDIR"/klipsdebug", IPSECLIBDIR"/look", IPSECLIBDIR"/newhostkey", IPSECLIBDIR"/pf_key", IPSECLIBDIR"/_pluto_adns", IPSECLIBDIR"/_plutoload", IPSECLIBDIR"/_plutorun", IPSECLIBDIR"/ranbits", IPSECLIBDIR"/_realsetup", IPSECLIBDIR"/rsasigkey", IPSECLIBDIR"/pluto", IPSECLIBDIR"/_secretcensor", IPSECLIBDIR"/secrets", IPSECLIBDIR"/showdefaults", IPSECLIBDIR"/showhostkey", IPSECLIBDIR"/showpolicy", IPSECLIBDIR"/spi", IPSECLIBDIR"/spigrp", IPSECLIBDIR"/_startklips", IPSECLIBDIR"/_startnetkey", IPSECLIBDIR"/tncfg", IPSECLIBDIR"/_updown", IPSECLIBDIR"/_updown.klips", IPSECLIBDIR"/_updown.mast", IPSECLIBDIR"/_updown.netkey", IPSECLIBDIR"/verify", IPSECLIBDIR"/whack", IPSECSBINDIR"/ipsec", NULL }; if (Pluto_IsFIPS() && !FIPSCHECK_verify_files(package_files)) { loglog(RC_LOG_SERIOUS, "FIPS integrity verification test failed"); exit_pluto(10); } #endif } #endif /* Note: some scripts may look for this exact message -- don't change * ipsec barf was one, but it no longer does. */ { const char *vc = ipsec_version_code(); #ifdef PLUTO_SENDS_VENDORID const char *v = init_pluto_vendorid(); openswan_log("Starting Pluto (Openswan Version %s%s; Vendor ID %s) pid:%u" , vc, compile_time_interop_options, v, getpid()); #else openswan_log("Starting Pluto (Openswan Version %s%s) pid:%u" , vc, compile_time_interop_options, getpid()); #endif #ifdef HAVE_LIBNSS if(Pluto_IsFIPS()) { openswan_log("Pluto is running in FIPS mode"); } #endif if((vc[0]=='c' && vc[1]=='v' && vc[2]=='s') || (vc[2]=='g' && vc[3]=='i' && vc[4]=='t')) { /* * when people build RPMs from CVS or GIT, make sure they * get blamed appropriately, and that we get some way to * identify who did it, and when they did it. Use string concat, * so that strings the binary can or classic SCCS "what", will find * stuff too. */ openswan_log("@(#) built on "__DATE__":" __TIME__ " by " BUILDER); } #if defined(USE_1DES) openswan_log("WARNING: 1DES is enabled"); #endif } if(coredir) { openswan_log("core dump dir: %s", coredir); } #ifdef LEAK_DETECTIVE openswan_log("LEAK_DETECTIVE support [enabled]"); #else openswan_log("LEAK_DETECTIVE support [disabled]"); #endif #ifdef HAVE_OCF { struct stat buf; errno=0; if( stat("/dev/crypto",&buf) != -1) openswan_log("OCF support for IKE via /dev/crypto [enabled]"); else openswan_log("OCF support for IKE via /dev/crypto [failed:%s]", strerror(errno)); } #else openswan_log("OCF support for IKE [disabled]"); #endif /* 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 ) { openswan_log("SAref support [disabled]: %s" , strerror(errno)); } else { openswan_log("SAref support [enabled]"); } errno=0; e = setsockopt(sk, IPPROTO_IP, IP_IPSEC_BINDREF, &saref, sizeof(saref)); if (e == -1 ) { openswan_log("SAbind support [disabled]: %s" , strerror(errno)); } else { openswan_log("SAbind support [enabled]"); } close(sk); } #endif #ifdef HAVE_LIBNSS openswan_log("NSS support [enabled]"); #else openswan_log("NSS support [disabled]"); #endif #ifdef HAVE_STATSD openswan_log("HAVE_STATSD notification via /bin/openswan-statsd enabled"); #else openswan_log("HAVE_STATSD notification support not compiled in"); #endif /** Log various impair-* functions if they were enabled */ if(DBGP(IMPAIR_BUST_MI2)) openswan_log("Warning: IMPAIR_BUST_MI2 enabled"); if(DBGP(IMPAIR_BUST_MR2)) openswan_log("Warning: IMPAIR_BUST_MR2 enabled"); if(DBGP(IMPAIR_SA_CREATION)) openswan_log("Warning: IMPAIR_SA_CREATION enabled"); if(DBGP(IMPAIR_JACOB_TWO_TWO)) openswan_log("Warning: IMPAIR_JACOB_TWO_TWO enabled"); if(DBGP(IMPAIR_DIE_ONINFO)) openswan_log("Warning: IMPAIR_DIE_ONINFO enabled"); if(DBGP(IMPAIR_DELAY_ADNS_KEY_ANSWER)) openswan_log("Warning: IMPAIR_DELAY_ADNS_KEY_ANSWER enabled"); if(DBGP(IMPAIR_DELAY_ADNS_TXT_ANSWER)) openswan_log("Warning: IMPAIR_DELAY_ADNS_TXT_ANSWER enabled"); /** Initialize all of the various features */ #ifdef NAT_TRAVERSAL init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); #endif init_virtual_ip(virtual_private); init_rnd_pool(); init_timer(); init_secret(); init_states(); init_connections(); init_crypto(); init_crypto_helpers(nhelpers); load_oswcrypto(); init_demux(); init_kernel(); init_adns(); init_id(); #ifdef TPM init_tpm(); #endif #ifdef HAVE_THREADS init_fetch(); #endif ocsp_set_default_uri(ocspuri); /* loading X.509 CA certificates */ load_authcerts("CA cert", oco->cacerts_dir, AUTH_CA); /* loading X.509 AA certificates */ load_authcerts("AA cert", oco->aacerts_dir, AUTH_AA); /* loading X.509 OCSP certificates */ load_authcerts("OCSP cert", oco->ocspcerts_dir, AUTH_OCSP); /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ load_acerts(); #ifdef HAVE_LIBNSS /*Loading CA certs from NSS DB*/ load_authcerts_from_nss("CA cert", AUTH_CA); #endif daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ }
/* * initialize a helper. */ static void init_crypto_helper(struct pluto_crypto_worker *w, int n) { int fds[2]; #ifndef HAVE_LIBNSS int errno2; #endif /* reset this */ w->pcw_pid = -1; if(socketpair(PF_UNIX, SOCK_STREAM, 0, fds) != 0) { loglog(RC_LOG_SERIOUS, "could not create socketpair for helpers: %s", strerror(errno)); return; } w->pcw_helpernum = n; w->pcw_pipe = fds[0]; #ifdef HAVE_LIBNSS w->pcw_helper_pipe = fds[1]; #endif w->pcw_maxbasicwork = 2; w->pcw_maxcritwork = 4; w->pcw_work = 0; w->pcw_reaped = FALSE; w->pcw_dead = FALSE; TAILQ_INIT(&w->pcw_active); /* set the send/received queue length to be at least maxcritwork * times sizeof(pluto_crypto_req) in size */ { int qlen = w->pcw_maxcritwork * sizeof(struct pluto_crypto_req) + 10; if(setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF,&qlen, sizeof(qlen))==-1 || setsockopt(fds[0],SOL_SOCKET,SO_SNDBUF,&qlen,sizeof(qlen))==-1 || setsockopt(fds[1],SOL_SOCKET,SO_RCVBUF,&qlen,sizeof(qlen))==-1 || setsockopt(fds[1],SOL_SOCKET,SO_RCVBUF,&qlen,sizeof(qlen))==-1) { loglog(RC_LOG_SERIOUS, "could not set socket queue to %d", qlen); return; } } /* flush various descriptors so that they don't get written twice */ #ifndef HAVE_LIBNSS fflush(stdout); fflush(stderr); close_log(); close_peerlog(); #endif /* set local so that child inheirits it */ pc_helper_num = n; #ifdef HAVE_LIBNSS int thread_status; thread_status = pthread_create((pthread_t*)&w->pcw_pid, NULL, pluto_helper_thread, (void*)w); if(thread_status!=0) { loglog(RC_LOG_SERIOUS, "failed to start child, error = %d" , thread_status); w->pcw_pid= -1; close(fds[1]); close(fds[0]); w->pcw_dead = TRUE; return; } else{ openswan_log("started helper (thread) pid=%ld (fd:%d)", w->pcw_pid, w->pcw_pipe); } #else w->pcw_pid = fork(); errno2 = errno; if(w->pcw_pid == 0) { /* this is the CHILD */ int fd; int maxfd; struct rlimit nf; int i, arg_len = 0; /* diddle with our proc title */ memset(global_argv[0], '\0', strlen(global_argv[0])+1); arg_len += strlen(global_argv[0]); for(i = 1; i < global_argc; i++) { if(global_argv[i]) { int l = strlen(global_argv[i]); memset(global_argv[i], '\0', l); arg_len += l; } global_argv[i]=NULL; } snprintf(global_argv[0], arg_len, "pluto helper %s #%3d " , pluto_ifn_inst, n); if(getenv("PLUTO_CRYPTO_HELPER_DEBUG")) { snprintf(global_argv[0], arg_len, "pluto helper %s #%3d (waiting for GDB) ", pluto_ifn_inst, n); sleep(60); /* for debugger to attach */ sprintf(global_argv[0], "pluto helper %s #%3d " , pluto_ifn_inst, n); } if(getrlimit(RLIMIT_NOFILE, &nf) == -1) { maxfd = 256; } else { maxfd = nf.rlim_max; } /* in child process, close all non-essential fds */ for(fd = 3; fd < maxfd; fd++) { if(fd != fds[1]) close(fd); } pluto_init_log(); init_rnd_pool(); load_oswcrypto(); free_preshared_secrets(); #ifdef DEBUG openswan_passert_fail = helper_passert_fail; debug_prefix='!'; #endif pluto_crypto_helper(fds[1], n); exit(0); /* NOTREACHED */ } /* open the log files again */ pluto_init_log(); if(w->pcw_pid == -1) { loglog(RC_LOG_SERIOUS, "failed to start child, error = %s" , strerror(errno2)); close(fds[1]); close(fds[0]); w->pcw_dead = TRUE; return; } /* PARENT */ openswan_log("started helper pid=%d (fd:%d)", w->pcw_pid, w->pcw_pipe); /* close client side of socket pair in parent */ close(fds[1]); #endif }
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 */ }
int main(int argc, char **argv) { bool fork_desired = TRUE; bool log_to_stderr_desired = FALSE; int lockfd; char* ocspuri = NULL; #ifdef NAT_TRAVERSAL /** Overridden by nat_traversal= in ipsec.conf */ bool nat_traversal = FALSE; bool nat_t_spf = TRUE; /* support port floating */ unsigned int keep_alive = 0; bool force_keepalive = FALSE; #endif #ifdef VIRTUAL_IP /** Overridden by virtual_private= in ipsec.conf */ char *virtual_private = NULL; #endif /* handle arguments */ 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' }, { "optionsfrom", required_argument, NULL, '+' }, { "nofork", no_argument, NULL, 'd' }, { "stderrlog", no_argument, NULL, 'e' }, { "noklips", no_argument, NULL, 'n' }, { "nocrsend", no_argument, NULL, 'c' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, { "crlcheckinterval", required_argument, NULL, 'x'}, { "ocsprequestcert", required_argument, NULL, 'q'}, { "ocspuri", required_argument, NULL, 'o'}, { "uniqueids", no_argument, NULL, 'u' }, { "interface", required_argument, NULL, 'i' }, { "ikeport", required_argument, NULL, 'p' }, { "ctlbase", required_argument, NULL, 'b' }, { "secretsfile", required_argument, NULL, 's' }, { "foodgroupsdir", required_argument, NULL, 'f' }, { "perpeerlogbase", required_argument, NULL, 'P' }, { "perpeerlog", no_argument, NULL, 'l' }, { "noretransmits", no_argument, NULL, 'R' }, { "ipsecdir", required_argument, NULL, 'f' }, { "ipsec_dir", required_argument, NULL, 'f' }, #ifdef USE_LWRES { "lwdnsq", required_argument, NULL, 'a' }, #else /* !USE_LWRES */ { "adns", required_argument, NULL, 'a' }, #endif /* !USE_LWRES */ #ifdef NAT_TRAVERSAL { "nat_traversal", no_argument, NULL, '1' }, { "keep_alive", required_argument, NULL, '2' }, { "force_keepalive", no_argument, NULL, '3' }, { "disable_port_floating", no_argument, NULL, '4' }, { "debug-nat_t", no_argument, NULL, '5' }, #endif #ifdef VIRTUAL_IP { "virtual_private", required_argument, NULL, '6' }, #endif #ifdef DEBUG { "debug-none", no_argument, NULL, 'N' }, { "debug-all]", no_argument, NULL, 'A' }, { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET }, { "debug-crypt", 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-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET }, { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET }, { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET }, { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET }, { "debug-pfkey", no_argument, NULL, DBG_PFKEY + DBG_OFFSET }, { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET }, { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET }, { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET }, { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET }, #endif { 0,0,0,0 } }; /* 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 c = getopt_long(argc, argv, "", long_opts, NULL); /** Note: "breaking" from case terminates loop */ 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; /* not actually reached */ case 'h': /* --help */ usage(NULL); break; /* not actually reached */ case 'v': /* --version */ { 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); /* not exit_pluto because we are not initialized yet */ break; /* not actually reached */ case '+': /* --optionsfrom <filename> */ optionsfrom(optarg, &argc, &argv, optind, stderr); /* does not return on error */ continue; case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'n': /* --noklips */ no_klips = TRUE; continue; case 'c': /* --nocrsend */ no_cr_send = TRUE; continue ; case 'r': /* --strictcrlpolicy */ strict_crl_policy = TRUE; continue ; case 'R': no_retransmits = TRUE; continue; case 'x': /* --crlcheckinterval <time>*/ if (optarg == NULL || !isdigit(optarg[0])) usage("missing interval time"); { char *endptr; long interval = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || interval <= 0) usage("<interval-time> must be a positive number"); crl_check_interval = interval; } continue ; case 'o': /* --ocspuri */ ocspuri = optarg; continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'i': /* --interface <ifname> */ if (!use_interface(optarg)) usage("too many --interface specifications"); continue; case 'p': /* --port <portnumber> */ if (optarg == NULL || !isdigit(optarg[0])) usage("missing port number"); { char *endptr; long port = strtol(optarg, &endptr, 0); if (*endptr != '\0' || endptr == optarg || port <= 0 || port > 0x10000) usage("<port-number> must be a number between 1 and 65535"); pluto_port = port; } continue; case 'b': /* --ctlbase <path> */ if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path) , "%s%s", optarg, CTL_SUFFIX) == -1) usage("<path>" CTL_SUFFIX " too long for sun_path"); if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path) , "%s%s", optarg, INFO_SUFFIX) == -1) usage("<path>" INFO_SUFFIX " too long for sun_path"); if (snprintf(pluto_lock, sizeof(pluto_lock) , "%s%s", optarg, LOCK_SUFFIX) == -1) usage("<path>" LOCK_SUFFIX " must fit"); continue; case 's': /* --secretsfile <secrets-file> */ shared_secrets_file = optarg; continue; case 'f': /* --ipsecdir <ipsec-dir> */ ipsec_dir = optarg; continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; #ifdef DEBUG case 'N': /* --debug-none */ base_debugging = DBG_NONE; continue; case 'A': /* --debug-all */ base_debugging = DBG_ALL; continue; #endif case 'P': /* --perpeerlogbase */ base_perpeer_logdir = optarg; continue; case 'l': log_to_perpeer = TRUE; continue; #ifdef NAT_TRAVERSAL case '1': /* --nat_traversal */ nat_traversal = TRUE; continue; case '2': /* --keep_alive */ keep_alive = atoi(optarg); continue; case '3': /* --force_keepalive */ force_keepalive = TRUE; continue; case '4': /* --disable_port_floating */ nat_t_spf = FALSE; continue; case '5': /* --debug-nat_t */ base_debugging |= DBG_NATT; continue; #endif #ifdef VIRTUAL_IP case '6': /* --virtual_private */ virtual_private = optarg; continue; #endif default: #ifdef DEBUG if (c >= DBG_OFFSET) { base_debugging |= c - DBG_OFFSET; continue; } # undef DBG_OFFSET #endif bad_case(c); } break; } if (optind != argc) usage("unexpected argument"); reset_debugging(); lockfd = create_lock(); /* select between logging methods */ if (log_to_stderr_desired) log_to_syslog = FALSE; else log_to_stderr = FALSE; /* set the logging function of pfkey debugging */ #ifdef DEBUG pfkey_debug_func = DBG_log; pfkey_error_func = DBG_log; #else pfkey_debug_func = NULL; pfkey_error_func = NULL; #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: %s", ugh); exit_pluto(1); } } #ifdef IPSECPOLICY /* create info socket. */ { err_t ugh = init_info_socket(); if (ugh != NULL) { fprintf(stderr, "pluto: %s", ugh); exit_pluto(1); } } #endif /* If not suppressed, do daemon fork */ if (fork_desired) { { 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); } } else { /* no daemon fork: we have to fill in lock file */ (void) fill_lock(lockfd, getpid()); 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) #ifdef IPSECPOLICY && i != info_fd #endif && i != ctl_fd) close(i); /* make sure that stdin, stdout, stderr are reserved */ if (open("/dev/null", O_RDONLY) != 0) abort(); if (dup2(0, 1) != 1) abort(); if (!log_to_stderr && dup2(0, 2) != 2) abort(); } init_constants(); pluto_init_log(); /* Note: some scripts may look for this exact message -- don't change * ipsec barf was one, but it no longer does. */ { #ifdef PLUTO_SENDS_VENDORID const char *v = init_pluto_vendorid(); openswan_log("Starting Pluto (Openswan Version %s%s; Vendor ID %s)" , ipsec_version_code() , compile_time_interop_options , v); #else openswan_log("Starting Pluto (Openswan Version %s%s)" , ipsec_version_code() , compile_time_interop_options); #endif } /** Initialize all of the various features */ #ifdef NAT_TRAVERSAL init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); #endif #ifdef VIRTUAL_IP init_virtual_ip(virtual_private); #endif init_rnd_pool(); init_secret(); init_states(); init_crypto(); init_demux(); init_kernel(); init_adns(); init_id(); #ifdef HAVE_THREADS init_fetch(); #endif ocsp_set_default_uri(ocspuri); /* loading X.509 CA certificates */ load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA); /* loading X.509 AA certificates */ load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA); /* loading X.509 OCSP certificates */ load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP); /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ load_acerts(); daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ }