/* leave pluto, with status. * Once child is launched, parent must not exit this way because * the lock would be released. * * 0 OK * 1 general discomfort * 10 lock file exists */ void exit_pluto(int status) { reset_globals(); /* needed because we may be called in odd state */ free_preshared_secrets(); free_remembered_public_keys(); delete_every_connection(); /* free memory allocated by initialization routines. Please don't forget to do this. */ #ifdef HAVE_THREADS free_crl_fetch(); /* free chain of crl fetch requests */ #endif #ifdef HAVE_OCSP free_ocsp_fetch(); /* free chain of ocsp fetch requests */ #endif free_authcerts(); /* free chain of X.509 authority certificates */ free_crls(); /* free chain of X.509 CRLs */ free_acerts(); /* free chain of X.509 attribute certificates */ free_ocsp(); /* free ocsp cache */ free_ifaces(); /* free interface list from memory */ stop_adns(); /* Stop async DNS process (if running) */ free_md_pool(); /* free the md pool */ delete_lock(); /* delete any lock files */ #ifdef LEAK_DETECTIVE report_leaks(); /* report memory leaks now, after all free()s */ #endif /* LEAK_DETECTIVE */ close_log(); /* close the logfiles */ exit(status); /* exit, with our error code */ }
/* leave pluto, with status. * Once child is launched, parent must not exit this way because * the lock would be released. * * 0 OK * 1 general discomfort * 10 lock file exists */ void exit_pluto(int status) { reset_globals(); /* needed because we may be called in odd state */ free_preshared_secrets(); free_remembered_public_keys(); close_ha_iface(); delete_every_connection(); whack_attribute_finalize(); /* free in-memory pools */ fetch_finalize(); /* stop fetching thread */ free_crl_fetch(); /* free chain of crl fetch requests */ free_ocsp_fetch(); /* free chain of ocsp fetch requests */ free_authcerts(); /* free chain of X.509 authority certificates */ free_crls(); /* free chain of X.509 CRLs */ free_ca_infos(); /* free chain of X.509 CA information records */ free_ocsp(); /* free ocsp cache */ free_ifaces(); ac_finalize(); /* free X.509 attribute certificates */ scx_finalize(); /* finalize and unload PKCS #11 module */ stop_adns(); free_md_pool(); free_crypto(); free_myid(); /* free myids */ free_events(); /* free remaining events */ free_vendorid(); /* free all vendor id records */ free_builder(); delete_lock(); options->destroy(options); pluto_deinit(); lib->plugins->unload(lib->plugins); libhydra_deinit(); library_deinit(); close_log(); exit(status); }
static struct Interface *reload_config(int sock, struct Interface *ifaces, char const *conf_path) { free_ifaces(ifaces); flog(LOG_INFO, "attempting to reread config file"); /* reread config file */ ifaces = readin_config(conf_path); if (!ifaces) { flog(LOG_ERR, "exiting, failed to read config file"); exit(1); } setup_ifaces(sock, ifaces); flog(LOG_INFO, "resuming normal operation"); return ifaces; }
/* leave pluto, with status. * Once child is launched, parent must not exit this way because * the lock would be released. * * 0 OK * 1 general discomfort * 10 lock file exists */ void exit_pluto(int status) { reset_globals(); /* needed because we may be called in odd state */ free_preshared_secrets(); free_remembered_public_keys(); delete_every_connection(); free_cacerts(); /* free chain of CA certificates */ free_crls(); /* free chain of CRLS */ free_mycert(); /* free default certificate (deprecated for X.509) */ free_ifaces(); stop_adns(); free_md_pool(); delete_lock(); #ifdef LEAK_DETECTIVE report_leaks(); #endif /* LEAK_DETECTIVE */ close_log(); exit(status); }
/* * leave pluto, with status. * Once child is launched, parent must not exit this way because * the lock would be released. * * 0 OK * 1 general discomfort * 10 lock file exists */ void exit_pluto(int status) { /* needed because we may be called in odd state */ reset_globals(); #ifdef USE_SYSTEMD_WATCHDOG pluto_sd(PLUTO_SD_STOPPING, status); #endif free_preshared_secrets(); free_remembered_public_keys(); delete_every_connection(); /* * free memory allocated by initialization routines. Please don't * forget to do this. */ #if defined(LIBCURL) || defined(LDAP_VER) free_crl_fetch(); /* free chain of crl fetch requests */ #endif lsw_conf_free_oco(); /* free global_oco containing path names */ free_myFQDN(); /* free myid FQDN */ free_ifaces(); /* free interface list from memory */ free_md_pool(); /* free the md pool */ lsw_nss_shutdown(); delete_lock(); /* delete any lock files */ free_virtual_ip(); /* virtual_private= */ free_kernelfd(); /* stop listening to kernel FD, remove event */ free_pluto_main(); /* our static chars */ /* report memory leaks now, after all free_* calls */ if (leak_detective) report_leaks(); close_log(); /* close the logfiles */ #ifdef USE_SYSTEMD_WATCHDOG pluto_sd(PLUTO_SD_EXIT,status); #endif exit(status); /* exit, with our error code */ }
void exit_pluto(int status) { delete_every_connection(); if (g_ipsec_child_num == 0) { ipsec_template_delete_all(); ipsec_enable_flag(0); } free_authcerts(); /* free chain of X.509 authority certificates */ free_crls(); /* free chain of X.509 CRLs */ free_ifaces(); /* free interface list from memory */ if(g_ipsec_child_num < g_ipsec_child_cnt) { /*若是子进程,则告知父进程,子进程退出了*/ int wlen = 0; pid_t local_pid = g_ipsec_child_num + ipsec_upid_float; int flag = IPSEC_CHILD_STOP_EXIT; ipsec_nl_send2krl(g_ipsec_nl_fd, local_pid, IPSEC_NL_1U_CLOSE); wlen = write(g_ipsec_child_fd, (void *)&flag, 4); IPSEC_DEBUG(DBG_CONTROL, IPSEC_dbg("g_ipsec_child_num: %d, cnt: %d, wlen is : %d \n\n",g_ipsec_child_num, g_ipsec_child_cnt,wlen););
/* leave pluto, with status. * Once child is launched, parent must not exit this way because * the lock would be released. * * 0 OK * 1 general discomfort * 10 lock file exists */ void exit_pluto(int status) { reset_globals(); /* needed because we may be called in odd state */ free_preshared_secrets(); free_remembered_public_keys(); delete_every_connection(); /* free memory allocated by initialization routines. Please don't forget to do this. */ #ifdef TPM free_tpm(); #endif #if defined(LIBCURL) || defined(LDAP_VER) free_crl_fetch(); /* free chain of crl fetch requests */ #endif free_authcerts(); /* free chain of X.509 authority certificates */ free_crls(); /* free chain of X.509 CRLs */ free_acerts(); /* free chain of X.509 attribute certificates */ lsw_conf_free_oco(); /* free global_oco containing path names */ free_myFQDN(); /* free myid FQDN */ free_ifaces(); /* free interface list from memory */ stop_adns(); /* Stop async DNS process (if running) */ free_md_pool(); /* free the md pool */ NSS_Shutdown(); delete_lock(); /* delete any lock files */ #ifdef LEAK_DETECTIVE report_leaks(); /* report memory leaks now, after all free()s */ #endif /* LEAK_DETECTIVE */ close_log(); /* close the logfiles */ exit(status); /* exit, with our error code */ }
/* * Returns zero or more local interfaces to the requestor */ DWORD request_net_config_get_interfaces(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; DWORD entryCount; #ifdef _WIN32 Tlv entries[5]; PMIB_IPADDRTABLE table = NULL; DWORD tableSize = sizeof(MIB_IPADDRROW) * 33; DWORD index; MIB_IFROW iface; do { // Allocate memory for reading addresses into if (!(table = (PMIB_IPADDRTABLE)malloc(tableSize))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } // Get the IP address table if (GetIpAddrTable(table, &tableSize, TRUE) != NO_ERROR) { result = GetLastError(); break; } // Enumerate the entries for (index = 0; index < table->dwNumEntries; index++) { entryCount = 0; entries[entryCount].header.length = sizeof(DWORD); entries[entryCount].header.type = TLV_TYPE_IP; entries[entryCount].buffer = (PUCHAR)&table->table[index].dwAddr; entryCount++; entries[entryCount].header.length = sizeof(DWORD); entries[entryCount].header.type = TLV_TYPE_NETMASK; entries[entryCount].buffer = (PUCHAR)&table->table[index].dwMask; entryCount++; iface.dwIndex = table->table[index].dwIndex; // If interface information can get gotten, use it. if (GetIfEntry(&iface) == NO_ERROR) { entries[entryCount].header.length = iface.dwPhysAddrLen; entries[entryCount].header.type = TLV_TYPE_MAC_ADDR; entries[entryCount].buffer = (PUCHAR)iface.bPhysAddr; entryCount++; if (iface.bDescr) { entries[entryCount].header.length = iface.dwDescrLen + 1; entries[entryCount].header.type = TLV_TYPE_MAC_NAME; entries[entryCount].buffer = (PUCHAR)iface.bDescr; entryCount++; } } // Add the interface group packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, entryCount); } } while (0); if (table) free(table); #else struct iface *ifaces; int count; int i; int if_error; Tlv entries[4]; if_error = get_ifaces(&ifaces, &count); if (if_error) { result = if_error; } else { for (i = 0; i < count; i++) { entries[0].header.length = strlen(ifaces[i].name)+1; entries[0].header.type = TLV_TYPE_MAC_NAME; entries[0].buffer = (PUCHAR)ifaces[i].name; entries[1].header.length = 6; entries[1].header.type = TLV_TYPE_MAC_ADDR; entries[1].buffer = (PUCHAR)ifaces[i].hwaddr; entries[2].header.length = ifaces[i].addr_size; entries[2].header.type = TLV_TYPE_IP; entries[2].buffer = (PUCHAR)ifaces[i].addr; entries[3].header.length = ifaces[i].addr_size; entries[3].header.type = TLV_TYPE_NETMASK; entries[3].buffer = (PUCHAR)ifaces[i].netmask; packet_add_tlv_group(response, TLV_TYPE_NETWORK_INTERFACE, entries, 4); } } if (ifaces) free_ifaces(ifaces, count); #endif // Transmit the response if valid packet_transmit_response(result, remote, response); return result; }
/* * Scan for interfaces, and work out which one the user wanted to use. */ int artnet_net_init(node n, const char *preferred_ip) { iface_t *ift, *ift_head = NULL; struct in_addr wanted_ip; int found = FALSE; int i; int ret = ARTNET_EOK; if ((ret = get_ifaces(&ift_head))) goto e_return; if (n->state.verbose) { printf("#### INTERFACES FOUND ####\n"); for (ift = ift_head; ift != NULL; ift = ift->next) { printf("IP: %s\n", inet_ntoa(ift->ip_addr.sin_addr)); printf(" bcast: %s\n" , inet_ntoa(ift->bcast_addr.sin_addr)); printf(" hwaddr: "); for (i = 0; i < ARTNET_MAC_SIZE; i++) { if (i) printf(":"); printf("%02x", (uint8_t) ift->hw_addr[i]); } printf("\n"); } printf("#########################\n"); } if (preferred_ip) { // search through list of interfaces for one with the correct address ret = artnet_net_inet_aton(preferred_ip, &wanted_ip); if (ret) goto e_cleanup; for (ift = ift_head; ift != NULL; ift = ift->next) { if (ift->ip_addr.sin_addr.s_addr == wanted_ip.s_addr) { found = TRUE; n->state.ip_addr = ift->ip_addr.sin_addr; n->state.bcast_addr = ift->bcast_addr.sin_addr; memcpy(&n->state.hw_addr, &ift->hw_addr, ARTNET_MAC_SIZE); break; } } if (!found) { artnet_error("Cannot find interface by ip %s", preferred_ip); ret = ARTNET_ENET; goto e_cleanup; } } else { if (ift_head) { // pick first address // copy ip address, bcast address and hardware address n->state.ip_addr = ift_head->ip_addr.sin_addr; n->state.bcast_addr = ift_head->bcast_addr.sin_addr; memcpy(&n->state.hw_addr, &ift_head->hw_addr, ARTNET_MAC_SIZE); } else { artnet_error("No interfaces found!"); ret = ARTNET_ENET; } } e_cleanup: free_ifaces(ift_head); e_return : return ret; }
int main(int argc, char *argv[]) { int c; int log_method = L_STDERR_SYSLOG; char *logfile = PATH_RADVD_LOG; int facility = LOG_FACILITY; char *username = NULL; char *chrootdir = NULL; int configtest = 0; int daemonize = 1; char const *pname = ((pname = strrchr(argv[0], '/')) != NULL) ? pname + 1 : argv[0]; srand((unsigned int)time(NULL)); char const *conf_path = PATH_RADVD_CONF; char const *daemon_pid_file_ident = PATH_RADVD_PID; /* parse args */ #define OPTIONS_STR "d:C:l:m:p:t:u:vhcn" #ifdef HAVE_GETOPT_LONG int opt_idx; while ((c = getopt_long(argc, argv, OPTIONS_STR, prog_opt, &opt_idx)) > 0) #else while ((c = getopt(argc, argv, OPTIONS_STR)) > 0) #endif { switch (c) { case 'C': conf_path = optarg; break; case 'd': set_debuglevel(atoi(optarg)); break; case 'f': facility = atoi(optarg); break; case 'l': logfile = optarg; break; case 'p': daemon_pid_file_ident = optarg; break; case 'm': if (!strcmp(optarg, "syslog")) { log_method = L_SYSLOG; } else if (!strcmp(optarg, "stderr_syslog")) { log_method = L_STDERR_SYSLOG; } else if (!strcmp(optarg, "stderr")) { log_method = L_STDERR; } else if (!strcmp(optarg, "logfile")) { log_method = L_LOGFILE; } else if (!strcmp(optarg, "none")) { log_method = L_NONE; } else { fprintf(stderr, "%s: unknown log method: %s\n", pname, optarg); exit(1); } break; case 't': chrootdir = strdup(optarg); break; case 'u': username = strdup(optarg); break; case 'v': version(); break; case 'c': configtest = 1; break; case 'n': daemonize = 0; break; case 'h': usage(pname); #ifdef HAVE_GETOPT_LONG case ':': fprintf(stderr, "%s: option %s: parameter expected\n", pname, prog_opt[opt_idx].name); exit(1); #endif case '?': exit(1); } } /* TODO: Seems like this chroot'ing should happen *after* daemonizing for * the sake of the PID file. */ if (chrootdir) { if (!username) { fprintf(stderr, "Chroot as root is not safe, exiting\n"); exit(1); } if (chroot(chrootdir) == -1) { perror("chroot"); exit(1); } if (chdir("/") == -1) { perror("chdir"); exit(1); } /* username will be switched later */ } if (configtest) { set_debuglevel(1); log_method = L_STDERR; } if (log_open(log_method, pname, logfile, facility) < 0) { perror("log_open"); exit(1); } if (!configtest) { flog(LOG_INFO, "version %s started", VERSION); } /* check that 'other' cannot write the file * for non-root, also that self/own group can't either */ if (check_conffile_perm(username, conf_path) != 0) { if (get_debuglevel() == 0) { flog(LOG_ERR, "exiting, permissions on conf_file invalid"); exit(1); } else flog(LOG_WARNING, "Insecure file permissions, but continuing anyway"); } /* parse config file */ struct Interface *ifaces = NULL; if ((ifaces = readin_config(conf_path)) == 0) { flog(LOG_ERR, "exiting, failed to read config file"); exit(1); } if (configtest) { free_ifaces(ifaces); exit(0); } /* get a raw socket for sending and receiving ICMPv6 messages */ int sock = open_icmpv6_socket(); if (sock < 0) { perror("open_icmpv6_socket"); exit(1); } /* if we know how to do it, check whether forwarding is enabled */ if (check_ip6_forwarding()) { flog(LOG_WARNING, "IPv6 forwarding seems to be disabled, but continuing anyway"); } int const pidfd = open_and_lock_pid_file(daemon_pid_file_ident); /* * okay, config file is read in, socket and stuff is setup, so * lets fork now... */ if (daemonize) { pid_t pid = do_daemonize(log_method, daemon_pid_file_ident); if (pid != 0 && pid != -1) { /* We want to see clean output from valgrind, so free username, chrootdir, * and ifaces in the child process. */ if (ifaces) free_ifaces(ifaces); if (username) free(username); if (chrootdir) free(chrootdir); exit(0); } } else { if (0 != write_pid_file(daemon_pid_file_ident, getpid())) { flog(LOG_ERR, "failure writing pid file detected"); exit(-1); } } check_pid_file(daemon_pid_file_ident); #ifdef __linux__ /* for privsep */ { dlog(LOG_DEBUG, 3, "initializing privsep"); int pipefds[2]; if (pipe(pipefds) != 0) { flog(LOG_ERR, "Couldn't create privsep pipe."); return -1; } pid_t pid = fork(); if (pid == -1) { flog(LOG_ERR, "Couldn't fork for privsep."); return -1; } if (pid == 0) { /* We want to see clean output from valgrind, so free username, chrootdir, * and ifaces in the child process. */ if (ifaces) free_ifaces(ifaces); if (username) free(username); if (chrootdir) free(chrootdir); close(pipefds[1]); privsep_init(pipefds[0]); _exit(0); } dlog(LOG_DEBUG, 3, "radvd privsep PID is %d", pid); /* Continue execution (will drop privileges soon) */ close(pipefds[0]); privsep_set_write_fd(pipefds[1]); } #endif if (username) { if (drop_root_privileges(username) < 0) { perror("drop_root_privileges"); flog(LOG_ERR, "unable to drop root privileges"); exit(1); } dlog(LOG_DEBUG, 3, "running as user: %s", username); } setup_ifaces(sock, ifaces); ifaces = main_loop(sock, ifaces, conf_path); stop_adverts(sock, ifaces); flog(LOG_INFO, "removing %s", daemon_pid_file_ident); unlink(daemon_pid_file_ident); close(pidfd); if (ifaces) free_ifaces(ifaces); if (chrootdir) free(chrootdir); if (username) free(username); flog(LOG_INFO, "returning from radvd main"); log_close(); return 0; }
int main(int argc, char **argv) { bool fork_desired = TRUE; bool log_to_stderr_desired = FALSE; bool nat_traversal = FALSE; bool nat_t_spf = TRUE; /* support port floating */ unsigned int keep_alive = 0; bool force_keepalive = FALSE; char *virtual_private = NULL; int lockfd; #ifdef CAPABILITIES int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE }; #endif /* CAPABILITIES */ /* initialize library and optionsfrom */ if (!library_init(NULL)) { library_deinit(); exit(SS_RC_LIBSTRONGSWAN_INTEGRITY); } if (!libhydra_init("pluto")) { libhydra_deinit(); library_deinit(); exit(SS_RC_INITIALIZATION_FAILED); } if (!pluto_init(argv[0])) { pluto_deinit(); libhydra_deinit(); library_deinit(); exit(SS_RC_DAEMON_INTEGRITY); } options = options_create(); /* 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' }, { "nocrsend", no_argument, NULL, 'c' }, { "strictcrlpolicy", no_argument, NULL, 'r' }, { "crlcheckinterval", required_argument, NULL, 'x'}, { "cachecrls", no_argument, NULL, 'C' }, { "uniqueids", no_argument, NULL, 'u' }, { "disableuniqreqids", no_argument, NULL, 'Z'}, { "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' }, { "policygroupsdir", required_argument, NULL, 'f' }, #ifdef USE_LWRES { "lwdnsq", required_argument, NULL, 'a' }, #else /* !USE_LWRES */ { "adns", required_argument, NULL, 'a' }, #endif /* !USE_LWRES */ { "pkcs11module", required_argument, NULL, 'm' }, { "pkcs11keepstate", no_argument, NULL, 'k' }, { "pkcs11initargs", required_argument, NULL, 'z' }, { "pkcs11proxy", no_argument, NULL, 'y' }, { "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-natt", no_argument, NULL, '5' }, { "virtual_private", required_argument, NULL, '6' }, #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_KERNEL + DBG_OFFSET }, { "debug-kernel", no_argument, NULL, DBG_KERNEL + 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 }, { "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("strongSwan "VERSION"%s\n", compile_time_interop_options); for (; *sp != NULL; sp++) puts(*sp); } exit_pluto(0); break; /* not actually reached */ case '+': /* --optionsfrom <filename> */ if (!options->from(options, optarg, &argc, &argv, optind)) { exit_pluto(1); } continue; case 'd': /* --nofork*/ fork_desired = FALSE; continue; case 'e': /* --stderrlog */ log_to_stderr_desired = TRUE; continue; case 'c': /* --nocrsend */ no_cr_send = TRUE; continue; case 'r': /* --strictcrlpolicy */ strict_crl_policy = 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 'C': /* --cachecrls */ cache_crls = TRUE; continue; case 'u': /* --uniqueids */ uniqueIDs = TRUE; continue; case 'Z': /* --disableuniqreqids */ disable_uniqreqids = 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': /* --policygroupsdir <policygroups-dir> */ policygroups_dir = optarg; continue; case 'a': /* --adns <pathname> */ pluto_adns_option = optarg; continue; case 'm': /* --pkcs11module <pathname> */ pkcs11_module_path = optarg; continue; case 'k': /* --pkcs11keepstate */ pkcs11_keep_state = TRUE; continue; case 'y': /* --pkcs11proxy */ pkcs11_proxy = TRUE; continue; case 'z': /* --pkcs11initargs */ pkcs11_init_args = 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; 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; 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(); 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; #else pfkey_debug_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); } } /* 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); } /* Redirect stdin, stdout and stderr to /dev/null */ { int fd; if ((fd = open("/dev/null", O_RDWR)) == -1) abort(); if (dup2(fd, 0) != 0) abort(); if (dup2(fd, 1) != 1) abort(); if (!log_to_stderr && dup2(fd, 2) != 2) abort(); close(fd); } init_constants(); init_log("pluto"); /* Note: some scripts may look for this exact message -- don't change * ipsec barf was one, but it no longer does. */ plog("Starting IKEv1 pluto daemon (strongSwan "VERSION")%s", compile_time_interop_options); if (lib->integrity) { plog("integrity tests enabled:"); plog("lib 'libstrongswan': passed file and segment integrity tests"); plog("lib 'libhydra': passed file and segment integrity tests"); plog("daemon 'pluto': passed file integrity test"); } /* load plugins, further infrastructure may need it */ if (!lib->plugins->load(lib->plugins, NULL, lib->settings->get_str(lib->settings, "pluto.load", PLUGINS))) { exit(SS_RC_INITIALIZATION_FAILED); } print_plugins(); init_builder(); if (!init_secret() || !init_crypto()) { plog("initialization failed - aborting pluto"); exit_pluto(SS_RC_INITIALIZATION_FAILED); } init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf); init_virtual_ip(virtual_private); scx_init(pkcs11_module_path, pkcs11_init_args); init_states(); init_demux(); init_kernel(); init_adns(); init_myid(); fetch_initialize(); ac_initialize(); whack_attribute_initialize(); /* drop unneeded capabilities and change UID/GID */ prctl(PR_SET_KEEPCAPS, 1); #ifdef IPSEC_GROUP { struct group group, *grp; char buf[1024]; if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 || grp == NULL || setgid(grp->gr_gid) != 0) { plog("unable to change daemon group"); abort(); } } #endif #ifdef IPSEC_USER { struct passwd passwd, *pwp; char buf[1024]; if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 || pwp == NULL || setuid(pwp->pw_uid) != 0) { plog("unable to change daemon user"); abort(); } } #endif #ifdef CAPABILITIES_LIBCAP { cap_t caps; caps = cap_init(); cap_set_flag(caps, CAP_EFFECTIVE, countof(keep), keep, CAP_SET); cap_set_flag(caps, CAP_INHERITABLE, countof(keep), keep, CAP_SET); cap_set_flag(caps, CAP_PERMITTED, countof(keep), keep, CAP_SET); if (cap_set_proc(caps) != 0) { plog("unable to drop daemon capabilities"); abort(); } cap_free(caps); } #endif /* CAPABILITIES_LIBCAP */ #ifdef CAPABILITIES_NATIVE { struct __user_cap_data_struct caps = { .effective = 0 }; struct __user_cap_header_struct header = { .version = _LINUX_CAPABILITY_VERSION, }; int i; for (i = 0; i < countof(keep); i++) { caps.effective |= 1 << keep[i]; caps.permitted |= 1 << keep[i]; caps.inheritable |= 1 << keep[i]; } if (capset(&header, &caps) != 0) { plog("unable to drop daemon capabilities"); abort(); } } #endif /* CAPABILITIES_NATIVE */ /* loading X.509 CA certificates */ load_authcerts("ca", CA_CERT_PATH, X509_CA); /* loading X.509 AA certificates */ load_authcerts("aa", AA_CERT_PATH, X509_AA); /* loading X.509 OCSP certificates */ load_authcerts("ocsp", OCSP_CERT_PATH, X509_OCSP_SIGNER); /* loading X.509 CRLs */ load_crls(); /* loading attribute certificates (experimental) */ ac_load_certs(); lib->processor->set_threads(lib->processor, lib->settings->get_int(lib->settings, "pluto.threads", DEFAULT_THREADS)); daily_log_event(); call_server(); return -1; /* Shouldn't ever reach this */ } /* leave pluto, with status. * Once child is launched, parent must not exit this way because * the lock would be released. * * 0 OK * 1 general discomfort * 10 lock file exists */ void exit_pluto(int status) { lib->processor->set_threads(lib->processor, 0); reset_globals(); /* needed because we may be called in odd state */ free_preshared_secrets(); free_remembered_public_keys(); delete_every_connection(); whack_attribute_finalize(); /* free in-memory pools */ kernel_finalize(); fetch_finalize(); /* stop fetching thread */ free_crl_fetch(); /* free chain of crl fetch requests */ free_ocsp_fetch(); /* free chain of ocsp fetch requests */ free_authcerts(); /* free chain of X.509 authority certificates */ free_crls(); /* free chain of X.509 CRLs */ free_ca_infos(); /* free chain of X.509 CA information records */ free_ocsp(); /* free ocsp cache */ free_ifaces(); ac_finalize(); /* free X.509 attribute certificates */ scx_finalize(); /* finalize and unload PKCS #11 module */ stop_adns(); free_md_pool(); free_crypto(); free_myid(); /* free myids */ free_events(); /* free remaining events */ free_vendorid(); /* free all vendor id records */ free_builder(); delete_lock(); options->destroy(options); pluto_deinit(); lib->plugins->unload(lib->plugins); libhydra_deinit(); library_deinit(); close_log(); exit(status); }
/* * Set if_head to point to a list of iface_t structures which represent the * interfaces on this machine * @param ift_head the address of the pointer to the head of the list */ static int get_ifaces(iface_t **if_head) { struct ifconf ifc; struct ifreq *ifr, ifrcopy; struct sockaddr_in *sin; int len, lastlen, flags; char *buf, *ptr; iface_t *if_tail, *iface; int ret = ARTNET_EOK; int sd; *if_head = if_tail = NULL; // create socket to get iface config sd = socket(PF_INET, SOCK_DGRAM, 0); if (sd < 0) { artnet_error("%s : Could not create socket %s", __FUNCTION__, strerror(errno)); ret = ARTNET_ENET; goto e_return; } // first use ioctl to get a listing of interfaces lastlen = 0; len = INITIAL_IFACE_COUNT * sizeof(struct ifreq); for (;;) { buf = malloc(len); if (buf == NULL) { artnet_error_malloc(); ret = ARTNET_EMEM; goto e_free; } ifc.ifc_len = len; ifc.ifc_buf = buf; if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) { if (errno != EINVAL || lastlen != 0) { artnet_error("%s : ioctl error %s", __FUNCTION__, strerror(errno)); ret = ARTNET_ENET; goto e_free; } } else { if (ifc.ifc_len == lastlen) break; lastlen = ifc.ifc_len; } len += IFACE_COUNT_INC * sizeof(struct ifreq); free(buf); } // loop through each iface for (ptr = buf; ptr < buf + ifc.ifc_len;) { ifr = (struct ifreq*) ptr; // work out length here #ifdef HAVE_SOCKADDR_SA_LEN len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len); #else switch (ifr->ifr_addr.sa_family) { #ifdef IPV6 case AF_INET6: len = sizeof(struct sockaddr_in6); break; #endif case AF_INET: default: len = sizeof(SA); break; } #endif ptr += sizeof(ifr->ifr_name) + len; // look for AF_INET interfaces if (ifr->ifr_addr.sa_family == AF_INET) { ifrcopy = *ifr; if (ioctl(sd, SIOCGIFFLAGS, &ifrcopy) < 0) { artnet_error("%s : ioctl error %s" , __FUNCTION__, strerror(errno)); ret = ARTNET_ENET; goto e_free_list; } flags = ifrcopy.ifr_flags; if ((flags & IFF_UP) == 0) continue; //skip down interfaces if ((flags & IFF_LOOPBACK)) continue; //skip lookback iface = new_iface(if_head, &if_tail); if (!iface) goto e_free_list; sin = (struct sockaddr_in *) &ifr->ifr_addr; iface->ip_addr.sin_addr = sin->sin_addr; // fetch bcast address #ifdef SIOCGIFBRDADDR if (flags & IFF_BROADCAST) { if (ioctl(sd, SIOCGIFBRDADDR, &ifrcopy) < 0) { artnet_error("%s : ioctl error %s" , __FUNCTION__, strerror(errno)); ret = ARTNET_ENET; goto e_free_list; } sin = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr; iface->bcast_addr.sin_addr = sin->sin_addr; } #endif // fetch hardware address #ifdef SIOCGIFHWADDR if (flags & SIOCGIFHWADDR) { if (ioctl(sd, SIOCGIFHWADDR, &ifrcopy) < 0) { artnet_error("%s : ioctl error %s", __FUNCTION__, strerror(errno)); ret = ARTNET_ENET; goto e_free_list; } memcpy(&iface->hw_addr, ifrcopy.ifr_hwaddr.sa_data, ARTNET_MAC_SIZE); } #endif /* ok, if that all failed we should prob try and use sysctl to work out the bcast * and hware addresses * i'll leave that for another day */ } } free(buf); return ARTNET_EOK; e_free_list: free_ifaces(*if_head); e_free: free(buf); close(sd); e_return: return ret; }