void init_constants(void) { happy(anyaddr(AF_INET, &ipv4_any)); happy(anyaddr(AF_INET6, &ipv6_any)); happy(addrtosubnet(&ipv4_any, &ipv4_wildcard)); happy(addrtosubnet(&ipv6_any, &ipv6_wildcard)); happy(initsubnet(&ipv4_any, 0, '0', &ipv4_all)); happy(initsubnet(&ipv6_any, 0, '0', &ipv6_all)); }
/* Get a state object. * Caller must schedule an event for this object so that it doesn't leak. * Caller must insert_state(). */ struct state * new_state(void) { static const struct state blank_state; /* initialized all to zero & NULL */ static so_serial_t next_so = SOS_FIRST; struct state *st; st = clone_thing(blank_state, "struct state in new_state()"); st->st_serialno = next_so++; passert(next_so > SOS_FIRST); /* overflow can't happen! */ st->st_whack_sock = NULL_FD; anyaddr(AF_INET, &st->hidden_variables.st_nat_oa); anyaddr(AF_INET, &st->hidden_variables.st_natd); DBG(DBG_CONTROL, DBG_log("creating state object #%lu at %p" , st->st_serialno, (void *) st)); return st; }
void gcomm::AsioUdpSocket::connect(const gu::URI& uri) { gcomm_assert(state() == S_CLOSED); Critical<AsioProtonet> crit(net_); asio::ip::udp::resolver resolver(net_.io_service_); asio::ip::udp::resolver::query query(unescape_addr(uri.get_host()), uri.get_port()); asio::ip::udp::resolver::iterator conn_i(resolver.resolve(query)); target_ep_ = conn_i->endpoint(); socket_.open(conn_i->endpoint().protocol()); socket_.set_option(asio::ip::udp::socket::reuse_address(true)); socket_.set_option(asio::ip::udp::socket::linger(true, 1)); set_fd_options(socket_); asio::ip::udp::socket::non_blocking_io cmd(true); socket_.io_control(cmd); const std::string if_addr( unescape_addr( uri.get_option("socket.if_addr", anyaddr(conn_i->endpoint().address())))); asio::ip::address local_if(asio::ip::address::from_string(if_addr)); if (is_multicast(conn_i->endpoint()) == true) { join_group(socket_, conn_i->endpoint(), local_if); socket_.set_option( asio::ip::multicast::enable_loopback( gu::from_string<bool>(uri.get_option("socket.if_loop", "false")))); socket_.set_option( asio::ip::multicast::hops( gu::from_string<int>(uri.get_option("socket.mcast_ttl", "1")))); socket_.bind(*conn_i); } else { socket_.bind( asio::ip::udp::endpoint( local_if, gu::from_string<unsigned short>(uri.get_port()))); } async_receive(); state_ = S_CONNECTED; }
int main(int argc, char **argv) { /* int fd; */ char *endptr; /* int ret; */ int c; const char* error_s; int error = 0; char ipaddr_txt[ADDRTOT_BUF]; struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg; ip_address pfkey_address_s_ska; /*struct sockaddr_in pfkey_address_d_ska;*/ ip_address pfkey_address_sflow_ska; ip_address pfkey_address_dflow_ska; ip_address pfkey_address_smask_ska; ip_address pfkey_address_dmask_ska; int transport_proto = 0; int src_port = 0; int dst_port = 0; ip_said said; ip_subnet s_subnet, d_subnet; int eroute_af = 0; int said_af = 0; int sa_flags=0; int argcount = argc; progname = argv[0]; memset(&pfkey_address_s_ska, 0, sizeof(ip_address)); memset(&pfkey_address_sflow_ska, 0, sizeof(ip_address)); memset(&pfkey_address_dflow_ska, 0, sizeof(ip_address)); memset(&pfkey_address_smask_ska, 0, sizeof(ip_address)); memset(&pfkey_address_dmask_ska, 0, sizeof(ip_address)); memset(&said, 0, sizeof(ip_said)); memset(&s_subnet, 0, sizeof(ip_subnet)); memset(&d_subnet, 0, sizeof(ip_subnet)); eroute_af_opt = said_af_opt = edst_opt = spi_opt = proto_opt = said_opt = dst_opt = src_opt = NULL; while((c = getopt_long(argc, argv, ""/*"acdD:e:i:hprs:S:f:vl:+:g"*/, longopts, 0)) != EOF) { switch(c) { case 'g': debug = 1; pfkey_lib_debug = PF_KEY_DEBUG_PARSE_MAX; argcount--; break; case 'a': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_SETEROUTE; break; case 'A': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_INEROUTE; break; case 'r': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_REPLACEROUTE; break; case 'E': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_INREPLACEROUTE; break; case 'c': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_CLREROUTE; break; case 'd': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_DELEROUTE; break; case 'e': if(said_opt) { fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit (1); } if(edst_opt) { fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined as:%s\n", progname, optarg, edst_opt); exit (1); } error_s = ttoaddr(optarg, 0, said_af, &said.dst); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --edst argument:%s\n", progname, error_s, optarg); exit (1); } edst_opt = optarg; break; case 'h': case '?': usage(progname); exit(1); case 's': if(said_opt) { fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit (1); } if(spi_opt) { fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined as:%s\n", progname, optarg, spi_opt); exit (1); } said.spi = htonl(strtoul(optarg, &endptr, 0)); if(!(endptr == optarg + strlen(optarg))) { fprintf(stderr, "%s: Invalid character in SPI parameter: %s\n", progname, optarg); exit (1); } if(ntohl(said.spi) < 0x100) { fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than 0x100.\n", progname, optarg, ntohl(said.spi)); exit(1); } spi_opt = optarg; break; case 'p': if(said_opt) { fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit (1); } if(proto_opt) { fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined as:%s\n", progname, optarg, proto_opt); exit (1); } #if 0 if(said.proto) { fprintf(stderr, "%s: Warning, PROTO parameter redefined:%s\n", progname, optarg); exit (1); } #endif if(!strcmp(optarg, "ah")) said.proto = SA_AH; if(!strcmp(optarg, "esp")) said.proto = SA_ESP; if(!strcmp(optarg, "tun")) said.proto = SA_IPIP; if(!strcmp(optarg, "comp")) said.proto = SA_COMP; if(said.proto == 0) { fprintf(stderr, "%s: Invalid PROTO parameter: %s\n", progname, optarg); exit (1); } proto_opt = optarg; break; case 'I': if(said_opt) { fprintf(stderr, "%s: Error, SAID parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit (1); } if(proto_opt) { fprintf(stderr, "%s: Error, PROTO parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, proto_opt); exit (1); } if(edst_opt) { fprintf(stderr, "%s: Error, EDST parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, edst_opt); exit (1); } if(spi_opt) { fprintf(stderr, "%s: Error, SPI parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, spi_opt); exit (1); } if(said_af_opt) { fprintf(stderr, "%s: Error, address family parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, said_af_opt); exit (1); } error_s = ttosa(optarg, 0, &said); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n", progname, error_s, optarg); exit (1); } else if(ntohl(said.spi) < 0x100){ fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than or equal to 0x100.\n", progname, optarg, said.spi); exit(1); } said_af = addrtypeof(&said.dst); said_opt = optarg; break; case 'v': fprintf(stdout, "%s %s\n", me, ipsec_version_code()); fprintf(stdout, "See `ipsec --copyright' for copyright information.\n"); exit(1); case 'D': if(dst_opt) { fprintf(stderr, "%s: Error, --dst parameter redefined:%s, already defined as:%s\n", progname, optarg, dst_opt); exit (1); } error_s = ttosubnet(optarg, 0, eroute_af, &d_subnet); if (error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --dst argument: %s\n", progname, error_s, optarg); exit (1); } dst_opt = optarg; break; case 'S': if(src_opt) { fprintf(stderr, "%s: Error, --src parameter redefined:%s, already defined as:%s\n", progname, optarg, src_opt); exit (1); } error_s = ttosubnet(optarg, 0, eroute_af, &s_subnet); if (error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --src argument: %s\n", progname, error_s, optarg); exit (1); } src_opt = optarg; break; case 'P': if (transport_proto_opt) { fprintf(stderr, "%s: Error, --transport-proto" " parameter redefined:%s, " "already defined as:%s\n", progname, optarg, transport_proto_opt); exit(1); } transport_proto_opt = optarg; break; case 'Q': if (src_port_opt) { fprintf(stderr, "%s: Error, --src-port" " parameter redefined:%s, " "already defined as:%s\n", progname, optarg, src_port_opt); exit(1); } src_port_opt = optarg; break; case 'R': if (dst_port_opt) { fprintf(stderr, "%s: Error, --dst-port" " parameter redefined:%s, " "already defined as:%s\n", progname, optarg, dst_port_opt); exit(1); } dst_port_opt = optarg; break; case 'l': progname = malloc(strlen(argv[0]) + 10 /* update this when changing the sprintf() */ + strlen(optarg)); sprintf(progname, "%s --label %s", argv[0], optarg); argcount -= 2; break; case 'i': /* specifies the address family of the SAID, stored in said_af */ if(said_af_opt) { fprintf(stderr, "%s: Error, address family of SAID redefined:%s, already defined as:%s\n", progname, optarg, said_af_opt); exit (1); } if(!strcmp(optarg, "inet")) said_af = AF_INET; if(!strcmp(optarg, "inet6")) said_af = AF_INET6; if(said_af == 0) { fprintf(stderr, "%s: Invalid address family parameter for SAID: %s\n", progname, optarg); exit (1); } said_af_opt = optarg; break; case 'f': /* specifies the address family of the eroute, stored in eroute_af */ if(eroute_af_opt) { fprintf(stderr, "%s: Error, address family of eroute redefined:%s, already defined as:%s\n", progname, optarg, eroute_af_opt); exit (1); } if(!strcmp(optarg, "inet")) eroute_af = AF_INET; if(!strcmp(optarg, "inet6")) eroute_af = AF_INET6; if(eroute_af == 0) { fprintf(stderr, "%s: Invalid address family parameter for eroute: %s\n", progname, optarg); exit (1); } eroute_af_opt = optarg; break; case '+': /* optionsfrom */ optionsfrom(optarg, &argc, &argv, optind, stderr); /* no return on error */ break; default: break; } } if(debug) { fprintf(stdout, "%s: DEBUG: argc=%d\n", progname, argc); } if(argcount == 1) { struct stat sts; if ( ((stat ("/proc/net/pfkey", &sts)) == 0) ) { fprintf(stderr, "%s: NETKEY does not support eroute table.\n",progname); exit(1); } else { int ret = 1; if ((stat ("/proc/net/ipsec_eroute", &sts)) != 0) { fprintf(stderr, "%s: No eroute table - no IPsec support in kernel (are the modules loaded?)\n", progname); } else { ret = system("cat /proc/net/ipsec_eroute"); ret = ret != -1 && WIFEXITED(ret) ? WEXITSTATUS(ret) : 1; } exit(ret); } } /* Sanity checks */ if(debug) { fprintf(stdout, "%s: DEBUG: action_type=%d\n", progname, action_type); } if (transport_proto_opt != 0) { struct protoent * proto = getprotobyname(transport_proto_opt); if (proto != 0) { transport_proto = proto->p_proto; } else { transport_proto = strtoul(transport_proto_opt, &endptr, 0); if ((*endptr != '\0') || (transport_proto == 0 && endptr == transport_proto_opt)) { fprintf(stderr, "%s: Invalid character in --transport-proto parameter: %s\n", progname, transport_proto_opt); exit (1); } if (transport_proto > 255) { fprintf(stderr, "%s: --transport-proto parameter: %s must be in the range 0 to 255 inclusive\n", progname, transport_proto_opt); exit (1); } } } if (src_port_opt != 0 || dst_port_opt != 0) { switch (transport_proto) { case IPPROTO_UDP: case IPPROTO_TCP: break; default: fprintf(stderr, "%s: --transport-proto with either UDP or TCP must be specified if --src-port or --dst-port is used\n", progname); exit(1); } } if (src_port_opt) { struct servent * ent = getservbyname(src_port_opt, 0); if (ent != 0) { src_port = ent->s_port; } else { src_port = strtoul(src_port_opt, &endptr, 0); if ((*endptr != '\0') || (src_port == 0 && endptr == src_port_opt)) { fprintf(stderr, "%s: Invalid character in --src-port parameter: %s\n", progname, src_port_opt); exit (1); } if (src_port > 65535) { fprintf(stderr, "%s: --src-port parameter: %s must be in the range 0 to 65535 inclusive\n", progname, src_port_opt); } src_port = htons(src_port); } } if (dst_port_opt) { struct servent * ent = getservbyname(dst_port_opt, 0); if (ent != 0) { dst_port = ent->s_port; } else { dst_port = strtoul(dst_port_opt, &endptr, 0); if ((*endptr != '\0') || (dst_port == 0 && endptr == dst_port_opt)) { fprintf(stderr, "%s: Invalid character in --dst-port parameter: %s\n", progname, dst_port_opt); exit (1); } if (dst_port > 65535) { fprintf(stderr, "%s: --dst-port parameter: %s must be in the range 0 to 65535 inclusive\n", progname, dst_port_opt); } dst_port = htons(dst_port); } } switch(action_type) { case EMT_SETEROUTE: case EMT_REPLACEROUTE: case EMT_INEROUTE: case EMT_INREPLACEROUTE: if(!(said_af_opt && edst_opt && spi_opt && proto_opt) && !(said_opt)) { fprintf(stderr, "%s: add and addin options must have SA specified.\n", progname); exit(1); } case EMT_DELEROUTE: if(!src_opt) { fprintf(stderr, "%s: Error -- %s option '--src' is required.\n", progname, (action_type == EMT_SETEROUTE) ? "add" : "del"); exit(1); } if(!dst_opt) { fprintf(stderr, "%s: Error -- %s option '--dst' is required.\n", progname, (action_type == EMT_SETEROUTE) ? "add" : "del"); exit(1); } case EMT_CLREROUTE: break; default: fprintf(stderr, "%s: exactly one of '--add', '--addin', '--replace', '--del' or '--clear' options must be specified.\n" "Try %s --help' for usage information.\n", progname, progname); exit(1); } pfkey_sock = pfkey_open_sock_with_error(); if(pfkey_sock == -1) { exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: PFKEYv2 socket successfully openned=%d.\n", progname, pfkey_sock); } /* Build an SADB_X_ADDFLOW or SADB_X_DELFLOW message to send down. */ /* It needs <base, SA, address(SD), flow(SD), mask(SD)> minimum. */ pfkey_extensions_init(extensions); if((error = pfkey_msg_hdr_build(&extensions[0], (action_type == EMT_SETEROUTE || action_type == EMT_REPLACEROUTE || action_type == EMT_INREPLACEROUTE || action_type == EMT_INEROUTE) ? SADB_X_ADDFLOW : SADB_X_DELFLOW, proto2satype(said.proto), 0, ++pfkey_seq, getpid()))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_msg_hdr_build successfull.\n", progname); } switch(action_type) { case EMT_CLREROUTE: sa_flags = SADB_X_SAFLAGS_CLEARFLOW; goto sa_build; case EMT_REPLACEROUTE: sa_flags = SADB_X_SAFLAGS_REPLACEFLOW; goto sa_build; case EMT_INREPLACEROUTE: sa_flags = SADB_X_SAFLAGS_REPLACEFLOW | SADB_X_SAFLAGS_INFLOW; goto sa_build; case EMT_INEROUTE: sa_flags = SADB_X_SAFLAGS_INFLOW; goto sa_build; case EMT_SETEROUTE: sa_build: if((error = pfkey_sa_build(&extensions[SADB_EXT_SA], SADB_EXT_SA, said.spi, /* in network order */ 0, 0, 0, 0, sa_flags))) { fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_sa_build successful.\n", progname); } default: break; } switch(action_type) { case EMT_SETEROUTE: case EMT_REPLACEROUTE: case EMT_INEROUTE: case EMT_INREPLACEROUTE: anyaddr(said_af, &pfkey_address_s_ska); if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, 0, sockaddrof(&pfkey_address_s_ska)))) { addrtot(&pfkey_address_s_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src.\n", progname); } if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, 0, sockaddrof(&said.dst)))) { addrtot(&said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst.\n", progname); } default: break; } switch(action_type) { case EMT_SETEROUTE: case EMT_REPLACEROUTE: case EMT_INEROUTE: case EMT_INREPLACEROUTE: case EMT_DELEROUTE: networkof(&s_subnet, &pfkey_address_sflow_ska); /* src flow */ add_port(eroute_af, &pfkey_address_sflow_ska, src_port); if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_SRC_FLOW], SADB_X_EXT_ADDRESS_SRC_FLOW, 0, 0, sockaddrof(&pfkey_address_sflow_ska)))) { addrtot(&pfkey_address_sflow_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_sflow extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src flow.\n", progname); } networkof(&d_subnet, &pfkey_address_dflow_ska); /* dst flow */ add_port(eroute_af, &pfkey_address_dflow_ska, dst_port); if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_DST_FLOW], SADB_X_EXT_ADDRESS_DST_FLOW, 0, 0, sockaddrof(&pfkey_address_dflow_ska)))) { addrtot(&pfkey_address_dflow_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_dflow extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst flow.\n", progname); } maskof(&s_subnet, &pfkey_address_smask_ska); /* src mask */ add_port(eroute_af, &pfkey_address_smask_ska, src_port ? ~0:0); if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_SRC_MASK], SADB_X_EXT_ADDRESS_SRC_MASK, 0, 0, sockaddrof(&pfkey_address_smask_ska)))) { addrtot(&pfkey_address_smask_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_smask extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src mask.\n", progname); } maskof(&d_subnet, &pfkey_address_dmask_ska); /* dst mask */ add_port(eroute_af, &pfkey_address_dmask_ska, dst_port ? ~0:0); if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_DST_MASK], SADB_X_EXT_ADDRESS_DST_MASK, 0, 0, sockaddrof(&pfkey_address_dmask_ska)))) { addrtot(&pfkey_address_dmask_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_dmask extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst mask.\n", progname); } } if (transport_proto != 0) { if ((error = pfkey_x_protocol_build(&extensions[SADB_X_EXT_PROTOCOL], transport_proto))) { fprintf(stderr, "%s: Trouble building transport" " protocol extension, error=%d.\n", progname, error); exit(1); } } if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) { fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n", progname, error); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_msg_build successful.\n", progname); } if((error = write(pfkey_sock, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) { fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n", progname, error, errno); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); switch(errno) { case EINVAL: fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n"); break; case ENXIO: if((action_type == EMT_SETEROUTE) || (action_type == EMT_REPLACEROUTE)) { fprintf(stderr, "Invalid mask.\n"); break; } if(action_type == EMT_DELEROUTE) { fprintf(stderr, "Mask not found.\n"); break; } case EFAULT: if((action_type == EMT_SETEROUTE) || (action_type == EMT_REPLACEROUTE)) { fprintf(stderr, "Invalid address.\n"); break; } if(action_type == EMT_DELEROUTE) { fprintf(stderr, "Address not found.\n"); break; } case EACCES: fprintf(stderr, "access denied. "); if(getuid() == 0) { fprintf(stderr, "Check permissions. Should be 600.\n"); } else { fprintf(stderr, "You must be root to open this file.\n"); } break; case EUNATCH: fprintf(stderr, "KLIPS not loaded.\n"); break; case EBUSY: fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. Please report as much detail as possible to development team.\n"); break; case ENODEV: fprintf(stderr, "KLIPS not loaded or enabled.\n"); fprintf(stderr, "No device?!?\n"); break; case ENOBUFS: fprintf(stderr, "No kernel memory to allocate SA.\n"); break; case ESOCKTNOSUPPORT: fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n"); break; case EEXIST: fprintf(stderr, "eroute already in use. Delete old one first.\n"); break; case ENOENT: if(action_type == EMT_INEROUTE || action_type == EMT_INREPLACEROUTE) { fprintf(stderr, "non-existant IPIP SA.\n"); break; } fprintf(stderr, "eroute doesn't exist. Can't delete.\n"); break; case ENOSPC: fprintf(stderr, "no room in kernel SAref table. Cannot process request.\n"); break; case ESPIPE: fprintf(stderr, "kernel SAref table internal error. Cannot process request.\n"); break; default: fprintf(stderr, "Unknown socket write error %d. Please report as much detail as possible to development team.\n", errno); } /* fprintf(stderr, "%s: socket write returned errno %d\n", progname, errno);*/ exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey write successful.\n", progname); } if(pfkey_msg) { pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); } (void) close(pfkey_sock); /* close the socket */ if(debug) { fprintf(stdout, "%s: DEBUG: write ok\n", progname); } exit(0); }
static void default_values(starter_config_t *cfg) { if (cfg == NULL) return; memset(cfg, 0, sizeof(struct starter_config)); /* is there enough space for all seen flags? */ assert(KW_SETUP_LAST - KW_SETUP_FIRST < sizeof(cfg->setup.seen) * BITS_PER_BYTE); assert(KW_CONN_LAST - KW_CONN_FIRST < sizeof(cfg->conn_default.seen) * BITS_PER_BYTE); assert(KW_END_LAST - KW_END_FIRST < sizeof(cfg->conn_default.right.seen) * BITS_PER_BYTE); assert(KW_CA_LAST - KW_CA_FIRST < sizeof(cfg->ca_default.seen) * BITS_PER_BYTE); cfg->setup.seen = LEMPTY; cfg->setup.fragicmp = TRUE; cfg->setup.hidetos = TRUE; cfg->setup.uniqueids = TRUE; cfg->setup.interfaces = new_list("%defaultroute"); #ifdef START_CHARON cfg->setup.charonstart = TRUE; #endif #ifdef START_PLUTO cfg->setup.plutostart = TRUE; #endif cfg->setup.pluto_ikeport = IKE_UDP_PORT; cfg->setup.ha_seqdiff_in = 0xFFFFFFFF; cfg->setup.ha_seqdiff_out = 0xFFFFFFFF; cfg->conn_default.seen = LEMPTY; cfg->conn_default.startup = STARTUP_NO; cfg->conn_default.state = STATE_IGNORE; cfg->conn_default.policy = POLICY_ENCRYPT | POLICY_TUNNEL | POLICY_PUBKEY | POLICY_PFS | POLICY_MOBIKE; cfg->conn_default.ike = clone_str(ike_defaults); cfg->conn_default.esp = clone_str(esp_defaults); cfg->conn_default.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT; cfg->conn_default.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT; cfg->conn_default.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT; cfg->conn_default.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT; cfg->conn_default.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT; cfg->conn_default.addr_family = AF_INET; cfg->conn_default.tunnel_addr_family = AF_INET; cfg->conn_default.xfrm_flags = 0; cfg->conn_default.install_policy = TRUE; cfg->conn_default.dev = 0; cfg->conn_default.dpd_delay = 30; /* seconds */ cfg->conn_default.dpd_timeout = 150; /* seconds */ cfg->conn_default.left.seen = LEMPTY; cfg->conn_default.right.seen = LEMPTY; cfg->conn_default.left.sendcert = CERT_SEND_IF_ASKED; cfg->conn_default.right.sendcert = CERT_SEND_IF_ASKED; anyaddr(AF_INET, &cfg->conn_default.left.addr); anyaddr(AF_INET, &cfg->conn_default.left.nexthop); anyaddr(AF_INET, &cfg->conn_default.right.addr); anyaddr(AF_INET, &cfg->conn_default.right.nexthop); cfg->conn_default.left.ikeport = 500; cfg->conn_default.right.ikeport = 500; cfg->ca_default.seen = LEMPTY; }
static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token, kw_list_t *kw, char *conn_name, starter_config_t *cfg) { err_t ugh = NULL; bool assigned = FALSE; bool has_port_wildcard; /* set if port is %any */ char *name = kw->entry->name; char *value = kw->value; if (!assign_arg(token, KW_END_FIRST, kw, (char *)end, &assigned)) goto err; /* post processing of some keywords that were assigned automatically */ switch (token) { case KW_SUBNET: if ((strlen(value) >= 6 && strncmp(value,"vhost:",6) == 0) || (strlen(value) >= 5 && strncmp(value,"vnet:",5) == 0)) { /* used by pluto only */ end->has_virt = TRUE; } else { ip_subnet net; char *pos; int len = 0; end->has_client = TRUE; conn->tunnel_addr_family = ip_version(value); pos = strchr(value, ','); if (pos) { len = pos - value; } ugh = ttosubnet(value, len, ip_version(value), &net); if (ugh != NULL) { plog("# bad subnet: %s=%s [%s]", name, value, ugh); goto err; } } break; case KW_SOURCEIP: if (end->has_natip) { plog("# natip and sourceip cannot be defined at the same time"); goto err; } if (value[0] == '%') { if (streq(value, "%modeconfig") || streq(value, "%modecfg") || streq(value, "%config") || streq(value, "%cfg")) { /* request ip via config payload */ free(end->sourceip); end->sourceip = NULL; end->sourceip_mask = 1; } else { /* %poolname, strip %, serve ip requests */ free(end->sourceip); end->sourceip = clone_str(value+1); end->sourceip_mask = 0; } end->modecfg = TRUE; } else { char *pos; ip_address addr; ip_subnet net; conn->tunnel_addr_family = ip_version(value); pos = strchr(value, '/'); if (pos) { /* CIDR notation, address pool */ ugh = ttosubnet(value, 0, conn->tunnel_addr_family, &net); if (ugh != NULL) { plog("# bad subnet: %s=%s [%s]", name, value, ugh); goto err; } *pos = '\0'; free(end->sourceip); end->sourceip = clone_str(value); end->sourceip_mask = atoi(pos + 1); } else { /* fixed srcip */ ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr); if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); goto err; } end->sourceip_mask = (conn->tunnel_addr_family == AF_INET) ? 32 : 128; } } conn->policy |= POLICY_TUNNEL; break; case KW_SENDCERT: if (end->sendcert == CERT_YES_SEND) { end->sendcert = CERT_ALWAYS_SEND; } else if (end->sendcert == CERT_NO_SEND) { end->sendcert = CERT_NEVER_SEND; } break; default: break; } if (assigned) return; /* individual processing of keywords that were not assigned automatically */ switch (token) { case KW_HOST: if (streq(value, "%defaultroute")) { if (cfg->defaultroute.defined) { end->addr = cfg->defaultroute.addr; end->nexthop = cfg->defaultroute.nexthop; } else if (!cfg->defaultroute.supported) { plog("%%defaultroute not supported, fallback to %%any"); } else { plog("# default route not known: %s=%s", name, value); goto err; } } else if (streq(value, "%any") || streq(value, "%any4")) { anyaddr(conn->addr_family, &end->addr); } else if (streq(value, "%any6")) { conn->addr_family = AF_INET6; anyaddr(conn->addr_family, &end->addr); } else if (streq(value, "%group")) { ip_address any; conn->policy |= POLICY_GROUP | POLICY_TUNNEL; anyaddr(conn->addr_family, &end->addr); anyaddr(conn->tunnel_addr_family, &any); end->has_client = TRUE; } else { /* check for allow_any prefix */ if (value[0] == '%') { end->allow_any = TRUE; value++; } conn->addr_family = ip_version(value); ugh = ttoaddr(value, 0, conn->addr_family, &end->addr); if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); if (streq(ugh, "does not look numeric and name lookup failed")) { end->dns_failed = TRUE; anyaddr(conn->addr_family, &end->addr); } else { goto err; } } } break; case KW_NEXTHOP: if (streq(value, "%defaultroute")) { if (cfg->defaultroute.defined) { end->nexthop = cfg->defaultroute.nexthop; } else { plog("# default route not known: %s=%s", name, value); goto err; } } else if (streq(value, "%direct")) { ugh = anyaddr(conn->addr_family, &end->nexthop); } else { conn->addr_family = ip_version(value); ugh = ttoaddr(value, 0, conn->addr_family, &end->nexthop); } if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); goto err; } break; case KW_SUBNETWITHIN: { ip_subnet net; end->has_client = TRUE; end->has_client_wildcard = TRUE; conn->tunnel_addr_family = ip_version(value); ugh = ttosubnet(value, 0, ip_version(value), &net); if (ugh != NULL) { plog("# bad subnet: %s=%s [%s]", name, value, ugh); goto err; } end->subnet = clone_str(value); break; } case KW_PROTOPORT: ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &has_port_wildcard); end->has_port_wildcard = has_port_wildcard; break; case KW_NATIP: if (end->sourceip) { plog("# natip and sourceip cannot be defined at the same time"); goto err; } if (streq(value, "%defaultroute")) { char buf[64]; if (cfg->defaultroute.defined) { addrtot(&cfg->defaultroute.addr, 0, buf, sizeof(buf)); end->sourceip = clone_str(buf); } else { plog("# default route not known: %s=%s", name, value); goto err; } } else { ip_address addr; conn->tunnel_addr_family = ip_version(value); ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr); if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); goto err; } end->sourceip = clone_str(value); } end->has_natip = TRUE; conn->policy |= POLICY_TUNNEL; break; default: break; } return; err: plog(" bad argument value in conn '%s'", conn_name); cfg->err++; }
/** * Set up hardcoded defaults, from data in programs/pluto/constants.h * * @param cfg starter_config struct * @return void */ void ipsecconf_default_values(struct starter_config *cfg) { zero(cfg); /* ??? pointer fields might not be NULLed */ TAILQ_INIT(&cfg->conns); /* config setup */ cfg->setup.options[KBF_FRAGICMP] = FALSE; /* see sysctl_ipsec_icmp in ipsec_proc.c */ cfg->setup.options[KBF_HIDETOS] = TRUE; cfg->setup.options[KBF_PLUTORESTARTONCRASH] = TRUE; cfg->setup.options[KBF_PLUTOSTDERRLOGTIME] = TRUE; cfg->setup.options[KBF_PLUTOSTDERRLOGAPPEND] = TRUE; cfg->setup.options[KBF_UNIQUEIDS] = TRUE; cfg->setup.options[KBF_PERPEERLOG] = FALSE; cfg->setup.options[KBF_IKEPORT] = IKE_UDP_PORT; cfg->setup.options[KBF_NFLOG_ALL] = 0; /* disabled per default */ cfg->setup.options[KBF_XFRMLIFETIME] = 300; /* not used by pluto itself */ cfg->setup.options[KBF_NHELPERS] = -1; /* see also plutomain.c */ cfg->setup.options[KBF_KEEPALIVE] = 0; /* config setup */ cfg->setup.options[KBF_NATIKEPORT] = NAT_IKE_UDP_PORT; cfg->setup.options[KBF_DDOS_IKE_TRESHOLD] = DEFAULT_IKE_SA_DDOS_TRESHOLD; cfg->setup.options[KBF_MAX_HALFOPEN_IKE] = DEFAULT_MAXIMUM_HALFOPEN_IKE_SA; cfg->setup.options[KBF_SHUNTLIFETIME] = PLUTO_SHUNT_LIFE_DURATION_DEFAULT; /* Don't inflict BSI requirements on everyone */ cfg->setup.options[KBF_SEEDBITS] = 0; #ifdef HAVE_LABELED_IPSEC cfg->setup.options[KBF_SECCTX] = SECCTX; #endif cfg->setup.options[KBF_DDOS_MODE] = DDOS_AUTO; /* conn %default */ cfg->conn_default.options[KBF_NAT_KEEPALIVE] = TRUE; /* per conn */ cfg->conn_default.options[KBF_TYPE] = KS_TUNNEL; cfg->conn_default.options[KBF_INITIAL_CONTACT] = FALSE; cfg->conn_default.options[KBF_CISCO_UNITY] = FALSE; cfg->conn_default.options[KBF_SEND_VENDORID] = FALSE; cfg->conn_default.options[KBF_REMOTEPEERTYPE] = NON_CISCO; cfg->conn_default.options[KBF_SHA2_TRUNCBUG] = FALSE; cfg->conn_default.options[KBF_IKEPAD] = TRUE; cfg->conn_default.options[KBF_IKEV1_NATT] = natt_both; /* Network Manager support */ #ifdef HAVE_NM cfg->conn_default.options[KBF_NMCONFIGURED] = FALSE; #endif #ifdef HAVE_LABELED_IPSEC cfg->conn_default.options[KBF_LABELED_IPSEC] = FALSE; #endif cfg->conn_default.options[KBF_XAUTHBY] = XAUTHBY_FILE; cfg->conn_default.options[KBF_XAUTHFAIL] = XAUTHFAIL_HARD; cfg->conn_default.policy = POLICY_RSASIG | POLICY_TUNNEL | POLICY_ENCRYPT | POLICY_PFS; cfg->conn_default.policy |= POLICY_IKEV1_ALLOW | POLICY_IKEV2_ALLOW; /* ikev2=permit */ cfg->conn_default.policy |= POLICY_SAREF_TRACK; /* sareftrack=yes */ cfg->conn_default.policy |= POLICY_IKE_FRAG_ALLOW; /* ike_frag=yes */ cfg->conn_default.options[KBF_IKELIFETIME] = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT; cfg->conn_default.options[KBF_RETRANSMIT_TIMEOUT] = RETRANSMIT_TIMEOUT_DEFAULT; cfg->conn_default.options[KBF_RETRANSMIT_INTERVAL] = RETRANSMIT_INTERVAL_DEFAULT; cfg->conn_default.options[KBF_SALIFETIME] = SA_LIFE_DURATION_DEFAULT; cfg->conn_default.options[KBF_REKEYMARGIN] = SA_REPLACEMENT_MARGIN_DEFAULT; cfg->conn_default.options[KBF_REKEYFUZZ] = SA_REPLACEMENT_FUZZ_DEFAULT; cfg->conn_default.options[KBF_KEYINGTRIES] = SA_REPLACEMENT_RETRIES_DEFAULT; /* now here is a sticker.. we want it on. But pluto has to be smarter first */ cfg->conn_default.options[KBF_OPPOENCRYPT] = FALSE; cfg->conn_default.options[KBF_CONNADDRFAMILY] = AF_INET; cfg->conn_default.left.addr_family = AF_INET; anyaddr(AF_INET, &cfg->conn_default.left.addr); cfg->conn_default.left.nexttype = KH_NOTSET; anyaddr(AF_INET, &cfg->conn_default.left.nexthop); cfg->conn_default.right.addr_family = AF_INET; anyaddr(AF_INET, &cfg->conn_default.right.addr); cfg->conn_default.right.nexttype = KH_NOTSET; anyaddr(AF_INET, &cfg->conn_default.right.nexthop); /* default is NOT to look in DNS */ cfg->conn_default.left.key_from_DNS_on_demand = FALSE; cfg->conn_default.right.key_from_DNS_on_demand = FALSE; cfg->conn_default.options[KBF_AUTO] = STARTUP_IGNORE; cfg->conn_default.state = STATE_LOADED; cfg->ctlbase = clone_str(CTL_FILE, "default base"); }
static bool validate_end(struct ub_ctx *dnsctx , #endif struct starter_conn *conn_st, struct starter_end *end, const char *leftright, bool resolvip UNUSED, err_t *perr) { err_t er = NULL; char *err_str = NULL; int family = conn_st->options[KBF_CONNADDRFAMILY]; bool err = FALSE; # define ERR_FOUND(...) { err |= error_append(&err_str, __VA_ARGS__); } if (!end->options_set[KNCF_IP]) conn_st->state = STATE_INCOMPLETE; end->addrtype = end->options[KNCF_IP]; end->addr_family = family; /* validate the KSCF_IP/KNCF_IP */ switch (end->addrtype) { case KH_ANY: anyaddr(family, &(end->addr)); break; case KH_IFACE: /* generally, this doesn't show up at this stage */ starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_IFACE", leftright); break; case KH_IPADDR: assert(end->strings[KSCF_IP] != NULL); if (end->strings[KSCF_IP][0] == '%') { pfree(end->iface); end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface"); if (!starter_iface_find(end->iface, family, &end->addr, &end->nexthop)) conn_st->state = STATE_INVALID; /* not numeric, so set the type to the iface type */ end->addrtype = KH_IFACE; break; } er = ttoaddr_num(end->strings[KNCF_IP], 0, family, &(end->addr)); if (er != NULL) { /* not numeric, so set the type to the string type */ end->addrtype = KH_IPHOSTNAME; } if (end->id == NULL) { ipstr_buf b; end->id = clone_str(ipstr(&end->addr, &b), "end if"); } break; case KH_OPPO: conn_st->policy |= POLICY_OPPORTUNISTIC; break; case KH_OPPOGROUP: conn_st->policy |= POLICY_OPPORTUNISTIC | POLICY_GROUP; break; case KH_GROUP: conn_st->policy |= POLICY_GROUP; break; case KH_IPHOSTNAME: /* generally, this doesn't show up at this stage */ starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_IPHOSTNAME", leftright); break; case KH_DEFAULTROUTE: starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_DEFAULTROUTE", leftright); break; case KH_NOTSET: starter_log(LOG_LEVEL_DEBUG, "starter: %s is KH_NOTSET", leftright); break; } /* validate the KSCF_SUBNET */ if (end->strings_set[KSCF_SUBNET]) { char *value = end->strings[KSCF_SUBNET]; if (end->strings_set[KSCF_ADDRESSPOOL]) { ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", leftright, leftright); } if (startswith(value, "vhost:") || startswith(value, "vnet:")) { er = NULL; end->virt = clone_str(value, "validate_end item"); } else { end->has_client = TRUE; er = ttosubnet(value, 0, family, &(end->subnet)); } if (er != NULL) ERR_FOUND("bad subnet %ssubnet=%s [%s]", leftright, value, er); } /* set nexthop address to something consistent, by default */ anyaddr(family, &end->nexthop); anyaddr(addrtypeof(&end->addr), &end->nexthop); /* validate the KSCF_NEXTHOP */ if (end->strings_set[KSCF_NEXTHOP]) { char *value = end->strings[KSCF_NEXTHOP]; if (strcaseeq(value, "%defaultroute")) { end->nexttype = KH_DEFAULTROUTE; } else { if (tnatoaddr(value, strlen(value), AF_INET, &(end->nexthop)) != NULL && tnatoaddr(value, strlen(value), AF_INET6, &(end->nexthop)) != NULL) { #ifdef DNSSEC starter_log(LOG_LEVEL_DEBUG, "Calling unbound_resolve() for %snexthop value", leftright); if (!unbound_resolve(dnsctx, value, strlen(value), AF_INET, &(end->nexthop)) && !unbound_resolve(dnsctx, value, strlen(value), AF_INET6, &(end->nexthop))) ERR_FOUND("bad value for %snexthop=%s\n", leftright, value); #else er = ttoaddr(value, 0, family, &(end->nexthop)); if (er != NULL) ERR_FOUND("bad value for %snexthop=%s [%s]", leftright, value, er); #endif } end->nexttype = KH_IPADDR; } } else { #if 0 if (conn_st->policy & POLICY_OPPORTUNISTIC) end->nexttype = KH_DEFAULTROUTE; #endif anyaddr(family, &end->nexthop); if (end->addrtype == KH_DEFAULTROUTE) { end->nexttype = KH_DEFAULTROUTE; } } /* validate the KSCF_ID */ if (end->strings_set[KSCF_ID]) { char *value = end->strings[KSCF_ID]; pfreeany(end->id); end->id = clone_str(value, "end->id"); } if (end->options_set[KSCF_RSAKEY1]) { end->rsakey1_type = end->options[KSCF_RSAKEY1]; end->rsakey2_type = end->options[KSCF_RSAKEY2]; switch (end->options[KSCF_RSAKEY1]) { case PUBKEY_DNS: case PUBKEY_DNSONDEMAND: end->key_from_DNS_on_demand = TRUE; break; default: end->key_from_DNS_on_demand = FALSE; /* validate the KSCF_RSAKEY1/RSAKEY2 */ if (end->strings[KSCF_RSAKEY1] != NULL) { char *value = end->strings[KSCF_RSAKEY1]; pfreeany(end->rsakey1); end->rsakey1 = (unsigned char *)clone_str(value,"end->rsakey1"); } if (end->strings[KSCF_RSAKEY2] != NULL) { char *value = end->strings[KSCF_RSAKEY2]; pfreeany(end->rsakey2); end->rsakey2 = (unsigned char *)clone_str(value,"end->rsakey2"); } } } /* validate the KSCF_SOURCEIP, if any, and if set, * set the subnet to same value, if not set. */ if (end->strings_set[KSCF_SOURCEIP]) { char *value = end->strings[KSCF_SOURCEIP]; if (tnatoaddr(value, strlen(value), AF_INET, &(end->sourceip)) != NULL && tnatoaddr(value, strlen(value), AF_INET6, &(end->sourceip)) != NULL) { #ifdef DNSSEC starter_log(LOG_LEVEL_DEBUG, "Calling unbound_resolve() for %ssourceip value", leftright); if (!unbound_resolve(dnsctx, value, strlen(value), AF_INET, &(end->sourceip)) && !unbound_resolve(dnsctx, value, strlen(value), AF_INET6, &(end->sourceip))) ERR_FOUND("bad value for %ssourceip=%s\n", leftright, value); #else er = ttoaddr(value, 0, family, &(end->sourceip)); if (er != NULL) ERR_FOUND("bad addr %ssourceip=%s [%s]", leftright, value, er); #endif } else { er = tnatoaddr(value, 0, family, &(end->sourceip)); if (er != NULL) ERR_FOUND("bad numerical addr %ssourceip=%s [%s]", leftright, value, er); } if (!end->has_client) { starter_log(LOG_LEVEL_INFO, "%ssourceip= used but not %ssubnet= defined, defaulting %ssubnet to %s", leftright, leftright, leftright, value); er = addrtosubnet(&end->sourceip, &end->subnet); if (er != NULL) { ERR_FOUND("attempt to default %ssubnet from %s failed: %s", leftright, value, er); } end->has_client = TRUE; end->has_client_wildcard = FALSE; } } /* copy certificate path name */ if (end->strings_set[KSCF_CERT]) end->cert = clone_str(end->strings[KSCF_CERT], "KSCF_CERT"); if (end->strings_set[KSCF_CA]) end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA"); if (end->strings_set[KSCF_UPDOWN]) end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN"); if (end->strings_set[KSCF_PROTOPORT]) { err_t ugh; char *value = end->strings[KSCF_PROTOPORT]; ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &end->has_port_wildcard); if (ugh != NULL) ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value, ugh); } if (end->strings_set[KSCF_ADDRESSPOOL]) { char *addresspool = end->strings[KSCF_ADDRESSPOOL]; if (end->strings_set[KSCF_SUBNET]) ERR_FOUND("cannot specify both %ssubnet= and %saddresspool=", leftright, leftright); starter_log(LOG_LEVEL_DEBUG, "connection's %saddresspool set to: %s", leftright, end->strings[KSCF_ADDRESSPOOL] ); er = ttorange(addresspool, 0, AF_INET, &end->pool_range, TRUE); if (er != NULL) ERR_FOUND("bad %saddresspool=%s [%s]", leftright, addresspool, er); } if (end->options_set[KNCF_XAUTHSERVER] || end->options_set[KNCF_XAUTHCLIENT]) conn_st->policy |= POLICY_XAUTH; /* KSCF_SUBNETWITHIN --- not sure what to do with it. KSCF_ESPENCKEY --- todo (manual keying) KSCF_ESPAUTHKEY --- todo (manual keying) KSCF_SOURCEIP = 16, KSCF_MAX = 19 */ if (err) *perr = err_str; return err; # undef ERR_FOUND }
/** * Set up hardcoded defaults, from data in programs/pluto/constants.h * * @param cfg starter_config struct * @return void */ void ipsecconf_default_values(struct starter_config *cfg) { if (!cfg) return; zero(cfg); TAILQ_INIT(&cfg->conns); cfg->setup.options[KBF_FRAGICMP] = TRUE; cfg->setup.options[KBF_HIDETOS] = TRUE; cfg->setup.options[KBF_PLUTORESTARTONCRASH] = TRUE; cfg->setup.options[KBF_PLUTOSTDERRLOGTIME] = FALSE; cfg->setup.options[KBF_UNIQUEIDS] = TRUE; /* XXX not yet: cfg->setup.options[KBF_PLUTOFORK] = FALSE; */ cfg->setup.options[KBF_IKEPORT] = IKE_UDP_PORT; cfg->setup.options[KBF_NATIKEPORT] = NAT_IKE_UDP_PORT; cfg->setup.options[KBF_NHELPERS] = -1; /* MCR XXX */ cfg->setup.options[KBF_KEEPALIVE] = 0; cfg->setup.options[KBF_SECCTX] = SECCTX; cfg->setup.options[KBF_DISABLEPORTFLOATING]= FALSE; cfg->setup.options[KBF_FORCE_KEEPALIVE]= FALSE; cfg->conn_default.options[KBF_NAT_KEEPALIVE] = TRUE; /* per conn */ cfg->conn_default.options[KBF_TYPE] = KS_TUNNEL; /*Cisco interop: remote peer type*/ cfg->conn_default.options[KBF_INITIAL_CONTACT] = FALSE; /* cfg->conn_default.options[KBF_CISCO_UNITY] = FALSE; */ cfg->conn_default.options[KBF_SEND_VENDORID] = FALSE; cfg->conn_default.options[KBF_REMOTEPEERTYPE] = NON_CISCO; cfg->conn_default.options[KBF_SHA2_TRUNCBUG] = FALSE; cfg->conn_default.options[KBF_IKEV1_NATT] = natt_both; /*Network Manager support*/ cfg->conn_default.options[KBF_NMCONFIGURED] = FALSE; cfg->conn_default.options[KBF_LOOPBACK] = FALSE; cfg->conn_default.options[KBF_LABELED_IPSEC] = FALSE; #if 0 cfg->conn_default.options[KBF_XAUTHBY] = XAUTHBY_FILE; cfg->conn_default.options[KBF_XAUTHFAIL] = XAUTHFAIL_HARD; #endif cfg->conn_default.policy = POLICY_RSASIG | POLICY_TUNNEL | POLICY_ENCRYPT | POLICY_PFS; cfg->conn_default.policy |= POLICY_IKEV2_ALLOW; /* ikev2=yes */ cfg->conn_default.policy |= POLICY_SAREF_TRACK; /* sareftrack=yes */ /* cfg->conn_default.policy |= POLICY_IKE_FRAG_ALLOW; */ /* ike_frag=yes */ cfg->conn_default.options[KBF_IKELIFETIME] = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT; cfg->conn_default.options[KBF_SALIFETIME] = SA_LIFE_DURATION_DEFAULT; cfg->conn_default.options[KBF_REKEYMARGIN] = SA_REPLACEMENT_MARGIN_DEFAULT; cfg->conn_default.options[KBF_REKEYFUZZ] = SA_REPLACEMENT_FUZZ_DEFAULT; cfg->conn_default.options[KBF_KEYINGTRIES] = SA_REPLACEMENT_RETRIES_DEFAULT; /* now here is a sticker.. we want it on. But pluto has to be smarter first */ cfg->conn_default.options[KBF_OPPOENCRYPT] = FALSE; cfg->conn_default.options[KBF_CONNADDRFAMILY] = AF_INET; cfg->conn_default.left.addr_family = AF_INET; anyaddr(AF_INET, &cfg->conn_default.left.addr); cfg->conn_default.left.nexttype = KH_NOTSET; anyaddr(AF_INET, &cfg->conn_default.left.nexthop); cfg->conn_default.right.addr_family = AF_INET; anyaddr(AF_INET, &cfg->conn_default.right.addr); cfg->conn_default.right.nexttype = KH_NOTSET; anyaddr(AF_INET, &cfg->conn_default.right.nexthop); /* default is to look in DNS */ cfg->conn_default.left.key_from_DNS_on_demand = TRUE; cfg->conn_default.right.key_from_DNS_on_demand = TRUE; cfg->conn_default.options[KBF_AUTO] = STARTUP_NO; cfg->conn_default.state = STATE_LOADED; cfg->ctlbase = clone_str(CTL_FILE, "default base"); }
/** * Validate that yes in fact we are one side of the tunnel * * The function checks that IP addresses are valid, nexthops are * present (if needed) as well as policies, and sets the leftID * from the left= if it isn't set. * * @param conn_st a connection definition * @param end a connection end * @param left boolean (are we 'left'? 1 = yes, 0 = no) * @param perr pointer to char containing error value * @return bool TRUE if failed */ static bool validate_end(struct starter_conn *conn_st , struct starter_end *end , bool left , bool resolvip UNUSED , err_t *perr) { err_t er = NULL; char *err_str = NULL; const char *leftright=(left ? "left" : "right"); int family = conn_st->options[KBF_CONNADDRFAMILY]; bool err = FALSE; #define ERR_FOUND(args...) do { err += error_append(&err_str, ##args); } while(0) if(!end->options_set[KNCF_IP]) { conn_st->state = STATE_INCOMPLETE; } end->addrtype=end->options[KNCF_IP]; end->addr_family = family; /* validate the KSCF_IP/KNCF_IP */ switch(end->addrtype) { case KH_ANY: anyaddr(family, &(end->addr)); break; case KH_IFACE: /* generally, this doesn't show up at this stage */ break; case KH_IPADDR: /* right=/left= */ assert(end->strings[KSCF_IP] != NULL); if (end->strings[KSCF_IP][0]=='%') { if (end->iface) pfree(end->iface); end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface"); if (starter_iface_find(end->iface, family, &(end->addr), &(end->nexthop)) == -1) { conn_st->state = STATE_INVALID; } /* not numeric, so set the type to the iface type */ end->addrtype = KH_IFACE; break; } er = ttoaddr_num(end->strings[KNCF_IP], 0, family, &(end->addr)); if(er) { /* not numeric, so set the type to the string type */ end->addrtype = KH_IPHOSTNAME; } if(end->id == NULL) { char idbuf[ADDRTOT_BUF]; addrtot(&end->addr, 0, idbuf, sizeof(idbuf)); end->id= clone_str(idbuf, "end id"); } break; case KH_OPPO: conn_st->policy |= POLICY_OPPO; break; case KH_OPPOGROUP: conn_st->policy |= POLICY_OPPO|POLICY_GROUP; break; case KH_GROUP: conn_st->policy |= POLICY_GROUP; break; case KH_IPHOSTNAME: /* XXX */ break; case KH_DEFAULTROUTE: break; case KH_NOTSET: break; } /* validate the KSCF_SUBNET */ if(end->strings_set[KSCF_SUBNET]) { char *value = end->strings[KSCF_SUBNET]; if ( ((strlen(value)>=6) && (strncmp(value,"vhost:",6)==0)) || ((strlen(value)>=5) && (strncmp(value,"vnet:",5)==0)) ) { er = NULL; end->virt = clone_str(value, "end->virt"); } else { end->has_client = TRUE; er = ttosubnet(value, 0, 0, &(end->subnet)); } if (er) ERR_FOUND("bad subnet %ssubnet=%s [%s] family=%s", leftright, value, er, family2str(family)); } /* set nexthop address to something consistent, by default */ anyaddr(family, &end->nexthop); anyaddr(addrtypeof(&end->addr), &end->nexthop); /* validate the KSCF_NEXTHOP */ if(end->strings_set[KSCF_NEXTHOP]) { char *value = end->strings[KSCF_NEXTHOP]; if(strcasecmp(value, "%defaultroute")==0) { end->nexttype=KH_DEFAULTROUTE; } else { if (tnatoaddr(value, strlen(value), AF_INET, &(end->nexthop)) != NULL && tnatoaddr(value, strlen(value), AF_INET6, &(end->nexthop)) != NULL) { er = ttoaddr(value, 0, family, &(end->nexthop)); if (er) ERR_FOUND("bad addr %snexthop=%s [%s]", leftright, value, er); } end->nexttype = KH_IPADDR; } } else { if (end->addrtype == KH_DEFAULTROUTE) { end->nexttype = KH_DEFAULTROUTE; } anyaddr(family, &end->nexthop); } /* validate the KSCF_ID */ if(end->strings_set[KSCF_ID]) { char *value = end->strings[KSCF_ID]; pfreeany(end->id); end->id = clone_str(value, "end->id"); } if(end->options_set[KSCF_RSAKEY1]) { end->rsakey1_type = end->options[KSCF_RSAKEY1]; end->rsakey2_type = end->options[KSCF_RSAKEY2]; switch(end->rsakey1_type) { case PUBKEY_DNS: case PUBKEY_DNSONDEMAND: end->key_from_DNS_on_demand = TRUE; break; default: end->key_from_DNS_on_demand = FALSE; /* validate the KSCF_RSAKEY1/RSAKEY2 */ if(end->strings[KSCF_RSAKEY1] != NULL) { char *value = end->strings[KSCF_RSAKEY1]; pfreeany(end->rsakey1); end->rsakey1 = (unsigned char *)clone_str(value,"end->rsakey1"); } if(end->strings[KSCF_RSAKEY2] != NULL) { char *value = end->strings[KSCF_RSAKEY2]; pfreeany(end->rsakey2); end->rsakey2 = (unsigned char *)clone_str(value,"end->rsakey2"); } } } /* validate the KSCF_SOURCEIP, if any, and if set, * set the subnet to same value, if not set. */ if(end->strings_set[KSCF_SOURCEIP]) { char *value = end->strings[KSCF_SOURCEIP]; if (tnatoaddr(value, strlen(value), AF_INET, &(end->sourceip)) != NULL && tnatoaddr(value, strlen(value), AF_INET6, &(end->sourceip)) != NULL) { er = ttoaddr(value, 0, 0, &(end->sourceip)); if (er) ERR_FOUND("bad addr %ssourceip=%s [%s]", leftright, value, er); } else { er = tnatoaddr(value, 0, 0, &(end->sourceip)); if (er) ERR_FOUND("bad numerical addr %ssourceip=%s [%s]", leftright, value, er); } if(!end->has_client) { starter_log(LOG_LEVEL_INFO, "defaulting %ssubnet to %s\n", leftright, value); er = addrtosubnet(&end->sourceip, &end->subnet); if (er) ERR_FOUND("attempt to default %ssubnet from %s failed: %s", leftright, value, er); end->has_client = TRUE; end->has_client_wildcard = FALSE; } } /* copy certificate path name */ if(end->strings_set[KSCF_CERT]) { end->cert = clone_str(end->strings[KSCF_CERT], "KSCF_CERT"); } if(end->strings_set[KSCF_CA]) { end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA"); } if(end->strings_set[KSCF_UPDOWN]) { end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN"); } if(end->strings_set[KSCF_PROTOPORT]) { err_t ugh; char *value = end->strings[KSCF_PROTOPORT]; ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &end->has_port_wildcard); if (ugh) ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value, ugh); } if (end->options_set[KNCF_XAUTHSERVER] || end->options_set[KNCF_XAUTHCLIENT]) { conn_st->policy |= POLICY_XAUTH; } /* KSCF_SUBNETWITHIN --- not sure what to do with it. KSCF_ESPENCKEY --- todo (manual keying) KSCF_ESPAUTHKEY --- todo (manual keying) KSCF_SOURCEIP = 16, KSCF_MAX = 19 */ if(err) *perr = err_str; return err; # undef ERR_FOUND }
void recv_pcap_packet_gen(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { struct msg_digest *md; u_int32_t *dlt; struct iphdr *ip; struct udphdr *udp; u_char *ike; const struct iface_port *ifp = &if1; int packet_len; err_t from_ugh; union { struct sockaddr sa; struct sockaddr_in sa_in4; struct sockaddr_in6 sa_in6; } from; md = alloc_md(); dlt = (u_int32_t *)bytes; if (*dlt != PF_INET) return; ip = (struct iphdr *)(dlt + 1); udp = (struct udphdr *)(dlt + ip->ihl + 1); ike = (u_char *)(udp + 1); from.sa_in4.sin_addr.s_addr = ip->saddr; from.sa_in4.sin_port = udp->source; md->iface = ifp; packet_len = h->len - (ike - bytes); happy(anyaddr(addrtypeof(&ifp->ip_addr), &md->sender)); from_ugh = initaddr((void *) &from.sa_in4.sin_addr, sizeof(from.sa_in4.sin_addr), AF_INET, &md->sender); setportof(from.sa_in4.sin_port, &md->sender); md->sender_port = ntohs(from.sa_in4.sin_port); cur_from = &md->sender; cur_from_port = md->sender_port; /* Clone actual message contents * and set up md->packet_pbs to describe it. */ init_pbs(&md->packet_pbs, clone_bytes(ike, packet_len, "message buffer in comm_handle()"), packet_len, "packet"); DBG_log("*received %d bytes from %s:%u on %s (port=%d)", (int) pbs_room(&md->packet_pbs), ip_str(&md->sender), (unsigned) md->sender_port, ifp->ip_dev->id_rname, ifp->port); DBG_dump("", md->packet_pbs.start, pbs_room(&md->packet_pbs)); process_packet(&md); if (md != NULL) release_md(md); cur_state = NULL; reset_cur_connection(); cur_from = NULL; }
struct raw_iface * find_raw_ifaces4(void) { static const int on = TRUE; /* by-reference parameter; constant, we hope */ int j; /* index into buf */ static int num=64; /* number of interfaces */ struct ifconf ifconf; struct ifreq *buf; /* for list of interfaces -- arbitrary limit */ struct raw_iface *rifaces = NULL; int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */ /* get list of interfaces with assigned IPv4 addresses from system */ if (master_sock == -1) exit_log_errno((e, "socket() failed in find_raw_ifaces4()")); if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR , (const void *)&on, sizeof(on)) < 0) exit_log_errno((e, "setsockopt() in find_raw_ifaces4()")); /* bind the socket */ { ip_address any; happy(anyaddr(AF_INET, &any)); setportof(htons(pluto_port), &any); if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0) exit_log_errno((e, "bind() failed in find_raw_ifaces4()")); } buf = NULL; /* a million interfaces is probably the maximum, ever... */ while(num < (1024*1024)) { /* Get local interfaces. See netdevice(7). */ ifconf.ifc_len = num * sizeof(struct ifreq); buf = (void *) realloc(buf, ifconf.ifc_len); if (!buf) exit_log_errno((e, "realloc of %d in find_raw_ifaces4()", ifconf.ifc_len)); memset(buf, 0, num*sizeof(struct ifreq)); ifconf.ifc_buf = (void *) buf; if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); /* if we got back less than we asked for, we have them all */ if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num)) break; /* try again and ask for more this time */ num *= 2; } /* Add an entry to rifaces for each interesting interface. */ for (j = 0; (j+1) * sizeof(struct ifreq) <= (size_t)ifconf.ifc_len; j++) { struct raw_iface ri; const struct sockaddr_in *rs = (struct sockaddr_in *) &buf[j].ifr_addr; struct ifreq auxinfo; /* ignore all but AF_INET interfaces */ if (rs->sin_family != AF_INET) continue; /* not interesting */ /* build a NUL-terminated copy of the rname field */ memcpy(ri.name, buf[j].ifr_name, IFNAMSIZ); ri.name[IFNAMSIZ] = '\0'; /* ignore if our interface names were specified, and this isn't one */ if (pluto_ifn_roof != 0) { int i; for (i = 0; i != pluto_ifn_roof; i++) if (streq(ri.name, pluto_ifn[i])) break; if (i == pluto_ifn_roof) continue; /* not found -- skip */ } /* Find out stuff about this interface. See netdevice(7). */ zero(&auxinfo); /* paranoia */ memcpy(auxinfo.ifr_name, buf[j].ifr_name, IFNAMSIZ); if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) exit_log_errno((e , "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()" , ri.name)); if (!(auxinfo.ifr_flags & IFF_UP)) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is not up" , ri.name)); continue; /* ignore an interface that isn't UP */ } if (auxinfo.ifr_flags & IFF_SLAVE) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is a slave interface" , ri.name)); continue; /* ignore slave interfaces; they share IPs with their master */ } /* ignore unconfigured interfaces */ if (rs->sin_addr.s_addr == 0) { DBG(DBG_CONTROL, DBG_log("Ignored interface %s - it is unconfigured" , ri.name)); continue; } happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr) , AF_INET, &ri.addr)); DBG(DBG_CONTROL, DBG_log("found %s with address %s" , ri.name, ip_str(&ri.addr))); ri.next = rifaces; rifaces = clone_thing(ri, "struct raw_iface"); } close(master_sock); return rifaces; }
struct raw_iface *find_raw_ifaces4(void) { static const int on = TRUE; /* by-reference parameter; constant, we hope */ int j; /* index into buf */ struct ifconf ifconf; struct ifreq *buf = NULL; /* for list of interfaces -- arbitrary limit */ struct ifreq *bp; /* cursor into buf */ struct raw_iface *rifaces = NULL; int master_sock = safe_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); /* Get a UDP socket */ /* * Current upper bound on number of interfaces. * Tricky: because this is a static, we won't have to start from * 64 in subsequent calls. */ static int num = 64; /* number of interfaces */ /* get list of interfaces with assigned IPv4 addresses from system */ if (master_sock == -1) exit_log_errno((e, "socket() failed in find_raw_ifaces4()")); if (setsockopt(master_sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0) exit_log_errno((e, "setsockopt() in find_raw_ifaces4()")); /* bind the socket */ { ip_address any; happy(anyaddr(AF_INET, &any)); setportof(htons(pluto_port), &any); if (bind(master_sock, sockaddrof(&any), sockaddrlenof(&any)) < 0) exit_log_errno((e, "bind() failed in find_raw_ifaces4()")); } /* a million interfaces is probably the maximum, ever... */ for (; num < (1024 * 1024); num *= 2) { /* Get num local interfaces. See netdevice(7). */ ifconf.ifc_len = num * sizeof(struct ifreq); buf = realloc(buf, ifconf.ifc_len); if (buf == NULL) { exit_log_errno((e, "realloc of %d in find_raw_ifaces4()", ifconf.ifc_len)); } memset(buf, 0xDF, ifconf.ifc_len); /* stomp */ ifconf.ifc_buf = (void *) buf; if (ioctl(master_sock, SIOCGIFCONF, &ifconf) == -1) exit_log_errno((e, "ioctl(SIOCGIFCONF) in find_raw_ifaces4()")); /* if we got back less than we asked for, we have them all */ if (ifconf.ifc_len < (int)(sizeof(struct ifreq) * num)) break; } /* Add an entry to rifaces for each interesting interface. On Apple, the size of struct ifreq depends on the contents of the union. See if.h */ for (bp = buf, j = 0; bp < (unsigned char *)buf + (size_t)ifconf.ifc_len; bp = (struct ifreq *) ((unsigned char *)bp +_SIZEOF_ADDR_IFREQ(*bp)), j++) { struct raw_iface ri; const struct sockaddr_in *rs = (struct sockaddr_in *) &bp->ifr_addr; struct ifreq auxinfo; /* ignore all but AF_INET interfaces */ if (rs->sin_family != AF_INET) continue; /* not interesting */ /* build a NUL-terminated copy of the rname field */ memcpy(ri.name, bp->ifr_name, IFNAMSIZ); ri.name[IFNAMSIZ] = '\0'; /* ignore if our interface names were specified, and this isn't one */ if (pluto_ifn_roof != 0) { int i; for (i = 0; i != pluto_ifn_roof; i++) if (streq(ri.name, pluto_ifn[i])) break; if (i == pluto_ifn_roof) continue; /* not found -- skip */ } /* Find out stuff about this interface. See netdevice(7). */ zero(&auxinfo); /* paranoia */ memcpy(auxinfo.ifr_name, bp->ifr_name, IFNAMSIZ); if (ioctl(master_sock, SIOCGIFFLAGS, &auxinfo) == -1) { exit_log_errno((e, "ioctl(SIOCGIFFLAGS) for %s in find_raw_ifaces4()", ri.name)); } if (!(auxinfo.ifr_flags & IFF_UP)) continue; /* ignore an interface that isn't UP */ /* ignore unconfigured interfaces */ if (rs->sin_addr.s_addr == 0) continue; happy(initaddr((const void *)&rs->sin_addr, sizeof(struct in_addr), AF_INET, &ri.addr)); DBG(DBG_CONTROL, { ipstr_buf b; DBG_log("found %s with address %s", ri.name, ipstr(&ri.addr, &b)); }); ri.next = rifaces; rifaces = clone_thing(ri, "struct raw_iface"); }
int main(int argc, char **argv) { int i, nspis; char *endptr; int said_opt = 0; const char* error_s = NULL; char ipaddr_txt[ADDRTOT_BUF]; int debug = 0; int j; struct said_af said_af_array[4]; int error = 0; struct sadb_ext *extensions[SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg; #if 0 ip_address pfkey_address_s_ska; #endif program_name = argv[0]; for(i = 0; i < 4; i++) { memset(&said_af_array[i], 0, sizeof(struct said_af)); } if(argc > 1 && strcmp(argv[1], "--debug") == 0) { debug = 1; if(debug) { fprintf(stdout, "\"--debug\" option requested.\n"); } argv += 1; argc -= 1; pfkey_lib_debug = 1; } if(debug) { fprintf(stdout, "argc=%d (%d incl. --debug option).\n", argc, argc + 1); } if(argc > 1 && strcmp(argv[1], "--label") == 0) { if(argc > 2) { program_name = malloc(strlen(argv[0]) + 10 /* update this when changing the sprintf() */ + strlen(argv[2])); sprintf(program_name, "%s --label %s", argv[0], argv[2]); if(debug) { fprintf(stdout, "using \"%s\" as a label.\n", program_name); } argv += 2; argc -= 2; } else { fprintf(stderr, "%s: --label option requires an argument.\n", program_name); exit(1); } } if(debug) { fprintf(stdout, "...After check for --label option.\n"); } if(argc == 1) { system("cat /proc/net/ipsec_spigrp"); exit(0); } if(debug) { fprintf(stdout, "...After check for no option to print /proc/net/ipsec_spigrp.\n"); } if(strcmp(argv[1], "--help") == 0) { if(debug) { fprintf(stdout, "\"--help\" option requested.\n"); } usage(program_name); exit(1); } if(debug) { fprintf(stdout, "...After check for --help option.\n"); } if(strcmp(argv[1], "--version") == 0) { if(debug) { fprintf(stdout, "\"--version\" option requested.\n"); } fprintf(stdout, "%s %s\n", me, ipsec_version_code()); fprintf(stdout, "See `ipsec --copyright' for copyright information.\n"); exit(1); } if(debug) { fprintf(stdout, "...After check for --version option.\n"); } if(strcmp(argv[1], "--said") == 0) { if(debug) { fprintf(stdout, "processing %d args with --said flag.\n", argc); } said_opt = 1; } if(debug) { fprintf(stdout, "...After check for --said option.\n"); } if(said_opt) { if (argc < 3 /*|| argc > 5*/) { fprintf(stderr, "expecting 3 or more args with --said, got %d.\n", argc); usage(program_name); exit(1); } nspis = argc - 2; } else { if ((argc < 5) || (argc > 17) || ((argc % 4) != 1)) { fprintf(stderr, "expecting 5 or more args without --said, got %d.\n", argc); usage(program_name); exit(1); } nspis = argc / 4; } if(debug) { fprintf(stdout, "processing %d nspis.\n", nspis); } for(i = 0; i < nspis; i++) { if(debug) { fprintf(stdout, "processing spi #%d.\n", i); } if(said_opt) { error_s = ttosa((const char *)argv[i+2], 0, (ip_said*)&(said_af_array[i].said)); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n", program_name, error_s, argv[i+2]); exit (1); } said_af_array[i].af = addrtypeof(&(said_af_array[i].said.dst)); if(debug) { addrtot(&said_af_array[i].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stdout, "said[%d].dst=%s.\n", i, ipaddr_txt); } } else { if(!strcmp(argv[i*4+4], "ah")) { said_af_array[i].said.proto = SA_AH; } if(!strcmp(argv[i*4+4], "esp")) { said_af_array[i].said.proto = SA_ESP; } if(!strcmp(argv[i*4+4], "tun")) { said_af_array[i].said.proto = SA_IPIP; } if(!strcmp(argv[i*4+4], "comp")) { said_af_array[i].said.proto = SA_COMP; } if(said_af_array[i].said.proto == 0) { fprintf(stderr, "%s: Badly formed proto: %s\n", program_name, argv[i*4+4]); exit(1); } said_af_array[i].said.spi = htonl(strtoul(argv[i*4+3], &endptr, 0)); if(!(endptr == argv[i*4+3] + strlen(argv[i*4+3]))) { fprintf(stderr, "%s: Badly formed spi: %s\n", program_name, argv[i*4+3]); exit(1); } if(!strcmp(argv[i*4+1], "inet")) { said_af_array[i].af = AF_INET; } if(!strcmp(argv[i*4+1], "inet6")) { said_af_array[i].af = AF_INET6; } if((said_af_array[i].af != AF_INET) && (said_af_array[i].af != AF_INET6)) { fprintf(stderr, "%s: Address family %s not supported\n", program_name, argv[i*4+1]); exit(1); } error_s = ttoaddr(argv[i*4+2], 0, said_af_array[i].af, &(said_af_array[i].said.dst)); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting %dth address argument:%s\n", program_name, error_s, i, argv[i*4+2]); exit (1); } } if(debug) { fprintf(stdout, "SA %d contains: ", i+1); fprintf(stdout, "\n"); fprintf(stdout, "proto = %d\n", said_af_array[i].said.proto); fprintf(stdout, "spi = %08x\n", said_af_array[i].said.spi); addrtot(&said_af_array[i].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stdout, "edst = %s\n", ipaddr_txt); } } if(debug) { fprintf(stdout, "Opening pfkey socket.\n"); } if((pfkey_sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2) ) < 0) { fprintf(stderr, "%s: Trouble opening PF_KEY family socket with error: ", program_name); switch(errno) { case ENOENT: fprintf(stderr, "device does not exist. See FreeS/WAN installation procedure.\n"); break; case EACCES: fprintf(stderr, "access denied. "); if(getuid() == 0) { fprintf(stderr, "Check permissions. Should be 600.\n"); } else { fprintf(stderr, "You must be root to open this file.\n"); } break; case EUNATCH: fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n"); break; case ENODEV: fprintf(stderr, "KLIPS not loaded or enabled.\n"); break; case EBUSY: fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. Please report as much detail as possible to development team.\n"); break; case EINVAL: fprintf(stderr, "Invalid argument, KLIPS not loaded or check kernel log messages for specifics.\n"); break; case ENOBUFS: fprintf(stderr, "No kernel memory to allocate SA.\n"); break; case ESOCKTNOSUPPORT: fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n"); break; case EEXIST: fprintf(stderr, "SA already in use. Delete old one first.\n"); break; case ENXIO: fprintf(stderr, "SA does not exist. Cannot delete.\n"); break; case EAFNOSUPPORT: fprintf(stderr, "KLIPS not loaded or enabled.\n"); break; default: fprintf(stderr, "Unknown file open error %d. Please report as much detail as possible to development team.\n", errno); } exit(1); } for(i = 0; i < (((nspis - 1) < 2) ? 1 : (nspis - 1)); i++) { if(debug) { fprintf(stdout, "processing %dth pfkey message.\n", i); } pfkey_extensions_init(extensions); for(j = 0; j < ((nspis == 1) ? 1 : 2); j++) { if(debug) { fprintf(stdout, "processing %dth said of %dth pfkey message.\n", j, i); } /* Build an SADB_X_GRPSA message to send down. */ /* It needs <base, SA, SA2, address(D,D2) > minimum. */ if(!j) { if((error = pfkey_msg_hdr_build(&extensions[0], SADB_X_GRPSA, proto2satype(said_af_array[i].said.proto), 0, ++pfkey_seq, getpid()))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", program_name, error); pfkey_extensions_free(extensions); exit(1); } } else { if(debug) { fprintf(stdout, "setting x_satype proto=%d satype=%d\n", said_af_array[i+j].said.proto, proto2satype(said_af_array[i+j].said.proto) ); } if((error = pfkey_x_satype_build(&extensions[SADB_X_EXT_SATYPE2], proto2satype(said_af_array[i+j].said.proto) ))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", program_name, error); pfkey_extensions_free(extensions); exit(1); } } if((error = pfkey_sa_build(&extensions[!j ? SADB_EXT_SA : SADB_X_EXT_SA2], !j ? SADB_EXT_SA : SADB_X_EXT_SA2, said_af_array[i+j].said.spi, /* in network order */ 0, 0, 0, 0, 0))) { fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n", program_name, error); pfkey_extensions_free(extensions); exit(1); } #if 0 if(!j) { anyaddr(said_af_array[i].af, &pfkey_address_s_ska); /* Is the address family correct ?? */ if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, 0, sockaddrof(&pfkey_address_s_ska)))) { addrtot(&pfkey_address_s_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n", program_name, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } } #endif if((error = pfkey_address_build(&extensions[!j ? SADB_EXT_ADDRESS_DST : SADB_X_EXT_ADDRESS_DST2], !j ? SADB_EXT_ADDRESS_DST : SADB_X_EXT_ADDRESS_DST2, 0, 0, sockaddrof(&said_af_array[i+j].said.dst)))) { addrtot(&said_af_array[i+j].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n", program_name, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } } if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) { fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n", program_name, error); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); exit(1); } if((error = write(pfkey_sock, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) != pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n", program_name, error, errno); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); switch(errno) { case EACCES: fprintf(stderr, "access denied. "); if(getuid() == 0) { fprintf(stderr, "Check permissions. Should be 600.\n"); } else { fprintf(stderr, "You must be root to open this file.\n"); } break; case EUNATCH: fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n"); break; case EBUSY: fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. Please report as much detail as possible to development team.\n"); break; case EINVAL: fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n"); break; case ENODEV: fprintf(stderr, "KLIPS not loaded or enabled.\n"); fprintf(stderr, "No device?!?\n"); break; case ENOBUFS: fprintf(stderr, "No kernel memory to allocate SA.\n"); break; case ESOCKTNOSUPPORT: fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n"); break; case EEXIST: fprintf(stderr, "SA already in use. Delete old one first.\n"); break; case ENOENT: fprintf(stderr, "device does not exist. See FreeS/WAN installation procedure.\n"); break; case ENXIO: fprintf(stderr, "SA does not exist. Cannot delete.\n"); break; default: fprintf(stderr, "Unknown socket write error %d. Please report as much detail as possible to development team.\n", errno); } exit(1); } if(pfkey_msg) { pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); } } (void) close(pfkey_sock); /* close the socket */ exit(0); }
int main(int argc, char **argv) { int i, nspis; char *endptr; int said_opt = 0; const char* error_s = NULL; char ipaddr_txt[ADDRTOT_BUF]; int j; struct said_af said_af_array[4]; int error = 0; struct stat sts; struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg; #if 0 ip_address pfkey_address_s_ska; #endif progname = argv[0]; for(i = 0; i < 4; i++) { memset(&said_af_array[i], 0, sizeof(struct said_af)); } if(argc > 1 && strcmp(argv[1], "--debug") == 0) { debug = 1; if(debug) { fprintf(stdout, "\"--debug\" option requested.\n"); } argv += 1; argc -= 1; pfkey_lib_debug = PF_KEY_DEBUG_PARSE_MAX; } if(debug) { fprintf(stdout, "argc=%d (%d incl. --debug option).\n", argc, argc + 1); } if(argc > 1 && strcmp(argv[1], "--label") == 0) { if(argc > 2) { progname = malloc(strlen(argv[0]) + 10 /* update this when changing the sprintf() */ + strlen(argv[2])); sprintf(progname, "%s --label %s", argv[0], argv[2]); if(debug) { fprintf(stdout, "using \"%s\" as a label.\n", progname); } argv += 2; argc -= 2; } else { fprintf(stderr, "%s: --label option requires an argument.\n", progname); exit(1); } } if(debug) { fprintf(stdout, "...After check for --label option.\n"); } if ( ((stat ("/proc/net/pfkey", &sts)) == 0) ) { fprintf(stderr, "%s: NETKEY does not use the ipsec spigrp command. Use 'ip xfrm' instead.\n",progname); exit(1); } if(argc == 1) { int ret = 1; if ((stat ("/proc/net/ipsec_spigrp", &sts)) != 0) { fprintf(stderr, "%s: No spigrp - no IPsec support in kernel (are the modules loaded?)\n", progname); } else { ret = system("cat /proc/net/ipsec_spigrp"); ret = ret != -1 && WIFEXITED(ret) ? WEXITSTATUS(ret) : 1; } exit(ret); } if(debug) { fprintf(stdout, "...After check for no option to print /proc/net/ipsec_spigrp.\n"); } if(strcmp(argv[1], "--help") == 0) { if(debug) { fprintf(stdout, "\"--help\" option requested.\n"); } usage(progname); exit(1); } if(debug) { fprintf(stdout, "...After check for --help option.\n"); } if(strcmp(argv[1], "--version") == 0) { if(debug) { fprintf(stdout, "\"--version\" option requested.\n"); } fprintf(stderr, "%s, %s\n", progname, ipsec_version_code()); exit(1); } if(debug) { fprintf(stdout, "...After check for --version option.\n"); } if(strcmp(argv[1], "--said") == 0) { if(debug) { fprintf(stdout, "processing %d args with --said flag.\n", argc); } said_opt = 1; } if(debug) { fprintf(stdout, "...After check for --said option.\n"); } if(said_opt) { if (argc < 3 /*|| argc > 5*/) { fprintf(stderr, "expecting 3 or more args with --said, got %d.\n", argc); usage(progname); exit(1); } nspis = argc - 2; } else { if ((argc < 5) || (argc > 17) || ((argc % 4) != 1)) { fprintf(stderr, "expecting 5 or more args without --said, got %d.\n", argc); usage(progname); exit(1); } nspis = argc / 4; } if(debug) { fprintf(stdout, "processing %d nspis.\n", nspis); } for(i = 0; i < nspis; i++) { if(debug) { fprintf(stdout, "processing spi #%d.\n", i); } if(said_opt) { error_s = ttosa((const char *)argv[i+2], 0, (ip_said*)&(said_af_array[i].said)); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n", progname, error_s, argv[i+2]); exit (1); } said_af_array[i].af = addrtypeof(&(said_af_array[i].said.dst)); if(debug) { addrtot(&said_af_array[i].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stdout, "said[%d].dst=%s.\n", i, ipaddr_txt); } } else { if(!strcmp(argv[i*4+4], "ah")) { said_af_array[i].said.proto = SA_AH; } if(!strcmp(argv[i*4+4], "esp")) { said_af_array[i].said.proto = SA_ESP; } if(!strcmp(argv[i*4+4], "tun")) { said_af_array[i].said.proto = SA_IPIP; } if(!strcmp(argv[i*4+4], "comp")) { said_af_array[i].said.proto = SA_COMP; } if(said_af_array[i].said.proto == 0) { fprintf(stderr, "%s: Badly formed proto: %s\n", progname, argv[i*4+4]); exit(1); } said_af_array[i].said.spi = htonl(strtoul(argv[i*4+3], &endptr, 0)); if(!(endptr == argv[i*4+3] + strlen(argv[i*4+3]))) { fprintf(stderr, "%s: Badly formed spi: %s\n", progname, argv[i*4+3]); exit(1); } if(!strcmp(argv[i*4+1], "inet")) { said_af_array[i].af = AF_INET; } if(!strcmp(argv[i*4+1], "inet6")) { said_af_array[i].af = AF_INET6; } if((said_af_array[i].af != AF_INET) && (said_af_array[i].af != AF_INET6)) { fprintf(stderr, "%s: Address family %s not supported\n", progname, argv[i*4+1]); exit(1); } error_s = ttoaddr(argv[i*4+2], 0, said_af_array[i].af, &(said_af_array[i].said.dst)); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting %dth address argument:%s\n", progname, error_s, i, argv[i*4+2]); exit (1); } } if(debug) { fprintf(stdout, "SA %d contains: ", i+1); fprintf(stdout, "\n"); fprintf(stdout, "proto = %d\n", said_af_array[i].said.proto); fprintf(stdout, "spi = %08x\n", said_af_array[i].said.spi); addrtot(&said_af_array[i].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stdout, "edst = %s\n", ipaddr_txt); } } if(debug) { fprintf(stdout, "Opening pfkey socket.\n"); } pfkey_sock = pfkey_open_sock_with_error(); if(pfkey_sock < 0) { exit(1); } for(i = 0; i < (((nspis - 1) < 2) ? 1 : (nspis - 1)); i++) { if(debug) { fprintf(stdout, "processing %dth pfkey message.\n", i); } pfkey_extensions_init(extensions); for(j = 0; j < ((nspis == 1) ? 1 : 2); j++) { if(debug) { fprintf(stdout, "processing %dth said of %dth pfkey message.\n", j, i); } /* Build an SADB_X_GRPSA message to send down. */ /* It needs <base, SA, SA2, address(D,D2) > minimum. */ if(!j) { if((error = pfkey_msg_hdr_build(&extensions[0], K_SADB_X_GRPSA, proto2satype(said_af_array[i].said.proto), 0, ++pfkey_seq, getpid()))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } } else { if(debug) { fprintf(stdout, "setting x_satype proto=%d satype=%d\n", said_af_array[i+j].said.proto, proto2satype(said_af_array[i+j].said.proto) ); } if((error = pfkey_x_satype_build(&extensions[K_SADB_X_EXT_SATYPE2], proto2satype(said_af_array[i+j].said.proto) ))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } } if((error = pfkey_sa_build(&extensions[!j ? K_SADB_EXT_SA : K_SADB_X_EXT_SA2], !j ? K_SADB_EXT_SA : K_SADB_X_EXT_SA2, said_af_array[i+j].said.spi, /* in network order */ 0, 0, 0, 0, 0))) { fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } #if 0 if(!j) { anyaddr(said_af_array[i].af, &pfkey_address_s_ska); /* Is the address family correct ?? */ if((error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, 0, 0, sockaddrof(&pfkey_address_s_ska)))) { addrtot(&pfkey_address_s_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } } #endif if((error = pfkey_address_build(&extensions[!j ? SADB_EXT_ADDRESS_DST : SADB_X_EXT_ADDRESS_DST2], !j ? SADB_EXT_ADDRESS_DST : SADB_X_EXT_ADDRESS_DST2, 0, 0, sockaddrof(&said_af_array[i+j].said.dst)))) { addrtot(&said_af_array[i+j].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } } if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) { fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n", progname, error); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); exit(1); } if((error = write(pfkey_sock, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) { fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n", progname, error, errno); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); pfkey_write_error(error, errno); } if(pfkey_msg) { pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); } } (void) close(pfkey_sock); /* close the socket */ exit(0); }
int main(int argc, char *argv[]) { __u32 spi = 0; int c; ip_said said; const char *error_s; char ipsaid_txt[SATOT_BUF]; int outif = 0; int error = 0; ssize_t io_error; int argcount = argc; pid_t mypid; int listenreply = 0; unsigned char authalg, encryptalg; struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg; char *edst_opt, *spi_opt, *proto_opt, *af_opt, *said_opt, *dst_opt, *src_opt; u_int32_t natt; u_int16_t sport, dport; uint32_t life[life_maxsever][life_maxtype]; char *life_opt[life_maxsever][life_maxtype]; struct stat sts; struct sadb_builds sab; progname = argv[0]; mypid = getpid(); natt = 0; sport = 0; dport = 0; tool_init_log(); zero(&said); /* OK: no pointer fields */ edst_opt = spi_opt = proto_opt = af_opt = said_opt = dst_opt = src_opt = NULL; { int i, j; for (i = 0; i < life_maxsever; i++) { for (j = 0; j < life_maxtype; j++) { life_opt[i][j] = NULL; life[i][j] = 0; } } } while ((c = getopt_long(argc, argv, "" /*"H:P:Z:46dcA:E:e:s:a:w:i:D:S:hvgl:+:f:"*/, longopts, 0)) != EOF) { unsigned long u; err_t ugh; switch (c) { case 'g': debug = TRUE; pfkey_lib_debug = PF_KEY_DEBUG_PARSE_MAX; /* paul: this is a plutoism? cur_debugging = 0xffffffff; */ argcount--; break; case 'R': listenreply = 1; argcount--; break; case 'r': dumpsaref = 1; argcount--; break; case 'b': /* set the SAref to use */ ugh = ttoulb(optarg, 0, 0, INT_MAX, &u); if (ugh != NULL) { fprintf(stderr, "%s: Invalid SAREFi parameter \"%s\": %s\n", progname, optarg, ugh); exit(1); } saref_me = u; argcount--; break; case 'B': /* set the SAref to use for outgoing packets */ ugh = ttoulb(optarg, 0, 0, INT_MAX, &u); if (ugh != NULL) { fprintf(stderr, "%s: Invalid SAREFo parameter \"%s\": %s\n", progname, optarg, ugh); exit(1); } saref_him = u; argcount--; break; case 'O': /* set interface from which packet should arrive */ ugh = ttoulb(optarg, 0, 0, INT_MAX, &u); if (ugh != NULL) { fprintf(stderr, "%s: Invalid outif parameter \"%s\": %s\n", progname, optarg, ugh); exit(1); } outif = u; argcount--; break; case 'l': { static const char combine_fmt[] = "%s --label %s"; size_t room = strlen(argv[0]) + sizeof(combine_fmt) + strlen(optarg); progname = malloc(room); snprintf(progname, room, combine_fmt, argv[0], optarg); tool_close_log(); tool_init_log(); argcount -= 2; break; } case 'H': if (alg) { fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n", progname); exit(1); } if (streq(optarg, "hmac-md5-96")) { alg = XF_AHHMACMD5; } else if (streq(optarg, "hmac-sha1-96")) { alg = XF_AHHMACSHA1; } else { fprintf(stderr, "%s: Unknown authentication algorithm '%s' follows '--ah' option.\n", progname, optarg); exit(1); } if (debug) { fprintf(stdout, "%s: Algorithm %d selected.\n", progname, alg); } break; case 'P': if (alg) { fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n", progname); exit(1); } alg = decode_esp(optarg); if (debug) { fprintf(stdout, "%s: Algorithm %d selected.\n", progname, alg); } break; case 'Z': if (alg) { fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n", progname); exit(1); } if (streq(optarg, "deflate")) { alg = XF_COMPDEFLATE; } else if (streq(optarg, "lzs")) { alg = XF_COMPLZS; } else { fprintf(stderr, "%s: Unknown compression algorithm '%s' follows '--comp' option.\n", progname, optarg); exit(1); } if (debug) { fprintf(stdout, "%s: Algorithm %d selected.\n", progname, alg); } break; case '4': if (alg) { fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n", progname); exit(1); } alg = XF_IP4; address_family = AF_INET; if (debug) { fprintf(stdout, "%s: Algorithm %d selected.\n", progname, alg); } break; case '6': if (alg) { fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n", progname); exit(1); } alg = XF_IP6; address_family = AF_INET6; if (debug) { fprintf(stdout, "%s: Algorithm %d selected.\n", progname, alg); } break; case 'd': if (alg) { fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n", progname); exit(1); } alg = XF_DEL; if (debug) { fprintf(stdout, "%s: Algorithm %d selected.\n", progname, alg); } break; case 'c': if (alg) { fprintf(stderr, "%s: Only one of '--ah', '--esp', '--comp', '--ip4', '--ip6', '--del' or '--clear' options permitted.\n", progname); exit(1); } alg = XF_CLR; if (debug) { fprintf(stdout, "%s: Algorithm %d selected.\n", progname, alg); } break; case 'e': if (said_opt) { fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit(1); } if (edst_opt) { fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined as:%s\n", progname, optarg, edst_opt); exit(1); } error_s = ttoaddr(optarg, 0, address_family, &edst); if (error_s != NULL) { if (error_s) { fprintf(stderr, "%s: Error, %s converting --edst argument:%s\n", progname, error_s, optarg); exit(1); } } edst_opt = optarg; if (debug) { ipstr_buf b; fprintf(stdout, "%s: edst=%s.\n", progname, ipstr(&edst, &b)); } break; case 's': if (said_opt != NULL) { fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit(1); } if (spi_opt != NULL) { fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined as:%s\n", progname, optarg, spi_opt); exit(1); } ugh = ttoulb(optarg, 0, 0, 0xFFFFFFFFul, &u); if (ugh == NULL && u < 0x100) ugh = "0 - 0xFF are reserved"; if (ugh != NULL) { fprintf(stderr, "%s: Invalid SPI parameter \"%s\": %s\n", progname, optarg, ugh); exit(1); } spi = u; spi_opt = optarg; break; case 'p': if (said_opt != NULL) { fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit(1); } if (proto_opt != NULL) { fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined as:%s\n", progname, optarg, proto_opt); exit(1); } if (streq(optarg, "ah")) { proto = SA_AH; } else if (streq(optarg, "esp")) { proto = SA_ESP; } else if (streq(optarg, "tun")) { proto = SA_IPIP; } else if (streq(optarg, "comp")) { proto = SA_COMP; } else { fprintf(stderr, "%s: Invalid PROTO parameter: %s\n", progname, optarg); exit(1); } proto_opt = optarg; break; case 'a': if (said_opt) { fprintf(stderr, "%s: Error, ADDRESS FAMILY parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit(1); } if (af_opt) { fprintf(stderr, "%s: Error, ADDRESS FAMILY parameter redefined:%s, already defined as:%s\n", progname, optarg, af_opt); exit(1); } if (streq(optarg, "inet")) { address_family = AF_INET; /* currently we ensure that all addresses belong to the same address family */ anyaddr(address_family, &dst); anyaddr(address_family, &edst); anyaddr(address_family, &src); } else if (streq(optarg, "inet6")) { address_family = AF_INET6; /* currently we ensure that all addresses belong to the same address family */ anyaddr(address_family, &dst); anyaddr(address_family, &edst); anyaddr(address_family, &src); } else { fprintf(stderr, "%s: Invalid ADDRESS FAMILY parameter: %s.\n", progname, optarg); exit(1); } af_opt = optarg; break; case 'I': if (said_opt) { fprintf(stderr, "%s: Error, SAID parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit(1); } if (proto_opt) { fprintf(stderr, "%s: Error, PROTO parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, proto_opt); exit(1); } if (edst_opt) { fprintf(stderr, "%s: Error, EDST parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, edst_opt); exit(1); } if (spi_opt) { fprintf(stderr, "%s: Error, SPI parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, spi_opt); exit(1); } error_s = ttosa(optarg, 0, &said); if (error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n", progname, error_s, optarg); exit(1); } if (debug) { satot(&said, 0, ipsaid_txt, sizeof(ipsaid_txt)); fprintf(stdout, "%s: said=%s.\n", progname, ipsaid_txt); } /* init the src and dst with the same address family */ if (address_family == 0) { address_family = addrtypeof(&said.dst); } else if (address_family != addrtypeof(&said.dst)) { fprintf(stderr, "%s: Error, specified address family (%d) is different that of SAID: %s\n", progname, address_family, optarg); exit(1); } anyaddr(address_family, &dst); anyaddr(address_family, &edst); anyaddr(address_family, &src); said_opt = optarg; break; case 'A': decode_blob(optarg, "Authentication Key", &authkey, &authkeylen); break; case 'E': decode_blob(optarg, "Encryption Key", &enckey, &enckeylen); break; case 'w': { err_t ugh = ttoul(optarg, 0, 0, &replay_window); if (ugh != NULL) { fprintf(stderr, "%s: Invalid replay_window parameter: %s\n", progname, ugh); exit(1); } if (!(1 <= replay_window && replay_window <= 64)) { fprintf(stderr, "%s: Failed -- Illegal window size: arg=%s, replay_window=%lu, must be 1 <= size <= 64.\n", progname, optarg, replay_window); exit(1); } } break; case 'i': decode_blob(optarg, "IV", &iv, &ivlen); break; case 'D': if (dst_opt) { fprintf(stderr, "%s: Error, DST parameter redefined:%s, already defined as:%s\n", progname, optarg, dst_opt); exit(1); } error_s = ttoaddr(optarg, 0, address_family, &dst); if (error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --dst argument:%s\n", progname, error_s, optarg); exit(1); } dst_opt = optarg; if (debug) { ipstr_buf b; fprintf(stdout, "%s: dst=%s.\n", progname, ipstr(&dst, &b)); } break; case 'F': /* src port */ { unsigned long u; err_t ugh = ttoulb(optarg, 0, 0, 0xFFFF, &u); if (ugh != NULL) { fprintf(stderr, "%s: Invalid source port parameter \"%s\": %s\n", progname, optarg, ugh); exit(1); } sport = u; } break; case 'G': /* dst port */ { unsigned long u; err_t ugh = ttoulb(optarg, 0, 0, 0xFFFF, &u); if (ugh != NULL) { fprintf(stderr, "%s: Invalid destination port parameter \"%s\": %s\n", progname, optarg, ugh); exit(1); } dport = u; } break; case 'N': /* nat-type */ if (strcaseeq(optarg, "nonesp")) { natt = ESPINUDP_WITH_NON_ESP; } else if (strcaseeq(optarg, "none")) { natt = 0; } else { /* ??? what does this do? Where is it documented? */ unsigned long u; err_t ugh = ttoulb(optarg, 0, 0, 0xFFFFFFFFul, &u); if (ugh != NULL) { fprintf(stderr, "%s: Invalid character in natt parameter \"%s\": %s\n", progname, optarg, ugh); exit(1); } natt = u; } break; case 'S': if (src_opt) { fprintf(stderr, "%s: Error, SRC parameter redefined:%s, already defined as:%s\n", progname, optarg, src_opt); exit(1); } error_s = ttoaddr(optarg, 0, address_family, &src); if (error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --src argument:%s\n", progname, error_s, optarg); exit(1); } src_opt = optarg; if (debug) { ipstr_buf b; fprintf(stdout, "%s: src=%s.\n", progname, ipstr(&src, &b)); } break; case 'h': usage(progname, stdout); exit(0); case '?': usage(progname, stderr); exit(1); case 'v': fprintf(stdout, "%s, %s\n", progname, ipsec_version_code()); exit(1); case 'f': if (parse_life_options(life, life_opt, optarg) != 0) exit(1); break; default: fprintf(stderr, "%s: unrecognized option '%c', update option processing.\n", progname, c); exit(1); } } if (debug) { fprintf(stdout, "%s: All options processed.\n", progname); } if (stat("/proc/net/pfkey", &sts) == 0) { fprintf(stderr, "%s: NETKEY does not use the ipsec spi command. Use 'ip xfrm' instead.\n", progname); exit(1); } if (argcount == 1) { int ret = 1; if ((stat("/proc/net/ipsec_spi", &sts)) != 0) { fprintf(stderr, "%s: No spi - no IPsec support in kernel (are the modules loaded?)\n", progname); } else { ret = system("cat /proc/net/ipsec_spi"); ret = ret != -1 && WIFEXITED(ret) ? WEXITSTATUS(ret) : 1; } exit(ret); } switch (alg) { case XF_OTHER_ALG: /* validate keysizes */ if (proc_read_ok) { const struct sadb_alg *alg_p; size_t keylen, minbits, maxbits; alg_p = kernel_alg_sadb_alg_get(SADB_SATYPE_ESP, SADB_EXT_SUPPORTED_ENCRYPT, esp_info->encryptalg); assert(alg_p != NULL); keylen = enckeylen * 8; minbits = alg_p->sadb_alg_minbits; maxbits = alg_p->sadb_alg_maxbits; /* * if explicit keylen told in encrypt algo, eg "aes128" * check actual keylen "equality" */ if (esp_info->enckeylen && esp_info->enckeylen != keylen) { fprintf(stderr, "%s: invalid encryption keylen=%d, " "required %d by encrypt algo string=\"%s\"\n", progname, (int)keylen, (int)esp_info->enckeylen, alg_string); exit(1); } /* thanks DES for this sh*t */ if (minbits > keylen || maxbits < keylen) { fprintf(stderr, "%s: invalid encryption keylen=%d, " "must be between %d and %d bits\n", progname, (int)keylen, (int)minbits, (int)maxbits); exit(1); } alg_p = kernel_alg_sadb_alg_get(SADB_SATYPE_ESP, SADB_EXT_SUPPORTED_AUTH, esp_info->authalg); assert(alg_p); keylen = authkeylen * 8; minbits = alg_p->sadb_alg_minbits; maxbits = alg_p->sadb_alg_maxbits; if (minbits > keylen || maxbits < keylen) { fprintf(stderr, "%s: invalid auth keylen=%d, " "must be between %d and %d bits\n", progname, (int)keylen, (int)minbits, (int)maxbits); exit(1); } } /* * ??? this break was added in a2791fda77a5cfcc6bc992fbc5019f4448112f88 * It is likely correct, but we're not sure. * Luckily this code is probably never used. */ break; case XF_IP4: case XF_IP6: case XF_DEL: case XF_COMPDEFLATE: case XF_COMPLZS: if (!said_opt) { if (isanyaddr(&edst)) { fprintf(stderr, "%s: SA destination not specified.\n", progname); exit(1); } if (!spi) { fprintf(stderr, "%s: SA SPI not specified.\n", progname); exit(1); } if (!proto) { fprintf(stderr, "%s: SA PROTO not specified.\n", progname); exit(1); } initsaid(&edst, htonl(spi), proto, &said); } else { proto = said.proto; spi = ntohl(said.spi); edst = said.dst; } if ((address_family != 0) && (address_family != addrtypeof(&said.dst))) { fprintf(stderr, "%s: Defined address family and address family of SA missmatch.\n", progname); exit(1); } if (debug) { fprintf(stdout, "%s: SA valid.\n", progname); } break; case XF_CLR: break; default: fprintf(stderr, "%s: No action chosen. See '%s --help' for usage.\n", progname, progname); exit(1); } switch (alg) { case XF_CLR: case XF_DEL: case XF_IP4: case XF_IP6: case XF_COMPDEFLATE: case XF_COMPLZS: case XF_OTHER_ALG: break; default: fprintf(stderr, "%s: No action chosen. See '%s --help' for usage.\n", progname, progname); exit(1); } if (debug) { fprintf(stdout, "%s: Algorithm ok.\n", progname); } pfkey_sock = pfkey_open_sock_with_error(); if (pfkey_sock < 0) exit(1); /* Build an SADB_ADD message to send down. */ /* It needs <base, SA, address(SD), key(AE)> minimum. */ /* Lifetime(HS) could be added before addresses. */ pfkey_extensions_init(extensions); error = pfkey_msg_hdr_build(&extensions[0], alg == XF_DEL ? SADB_DELETE : alg == XF_CLR ? SADB_FLUSH : SADB_ADD, proto2satype(proto), 0, ++pfkey_seq, mypid); if (error != 0) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } switch (alg) { case XF_OTHER_ALG: authalg = esp_info->authalg; if (debug) { fprintf(stdout, "%s: debug: authalg=%d\n", progname, authalg); } break; default: authalg = SADB_AALG_NONE; } switch (alg) { case XF_COMPDEFLATE: encryptalg = SADB_X_CALG_DEFLATE; break; case XF_COMPLZS: encryptalg = SADB_X_CALG_LZS; break; case XF_OTHER_ALG: encryptalg = esp_info->encryptalg; if (debug) { fprintf(stdout, "%s: debug: encryptalg=%d\n", progname, encryptalg); } break; default: encryptalg = SADB_EALG_NONE; } /* IE: pfkey_msg->sadb_msg_type == SADB_FLUSH */ if (!(alg == XF_CLR)) { sab.sa_base.sadb_sa_len = 0; sab.sa_base.sadb_sa_exttype = SADB_EXT_SA; sab.sa_base.sadb_sa_spi = htonl(spi); sab.sa_base.sadb_sa_replay = replay_window; sab.sa_base.sadb_sa_state = K_SADB_SASTATE_MATURE; sab.sa_base.sadb_sa_auth = authalg; sab.sa_base.sadb_sa_encrypt = encryptalg; sab.sa_base.sadb_sa_flags = 0; sab.sa_base.sadb_x_sa_ref = IPSEC_SAREF_NULL; sab.sa_base.sadb_x_reserved[0] = 0; sab.sa_base.sadb_x_reserved[1] = 0; sab.sa_base.sadb_x_reserved[2] = 0; sab.sa_base.sadb_x_reserved[3] = 0; error = pfkey_sa_builds(&extensions[SADB_EXT_SA], sab); if (error != 0) { fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } if (saref_me || saref_him) { error = pfkey_saref_build(&extensions[ K_SADB_X_EXT_SAREF], saref_me, saref_him); if (error) { fprintf(stderr, "%s: Trouble building saref extension, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } } if (outif != 0) { error = pfkey_outif_build(&extensions[ SADB_X_EXT_PLUMBIF], outif); if (error != 0) { fprintf(stderr, "%s: Trouble building outif extension, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } } if (debug) { fprintf(stdout, "%s: extensions[0]=0p%p previously set with msg_hdr.\n", progname, extensions[0]); } if (debug) { fprintf(stdout, "%s: assembled SA extension, pfkey msg authalg=%d encalg=%d.\n", progname, authalg, encryptalg); } if (debug) { int i, j; for (i = 0; i < life_maxsever; i++) { for (j = 0; j < life_maxtype; j++) { fprintf(stdout, "%s: i=%d, j=%d, life_opt[%d][%d]=0p%p, life[%d][%d]=%d\n", progname, i, j, i, j, life_opt[i][j], i, j, life[i][j]); } } } emit_lifetime("lifetime_s", SADB_EXT_LIFETIME_SOFT, extensions, life_opt[life_soft], life[life_soft]); emit_lifetime("lifetime_h", SADB_EXT_LIFETIME_HARD, extensions, life_opt[life_hard], life[life_hard]); if (debug) { ipstr_buf b; fprintf(stdout, "%s: assembling address_s extension (%s).\n", progname, ipstr(&src, &b)); } error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, 0, sockaddrof(&src)); if (error != 0) { ipstr_buf b; fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n", progname, ipstr(&src, &b), error); pfkey_extensions_free(extensions); exit(1); } error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, 0, sockaddrof(&edst)); if (error != 0) { ipstr_buf b; fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n", progname, ipstr(&edst, &b), error); pfkey_extensions_free(extensions); exit(1); } switch (alg) { /* Allow no auth ... after all is local root decision 8) */ case XF_OTHER_ALG: if (!authalg) break; error = pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH], SADB_EXT_KEY_AUTH, authkeylen * 8, authkey); if (error != 0) { fprintf(stderr, "%s: Trouble building key_a extension, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } if (debug) { fprintf(stdout, "%s: key_a extension assembled.\n", progname); } break; default: break; } switch (alg) { case XF_OTHER_ALG: if (enckeylen == 0) { if (debug) fprintf(stdout, "%s: key not provided (NULL alg?).\n", progname); break; } error = pfkey_key_build(&extensions[SADB_EXT_KEY_ENCRYPT], SADB_EXT_KEY_ENCRYPT, enckeylen * 8, enckey); if (error != 0) { fprintf(stderr, "%s: Trouble building key_e extension, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } if (debug) { fprintf(stdout, "%s: key_e extension assembled.\n", progname); } break; default: break; } } if (natt != 0) { bool success; int err; err = pfkey_x_nat_t_type_build(&extensions[ K_SADB_X_EXT_NAT_T_TYPE], natt); success = pfkey_build(err, "pfkey_nat_t_type Add ESP SA", ipsaid_txt, extensions); if (!success) return FALSE; if (debug) fprintf(stderr, "setting natt_type to %d\n", natt); if (sport != 0) { err = pfkey_x_nat_t_port_build( &extensions[K_SADB_X_EXT_NAT_T_SPORT], K_SADB_X_EXT_NAT_T_SPORT, sport); success = pfkey_build(err, "pfkey_nat_t_sport Add ESP SA", ipsaid_txt, extensions); if (debug) fprintf(stderr, "setting natt_sport to %d\n", sport); if (!success) return FALSE; } if (dport != 0) { err = pfkey_x_nat_t_port_build( &extensions[K_SADB_X_EXT_NAT_T_DPORT], K_SADB_X_EXT_NAT_T_DPORT, dport); success = pfkey_build(err, "pfkey_nat_t_dport Add ESP SA", ipsaid_txt, extensions); if (debug) fprintf(stderr, "setting natt_dport to %d\n", dport); if (!success) return FALSE; } #if 0 /* not yet implemented */ if (natt != 0 && !isanyaddr(&natt_oa)) { ip_str_buf b; success = pfkeyext_address(SADB_X_EXT_NAT_T_OA, &natt_oa, "pfkey_nat_t_oa Add ESP SA", ipsaid_txt, extensions); if (debug) fprintf(stderr, "setting nat_oa to %s\n", ipstr(&natt_oa, &b)); if (!success) return FALSE; } #endif } if (debug) { fprintf(stdout, "%s: assembling pfkey msg....\n", progname); } error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN); if (error != 0) { fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n", progname, error); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); exit(1); } if (debug) { fprintf(stdout, "%s: assembled.\n", progname); } if (debug) { fprintf(stdout, "%s: writing pfkey msg.\n", progname); } io_error = write(pfkey_sock, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN); if (io_error < 0) { fprintf(stderr, "%s: pfkey write failed (errno=%d): ", progname, errno); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); switch (errno) { case EACCES: fprintf(stderr, "access denied. "); if (getuid() == 0) fprintf(stderr, "Check permissions. Should be 600.\n"); else fprintf(stderr, "You must be root to open this file.\n"); break; case EUNATCH: fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n"); break; case EBUSY: fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. Please report as much detail as possible to development team.\n"); break; case EINVAL: fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n"); break; case ENODEV: fprintf(stderr, "KLIPS not loaded or enabled.\n"); fprintf(stderr, "No device?!?\n"); break; case ENOBUFS: fprintf(stderr, "No kernel memory to allocate SA.\n"); break; case ESOCKTNOSUPPORT: fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n"); break; case EEXIST: fprintf(stderr, "SA already in use. Delete old one first.\n"); break; case ENOENT: fprintf(stderr, "device does not exist. See Libreswan installation procedure.\n"); break; case ENXIO: case ESRCH: fprintf(stderr, "SA does not exist. Cannot delete.\n"); break; case ENOSPC: fprintf(stderr, "no room in kernel SAref table. Cannot process request.\n"); break; case ESPIPE: fprintf(stderr, "kernel SAref table internal error. Cannot process request.\n"); break; default: fprintf(stderr, "Unknown socket write error %d (%s). Please report as much detail as possible to development team.\n", errno, strerror(errno)); } exit(1); } else if (io_error != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) { fprintf(stderr, "%s: pfkey write truncated to %d bytes\n", progname, (int)io_error); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); exit(1); } if (debug) { fprintf(stdout, "%s: pfkey command written to socket.\n", progname); } if (pfkey_msg != NULL) { pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); } if (debug) { fprintf(stdout, "%s: pfkey message buffer freed.\n", progname); } if (authkey != NULL) { memset(authkey, 0, authkeylen); free(authkey); } if (enckey != NULL) { memset(enckey, 0, enckeylen); free(enckey); } if (iv != NULL) { memset(iv, 0, ivlen); free(iv); } if (listenreply || saref_me || dumpsaref) { ssize_t readlen; unsigned char pfkey_buf[PFKEYv2_MAX_MSGSIZE]; while ((readlen = read(pfkey_sock, pfkey_buf, sizeof(pfkey_buf))) > 0) { struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; pfkey_extensions_init(extensions); pfkey_msg = (struct sadb_msg *)pfkey_buf; /* first, see if we got enough for an sadb_msg */ if ((size_t)readlen < sizeof(struct sadb_msg)) { if (debug) { printf("%s: runt packet of size: %ld (<%lu)\n", progname, (long)readlen, (unsigned long)sizeof(struct sadb_msg)); } continue; } /* okay, we got enough for a message, print it out */ if (debug) { printf("%s: pfkey v%d msg received. type=%d(%s) seq=%d len=%d pid=%d errno=%d satype=%d(%s)\n", progname, pfkey_msg->sadb_msg_version, pfkey_msg->sadb_msg_type, pfkey_v2_sadb_type_string(pfkey_msg-> sadb_msg_type), pfkey_msg->sadb_msg_seq, pfkey_msg->sadb_msg_len, pfkey_msg->sadb_msg_pid, pfkey_msg->sadb_msg_errno, pfkey_msg->sadb_msg_satype, satype2name(pfkey_msg->sadb_msg_satype)); } if (readlen != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) { if (debug) { printf("%s: packet size read from socket=%d doesn't equal sadb_msg_len %u * %u; message not decoded\n", progname, (int)readlen, (unsigned)pfkey_msg->sadb_msg_len, (unsigned)IPSEC_PFKEYv2_ALIGN); } continue; } if (pfkey_msg_parse(pfkey_msg, NULL, extensions, EXT_BITS_OUT)) { if (debug) { printf("%s: unparseable PF_KEY message.\n", progname); } continue; } if (debug) { printf("%s: parseable PF_KEY message.\n", progname); } if ((pid_t)pfkey_msg->sadb_msg_pid == mypid) { if (saref_me || dumpsaref) { struct sadb_x_saref *s = (struct sadb_x_saref *) extensions[ K_SADB_X_EXT_SAREF]; if (s != NULL) { printf("%s: saref=%d/%d\n", progname, s->sadb_x_saref_me, s->sadb_x_saref_him); } } break; } } } (void) close(pfkey_sock); /* close the socket */ if (debug || listenreply) printf("%s: exited normally\n", progname); exit(0); }