diff options
Diffstat (limited to 'openvpn/src/openvpn/socket.c')
-rw-r--r-- | openvpn/src/openvpn/socket.c | 360 |
1 files changed, 212 insertions, 148 deletions
diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 2605f854..05ae9e91 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -39,6 +39,7 @@ #include "manage.h" #include "misc.h" #include "manage.h" +#include "openvpn.h" #include "memdbg.h" @@ -118,6 +119,59 @@ getaddr (unsigned int flags, } +void +do_preresolve(struct context *c) +{ + int i; + struct connection_list *l = c->options.connection_list; + + + for (i = 0; i < l->len; ++i) { + int status; + const char *remote; + struct connection_entry* ce = c->options.connection_list->array[i]; + unsigned int flags = GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE| + GETADDR_MENTION_RESOLVE_RETRY|GETADDR_FATAL; + + if (proto_is_dgram(ce->proto)) + flags |= GETADDR_DATAGRAM; + + if (c->options.sockflags & SF_HOST_RANDOMIZE) + flags |= GETADDR_RANDOMIZE; + + if (c->options.ip_remote_hint) + remote = c->options.ip_remote_hint; + else + remote = ce->remote; + + if (! ce->preresolved_remote) + { + status = openvpn_getaddrinfo (flags, remote, ce->remote_port, + c->options.resolve_retry_seconds, NULL, + ce->af, &ce->preresolved_remote); + + if (status != 0) + goto err; + } + + flags |= GETADDR_PASSIVE; + if (ce->bind_local && !ce->preresolved_local) + { + status = openvpn_getaddrinfo (flags, ce->local, ce->local_port, + c->options.resolve_retry_seconds, NULL, + ce->af, &ce->preresolved_local); + + if (status != 0) + goto err; + } + + } + return; + + err: + throw_signal_soft (SIGUSR1, "Preresolving failed"); +} + /* * Translate IPv4/IPv6 addr or hostname into struct addrinfo * If resolve error, try again for resolve_retry_seconds seconds. @@ -275,8 +329,8 @@ openvpn_getaddrinfo (unsigned int flags, /* hostname resolve succeeded */ - /* - * Do not chose an IP Addresse by random or change the order * + /* + * Do not choose an IP Addresse by random or change the order * * of IP addresses, doing so will break RFC 3484 address selection * */ } @@ -627,7 +681,7 @@ create_socket_udp (const int af, const unsigned int flags) else if (flags & SF_USE_IP_PKTINFO) { int pad = 1; - if(af == AF_INET) + if(af == AF_INET) { #ifdef IP_PKTINFO if (setsockopt (sd, SOL_IP, IP_PKTINFO, @@ -640,8 +694,8 @@ create_socket_udp (const int af, const unsigned int flags) #else #error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h) #endif - } - else if (af == AF_INET6 ) + } + else if (af == AF_INET6 ) { #ifndef IPV6_RECVPKTINFO /* Some older Darwin platforms require this */ if (setsockopt (sd, IPPROTO_IPV6, IPV6_PKTINFO, @@ -665,7 +719,7 @@ create_socket (struct link_socket *sock) int ai_family = sock->info.lsa->actual.ai_family; ASSERT (sock->info.af == AF_UNSPEC || sock->info.af == ai_family); - + if (ai_proto == IPPROTO_UDP) { sock->sd = create_socket_udp (ai_family, sock->sockflags); @@ -686,10 +740,9 @@ create_socket (struct link_socket *sock) } /* set socket buffers based on --sndbuf and --rcvbuf options */ socket_set_buffers (sock->sd, &sock->socket_buffer_sizes); - + /* set socket to --mark packets with given value */ socket_set_mark (sock->sd, sock->mark); - } #ifdef TARGET_ANDROID @@ -898,13 +951,12 @@ socket_bind (socket_descriptor_t sd, * For example if an address has multiple A records * What is the correct way to deal with it? */ - + struct addrinfo* cur; - int v6only= ipv6only ? 0: 1; - + ASSERT(local); - - + + /* find the first addrinfo with correct ai_family */ for (cur = local; cur; cur=cur->ai_next) { @@ -917,9 +969,11 @@ socket_bind (socket_descriptor_t sd, if (ai_family == AF_INET6) { + int v6only = ipv6only ? 0: 1; /* setsockopt must have an "int" */ + if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only))) { - msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY failed"); + msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY=%d failed", v6only); } } if (bind (sd, cur->ai_addr, cur->ai_addrlen)) @@ -1023,7 +1077,7 @@ void set_actual_address (struct link_socket_actual* actual, struct addrinfo* ai) { CLEAR (*actual); ASSERT (ai); - + if (ai->ai_family == AF_INET) actual->dest.addr.in4 = *((struct sockaddr_in*) ai->ai_addr); @@ -1032,7 +1086,7 @@ void set_actual_address (struct link_socket_actual* actual, struct addrinfo* ai) *((struct sockaddr_in6*) ai->ai_addr); else ASSERT(0); - + /* Copy addrinfo sock parameters for socket creating */ actual->ai_family = ai->ai_family; actual->ai_protocol = ai->ai_protocol; @@ -1047,9 +1101,9 @@ socket_connect (socket_descriptor_t *sd, { struct gc_arena gc = gc_new (); const struct sockaddr *dest = &lsa->actual.dest.addr.sa; - + int status; - + #ifdef CONNECT_NONBLOCK msg (M_INFO, "Attempting to establish TCP connection with %s [nonblock]", print_sockaddr (dest, &gc)); @@ -1057,14 +1111,14 @@ socket_connect (socket_descriptor_t *sd, msg (M_INFO, "Attempting to establish TCP connection with %s", print_sockaddr (dest, &gc)); #endif - + #ifdef ENABLE_MANAGEMENT if (management) management_set_state (management, - OPENVPN_STATE_TCP_CONNECT, - NULL, - (in_addr_t)0, - (in_addr_t)0); + OPENVPN_STATE_TCP_CONNECT, + NULL, + (in_addr_t)0, + (in_addr_t)0); #endif /* Set the actual address */ @@ -1154,7 +1208,13 @@ resolve_bind_local (struct link_socket *sock, const sa_family_t af) flags |= GETADDR_DATAGRAM; /* will return AF_{INET|INET6}from local_host */ - status = openvpn_getaddrinfo(flags, sock->local_host, sock->local_port, 0, + if (sock->preresolved_local) + { + status=0; + sock->info.lsa->bind_local=sock->preresolved_local; + } + else + status = openvpn_getaddrinfo(flags, sock->local_host, sock->local_port, 0, NULL, af, &sock->info.lsa->bind_local); if(status !=0) { @@ -1192,104 +1252,104 @@ resolve_remote (struct link_socket *sock, { struct gc_arena gc = gc_new (); - if (!sock->did_resolve_remote) + /* resolve remote address if undefined */ + if (!sock->info.lsa->remote_list) { - /* resolve remote address if undefined */ - if (!sock->info.lsa->remote_list) + if (sock->remote_host) { - if (sock->remote_host) + unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags); + int retry = 0; + int status = -1; + struct addrinfo* ai; + if (proto_is_dgram(sock->info.proto)) + flags |= GETADDR_DATAGRAM; + + if (sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE) + { + if (phase == 2) + flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL); + retry = 0; + } + else if (phase == 1) { - unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags); - int retry = 0; - int status = -1; - struct addrinfo* ai; - if (proto_is_dgram(sock->info.proto)) - flags |= GETADDR_DATAGRAM; - - if (sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE) + if (sock->resolve_retry_seconds) { - if (phase == 2) - flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL); retry = 0; } - else if (phase == 1) + else { - if (sock->resolve_retry_seconds) - { - retry = 0; - } - else - { - flags |= (GETADDR_FATAL | GETADDR_MENTION_RESOLVE_RETRY); - retry = 0; - } + flags |= (GETADDR_FATAL | GETADDR_MENTION_RESOLVE_RETRY); + retry = 0; } - else if (phase == 2) + } + else if (phase == 2) + { + if (sock->resolve_retry_seconds) { - if (sock->resolve_retry_seconds) - { - flags |= GETADDR_FATAL; - retry = sock->resolve_retry_seconds; - } - else - { - ASSERT (0); - } + flags |= GETADDR_FATAL; + retry = sock->resolve_retry_seconds; } else { ASSERT (0); } + } + else + { + ASSERT (0); + } - status = openvpn_getaddrinfo (flags, sock->remote_host, sock->remote_port, - retry, signal_received, sock->info.af, &ai); - - if(status == 0) { - sock->info.lsa->remote_list = ai; - sock->info.lsa->current_remote = ai; - - dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", - flags, - phase, - retry, - signal_received ? *signal_received : -1, - status); - } + if (sock->preresolved_remote) + { + status = 0; + ai = sock->preresolved_remote; + } + else + status = openvpn_getaddrinfo (flags, sock->remote_host, sock->remote_port, + retry, signal_received, sock->info.af, &ai); + + if(status == 0) { + sock->info.lsa->remote_list = ai; + sock->info.lsa->current_remote = ai; + + dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", + flags, + phase, + retry, + signal_received ? *signal_received : -1, + status); + } + if (signal_received) + { + if (*signal_received) + goto done; + } + if (status!=0) + { if (signal_received) - { - if (*signal_received) - goto done; - } - if (status!=0) - { - if (signal_received) - *signal_received = SIGUSR1; - goto done; - } + *signal_received = SIGUSR1; + goto done; } } + } - /* should we re-use previous active remote address? */ - if (link_socket_actual_defined (&sock->info.lsa->actual)) - { - msg (M_INFO, "TCP/UDP: Preserving recently used remote address: %s", - print_link_socket_actual (&sock->info.lsa->actual, &gc)); - if (remote_dynamic) - *remote_dynamic = NULL; - } - /* else, quick hack to fix persistent-remote ....*/ - { - CLEAR (sock->info.lsa->actual); - if(sock->info.lsa->current_remote) - { - set_actual_address (&sock->info.lsa->actual, - sock->info.lsa->current_remote); - } - } - - /* remember that we finished */ - sock->did_resolve_remote = true; + /* should we re-use previous active remote address? */ + if (link_socket_actual_defined (&sock->info.lsa->actual)) + { + msg (M_INFO, "TCP/UDP: Preserving recently used remote address: %s", + print_link_socket_actual (&sock->info.lsa->actual, &gc)); + if (remote_dynamic) + *remote_dynamic = NULL; } + /* else, quick hack to fix persistent-remote ....*/ + { + CLEAR (sock->info.lsa->actual); + if(sock->info.lsa->current_remote) + { + set_actual_address (&sock->info.lsa->actual, + sock->info.lsa->current_remote); + } + } done: gc_free (&gc); @@ -1317,11 +1377,11 @@ create_new_socket (struct link_socket* sock) resolve_bind_local (sock, sock->info.af); } resolve_remote (sock, 1, NULL, NULL); - + /* * In P2P or server mode we must create the socket even when resolving * the remote site fails/is not specified. */ - + if (sock->info.lsa->actual.ai_family==0 && sock->bind_local) { /* Copy sock parameters from bind addr */ @@ -1329,8 +1389,8 @@ create_new_socket (struct link_socket* sock) /* clear destination set by set_actual_address */ CLEAR(sock->info.lsa->actual.dest); } - - /* + + /* * Create the socket early if socket should be bound */ if (sock->bind_local) @@ -1340,6 +1400,7 @@ create_new_socket (struct link_socket* sock) if (sock->bind_local) bind_local(sock); } + } @@ -1348,8 +1409,10 @@ void link_socket_init_phase1 (struct link_socket *sock, const char *local_host, const char *local_port, + struct addrinfo *local_preresolved, const char *remote_host, const char *remote_port, + struct addrinfo *remote_preresolved, int proto, sa_family_t af, bool bind_ipv6_only, @@ -1382,8 +1445,10 @@ link_socket_init_phase1 (struct link_socket *sock, sock->local_host = local_host; sock->local_port = local_port; + sock->preresolved_local = local_preresolved; sock->remote_host = remote_host; sock->remote_port = remote_port; + sock->preresolved_remote = remote_preresolved; #ifdef ENABLE_HTTP_PROXY sock->http_proxy = http_proxy; @@ -1425,7 +1490,7 @@ link_socket_init_phase1 (struct link_socket *sock, ASSERT (!sock->inetd); sock->sd = accept_from->sd; } - + if (false) ; #ifdef ENABLE_HTTP_PROXY @@ -1560,39 +1625,35 @@ static void linksock_print_addr (struct link_socket *sock) { struct gc_arena gc = gc_new (); + const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? D_INIT_MEDIUM : M_INFO; - /* print local address */ - { - const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? D_INIT_MEDIUM : M_INFO; - - if (sock->inetd) - msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, sock->info.af, true)); - else if (sock->bind_local) - { - /* Socket is always bound on the first matching address */ - struct addrinfo *cur; - for (cur = sock->info.lsa->bind_local; cur; cur=cur->ai_next) - { - if(cur->ai_family == sock->info.lsa->actual.ai_family) - break; - } - ASSERT (cur); - msg (msglevel, "%s link local (bound): %s", + if (sock->inetd) + msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, sock->info.af, true)); + else if (sock->bind_local) + { + /* Socket is always bound on the first matching address */ + struct addrinfo *cur; + for (cur = sock->info.lsa->bind_local; cur; cur=cur->ai_next) + { + if(cur->ai_family == sock->info.lsa->actual.ai_family) + break; + } + ASSERT (cur); + msg (msglevel, "%s link local (bound): %s", proto2ascii (sock->info.proto, sock->info.af, true), print_sockaddr(cur->ai_addr,&gc)); - } - else - msg (msglevel, "%s link local: (not bound)", - proto2ascii (sock->info.proto, sock->info.af, true)); - - /* print active remote address */ - msg (msglevel, "%s link remote: %s", - proto2ascii (sock->info.proto, sock->info.af, true), - print_link_socket_actual_ex (&sock->info.lsa->actual, - ":", - PS_SHOW_PORT_IF_DEFINED, - &gc)); - } + } + else + msg (msglevel, "%s link local: (not bound)", + proto2ascii (sock->info.proto, sock->info.af, true)); + + /* print active remote address */ + msg (msglevel, "%s link remote: %s", + proto2ascii (sock->info.proto, sock->info.af, true), + print_link_socket_actual_ex (&sock->info.lsa->actual, + ":", + PS_SHOW_PORT_IF_DEFINED, + &gc)); gc_free(&gc); } @@ -1631,7 +1692,6 @@ phase2_tcp_server (struct link_socket *sock, const char *remote_dynamic, default: ASSERT (0); } - } @@ -1645,9 +1705,9 @@ phase2_tcp_client (struct link_socket *sock, struct signal_info *sig_info) #endif do { socket_connect (&sock->sd, - sock->info.lsa, - sock->connect_timeout, - sig_info); + sock->info.lsa, + sock->connect_timeout, + sig_info); if (sig_info->signal_received) return; @@ -1678,7 +1738,7 @@ phase2_tcp_client (struct link_socket *sock, struct signal_info *sig_info) if (proxy_retry) { /* TODO (schwabe): This code assumes AF_INET for the proxy socket - * when retrying a connection */ + * when retrying a connection */ openvpn_close_socket (sock->sd); sock->sd = create_socket_tcp (AF_INET); } @@ -1698,7 +1758,7 @@ phase2_socks_client (struct link_socket *sock, struct signal_info *sig_info) if (sig_info->signal_received) return; - + establish_socks_proxy_udpassoc (sock->socks_proxy, sock->ctrl_sd, sock->sd, @@ -1710,7 +1770,6 @@ phase2_socks_client (struct link_socket *sock, struct signal_info *sig_info) sock->remote_host = sock->proxy_dest_host; sock->remote_port = sock->proxy_dest_port; - sock->did_resolve_remote = false; addr_zero_host(&sock->info.lsa->actual.dest); if (sock->info.lsa->remote_list) @@ -2482,12 +2541,17 @@ struct proto_names { /* Indexed by PROTO_x */ static const struct proto_names proto_names[] = { {"proto-uninitialized", "proto-NONE", AF_UNSPEC, PROTO_NONE}, + /* try IPv4 and IPv6 (client), bind dual-stack (server) */ {"udp", "UDP", AF_UNSPEC, PROTO_UDP}, - {"udp4", "UDPv4", AF_INET, PROTO_UDP}, - {"tcp-server", "TCPv4_SERVER", AF_INET, PROTO_TCP_SERVER}, - {"tcp-client", "TCPv4_CLIENT", AF_INET, PROTO_TCP_CLIENT}, + {"tcp-server", "TCP_SERVER", AF_UNSPEC, PROTO_TCP_SERVER}, + {"tcp-client", "TCP_CLIENT", AF_UNSPEC, PROTO_TCP_CLIENT}, {"tcp", "TCP", AF_UNSPEC, PROTO_TCP}, - {"tcp4", "TCPv4", AF_INET, PROTO_TCP}, + /* force IPv4 */ + {"udp4", "UDPv4", AF_INET, PROTO_UDP}, + {"tcp4-server","TCPv4_SERVER", AF_INET, PROTO_TCP_SERVER}, + {"tcp4-client","TCPv4_CLIENT", AF_INET, PROTO_TCP_CLIENT}, + {"tcp4", "TCPv4", AF_INET, PROTO_TCP}, + /* force IPv6 */ {"udp6" ,"UDPv6", AF_INET6, PROTO_UDP}, {"tcp6-server","TCPv6_SERVER", AF_INET6, PROTO_TCP_SERVER}, {"tcp6-client","TCPv6_CLIENT", AF_INET6, PROTO_TCP_CLIENT}, |