diff options
Diffstat (limited to 'app/openvpn/src/openvpn/socket.c')
-rw-r--r-- | app/openvpn/src/openvpn/socket.c | 1029 |
1 files changed, 584 insertions, 445 deletions
diff --git a/app/openvpn/src/openvpn/socket.c b/app/openvpn/src/openvpn/socket.c index 31ff6d21..9e6bd10c 100644 --- a/app/openvpn/src/openvpn/socket.c +++ b/app/openvpn/src/openvpn/socket.c @@ -39,6 +39,7 @@ #include "manage.h" #include "misc.h" #include "manage.h" +#include "openvpn.h" #include "memdbg.h" @@ -117,6 +118,178 @@ getaddr (unsigned int flags, } } +static inline bool +streqnull (const char* a, const char* b) +{ + if (a == NULL && b == NULL) + return true; + else if (a == NULL || b == NULL) + return false; + else + return streq (a, b); +} + +/* + get_cached_dns_entry return 0 on success and -1 + otherwise. (like getaddrinfo) + */ +static int +get_cached_dns_entry (struct cached_dns_entry* dns_cache, + const char* hostname, + const char* servname, + int ai_family, + int resolve_flags, + struct addrinfo **ai) +{ + struct cached_dns_entry *ph; + int flags; + + /* Only use flags that are relevant for the structure */ + flags = resolve_flags & GETADDR_CACHE_MASK; + + for (ph = dns_cache; ph ; ph = ph->next) + { + if (streqnull (ph->hostname, hostname) && + streqnull (ph->servname, servname) && + ph->ai_family == ai_family && + ph->flags == flags) + { + *ai = ph->ai; + return 0; + } + } + return -1; +} + + +static int +do_preresolve_host (struct context *c, + const char *hostname, + const char *servname, + const int af, + const int flags) +{ + struct addrinfo *ai; + int status; + + if (get_cached_dns_entry(c->c1.dns_cache, + hostname, + servname, + af, + flags, + &ai) == 0 ) + { + /* entry already cached, return success */ + return 0; + } + + status = openvpn_getaddrinfo (flags, hostname, servname, + c->options.resolve_retry_seconds, NULL, + af, &ai); + if (status == 0) + { + struct cached_dns_entry *ph; + + ALLOC_OBJ_CLEAR_GC (ph, struct cached_dns_entry, &c->gc); + ph->ai = ai; + ph->hostname = hostname; + ph->servname = servname; + ph->flags = flags & GETADDR_CACHE_MASK; + + if (!c->c1.dns_cache) + c->c1.dns_cache = ph; + else + { + struct cached_dns_entry *prev = c->c1.dns_cache; + while (prev->next) + prev = prev->next; + prev->next = ph; + } + + gc_addspecial (ai, &gc_freeaddrinfo_callback, &c->gc); + + } + return status; +} + +void +do_preresolve (struct context *c) +{ + int i; + struct connection_list *l = c->options.connection_list; + const unsigned int preresolve_flags = GETADDR_RESOLVE| + GETADDR_UPDATE_MANAGEMENT_STATE| + GETADDR_MENTION_RESOLVE_RETRY| + GETADDR_FATAL; + + + for (i = 0; i < l->len; ++i) + { + int status; + const char *remote; + int flags = preresolve_flags; + + struct connection_entry* ce = c->options.connection_list->array[i]; + + 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; + + /* HTTP remote hostname does not need to be resolved */ + if (! ce->http_proxy_options) + { + status = do_preresolve_host (c, remote, ce->remote_port, ce->af, flags); + if (status != 0) + goto err; + } + + /* Preresolve proxy */ + if (ce->http_proxy_options) + { + status = do_preresolve_host (c, + ce->http_proxy_options->server, + ce->http_proxy_options->port, + ce->af, + preresolve_flags); + + if (status != 0) + goto err; + } + + if (ce->socks_proxy_server) + { + status = do_preresolve_host (c, + ce->socks_proxy_server, + ce->socks_proxy_port, + ce->af, + flags); + if (status != 0) + goto err; + } + + if (ce->bind_local) + { + flags |= GETADDR_PASSIVE; + flags &= ~GETADDR_RANDOMIZE; + status = do_preresolve_host (c, ce->local, ce->local_port, ce->af, flags); + if (status != 0) + goto err; + + } + + } + return; + + err: + throw_signal_soft (SIGHUP, "Preresolving failed"); +} /* * Translate IPv4/IPv6 addr or hostname into struct addrinfo @@ -155,7 +328,7 @@ openvpn_getaddrinfo (unsigned int flags, print_hostname = hostname; else print_hostname = "undefined"; - + if(servname) print_servname = servname; else @@ -172,11 +345,10 @@ openvpn_getaddrinfo (unsigned int flags, CLEAR(hints); hints.ai_family = ai_family; hints.ai_flags = AI_NUMERICHOST; - hints.ai_socktype = SOCK_STREAM; - + if(flags & GETADDR_PASSIVE) hints.ai_flags |= AI_PASSIVE; - + if(flags & GETADDR_DATAGRAM) hints.ai_socktype = SOCK_DGRAM; else @@ -192,7 +364,7 @@ openvpn_getaddrinfo (unsigned int flags, ((resolve_retry_seconds + 4)/ fail_wait_interval); const char *fmt; int level = 0; - + fmt = "RESOLVE: Cannot resolve host address: %s:%s (%s)"; if ((flags & GETADDR_MENTION_RESOLVE_RETRY) && !resolve_retry_seconds) @@ -276,8 +448,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 * */ } @@ -597,11 +769,14 @@ link_socket_update_buffer_sizes (struct link_socket *ls, int rcvbuf, int sndbuf) */ socket_descriptor_t -create_socket_tcp (int af) +create_socket_tcp (struct addrinfo* addrinfo) { socket_descriptor_t sd; - if ((sd = socket (af, SOCK_STREAM, IPPROTO_TCP)) < 0) + ASSERT (addrinfo); + ASSERT (addrinfo->ai_socktype == SOCK_STREAM); + + if ((sd = socket (addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol)) < 0) msg (M_ERR, "Cannot create TCP socket"); #ifndef WIN32 /* using SO_REUSEADDR on Windows will cause bind to succeed on port conflicts! */ @@ -618,17 +793,20 @@ create_socket_tcp (int af) } static socket_descriptor_t -create_socket_udp (const int af, const unsigned int flags) +create_socket_udp (struct addrinfo* addrinfo, const unsigned int flags) { socket_descriptor_t sd; - if ((sd = socket (af, SOCK_DGRAM, IPPROTO_UDP)) < 0) + ASSERT (addrinfo); + ASSERT (addrinfo->ai_socktype == SOCK_DGRAM); + + if ((sd = socket (addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol)) < 0) msg (M_ERR, "UDP: Cannot create UDP/UDP6 socket"); #if ENABLE_IP_PKTINFO else if (flags & SF_USE_IP_PKTINFO) { int pad = 1; - if(af == AF_INET) + if(addrinfo->ai_family == AF_INET) { #ifdef IP_PKTINFO if (setsockopt (sd, SOL_IP, IP_PKTINFO, @@ -641,8 +819,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 (addrinfo->ai_family == AF_INET6 ) { #ifndef IPV6_RECVPKTINFO /* Some older Darwin platforms require this */ if (setsockopt (sd, IPPROTO_IPV6, IPV6_PKTINFO, @@ -658,75 +836,91 @@ create_socket_udp (const int af, const unsigned int flags) return sd; } -static void -create_socket (struct link_socket *sock) +static void bind_local (struct link_socket *sock, const sa_family_t ai_family) { - /* create socket, use information carried over from getaddrinfo */ - const int ai_proto = sock->info.lsa->actual.ai_protocol; - const int ai_family = sock->info.lsa->actual.ai_family; - - ASSERT (sock->info.af == AF_UNSPEC || sock->info.af == ai_family); + /* bind to local address/port */ + if (sock->bind_local) + { + if (sock->socks_proxy && sock->info.proto == PROTO_UDP) + socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local, + ai_family, "SOCKS", false); + else + socket_bind (sock->sd, sock->info.lsa->bind_local, + ai_family, + "TCP/UDP", sock->info.bind_ipv6_only); + } +} - - if (ai_proto == IPPROTO_UDP) +static void +create_socket (struct link_socket* sock, struct addrinfo* addr) +{ + if (addr->ai_protocol == IPPROTO_UDP || addr->ai_socktype == SOCK_DGRAM) { - sock->sd = create_socket_udp (ai_family, sock->sockflags); + sock->sd = create_socket_udp (addr, sock->sockflags); sock->sockflags |= SF_GETADDRINFO_DGRAM; -#ifdef ENABLE_SOCKS + /* Assume that control socket and data socket to the socks proxy + * are using the same IP family */ if (sock->socks_proxy) - sock->ctrl_sd = create_socket_tcp (ai_family); -#endif + { + /* Construct a temporary addrinfo to create the socket, + * currently resolve two remote addresses is not supported, + * TODO: Rewrite the whole resolve_remote */ + struct addrinfo addrinfo_tmp = *addr; + addrinfo_tmp.ai_socktype = SOCK_STREAM; + addrinfo_tmp.ai_protocol = IPPROTO_TCP; + sock->ctrl_sd = create_socket_tcp (&addrinfo_tmp); + } } - else if (ai_proto == IPPROTO_TCP) + else if (addr->ai_protocol == IPPROTO_TCP || addr->ai_socktype == SOCK_STREAM) { - sock->sd = create_socket_tcp (ai_family); + sock->sd = create_socket_tcp (addr); } else { ASSERT (0); } - /* 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); - + + bind_local (sock, addr->ai_family); } #ifdef TARGET_ANDROID -static void protect_fd_nonlocal (int fd, struct sockaddr* addr) +static void protect_fd_nonlocal (int fd, const struct sockaddr* addr) { - if (addr_local (addr)) { - msg(M_DEBUG, "Address is local, not protecting socket fd %d", fd); - return; - } - - struct user_pass up; - strcpy(up.username ,__func__); - management->connection.fdtosend = fd; - msg(M_DEBUG, "Protecting socket fd %d", fd); - management_query_user_pass(management, &up , "PROTECTFD", GET_USER_PASS_NEED_OK,(void*) 0); + /* pass socket FD to management interface to pass on to VPNService API + * as "protected socket" (exempt from being routed into tunnel) + */ + if (addr_local (addr)) { + msg(M_DEBUG, "Address is local, not protecting socket fd %d", fd); + return; + } + msg(M_DEBUG, "Protecting socket fd %d", fd); + management->connection.fdtosend = fd; + management_android_control (management, "PROTECTFD", __func__); } #endif - /* * Functions used for establishing a TCP stream connection. */ static void socket_do_listen (socket_descriptor_t sd, - const struct sockaddr *local, + const struct addrinfo *local, bool do_listen, bool do_set_nonblock) { struct gc_arena gc = gc_new (); if (do_listen) { + ASSERT(local); msg (M_INFO, "Listening for incoming TCP connection on %s", - print_sockaddr (local, &gc)); + print_sockaddr (local->ai_addr, &gc)); if (listen (sd, 1)) msg (M_ERR, "TCP: listen() failed"); } @@ -819,7 +1013,7 @@ socket_listen_accept (socket_descriptor_t sd, int new_sd = SOCKET_UNDEFINED; CLEAR (*act); - socket_do_listen (sd, local->ai_addr, do_listen, true); + socket_do_listen (sd, local, do_listen, true); while (true) { @@ -854,7 +1048,7 @@ socket_listen_accept (socket_descriptor_t sd, if (socket_defined (new_sd)) { - struct addrinfo* ai; + struct addrinfo* ai = NULL; if(remote_dynamic) openvpn_getaddrinfo(0, remote_dynamic, NULL, 1, NULL, remote_verify.addr.sa.sa_family, &ai); @@ -891,7 +1085,8 @@ void socket_bind (socket_descriptor_t sd, struct addrinfo *local, int ai_family, - const char *prefix) + const char *prefix, + bool ipv6only) { struct gc_arena gc = gc_new (); @@ -901,10 +1096,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? */ - - ASSERT(local); + struct addrinfo* cur; - + + ASSERT(local); + + /* find the first addrinfo with correct ai_family */ for (cur = local; cur; cur=cur->ai_next) { @@ -914,7 +1111,17 @@ socket_bind (socket_descriptor_t sd, if (!cur) msg (M_FATAL, "%s: Socket bind failed: Addr to bind has no %s record", prefix, addr_family_name(ai_family)); - + + if (ai_family == AF_INET6) + { + int v6only = ipv6only ? 1: 0; /* setsockopt must have an "int" */ + + msg (M_INFO, "setsockopt(IPV6_V6ONLY=%d)", v6only); + if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only))) + { + msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY=%d failed", v6only); + } + } if (bind (sd, cur->ai_addr, cur->ai_addrlen)) { const int errnum = openvpn_errno (); @@ -934,12 +1141,13 @@ openvpn_connect (socket_descriptor_t sd, { int status = 0; +#ifdef TARGET_ANDROID + protect_fd_nonlocal(sd, remote); +#endif + #ifdef CONNECT_NONBLOCK set_nonblock (sd); - - protect_fd_nonlocal(sd, remote); status = connect (sd, remote, af_addr_size(remote->sa_family)); - if (status) status = openvpn_errno (); if ( @@ -1015,7 +1223,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); @@ -1024,24 +1232,18 @@ 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; - actual->ai_socktype = ai->ai_socktype; + } void -socket_connect (socket_descriptor_t *sd, - struct link_socket_addr *lsa, +socket_connect (socket_descriptor_t* sd, + const struct sockaddr* dest, const int connect_timeout, struct signal_info* sig_info) { 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)); @@ -1049,14 +1251,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 */ @@ -1139,41 +1341,34 @@ resolve_bind_local (struct link_socket *sock, const sa_family_t af) if (!sock->info.lsa->bind_local) { int flags = GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | - GETADDR_FATAL | GETADDR_PASSIVE; + GETADDR_FATAL | GETADDR_PASSIVE; int status; - + if(proto_is_dgram(sock->info.proto)) - flags |= GETADDR_DATAGRAM; - + flags |= GETADDR_DATAGRAM; + /* will return AF_{INET|INET6}from local_host */ - status = openvpn_getaddrinfo(flags, sock->local_host, sock->local_port, 0, - NULL, af, &sock->info.lsa->bind_local); + status = get_cached_dns_entry (sock->dns_cache, + sock->local_host, + sock->local_port, + af, + flags, + &sock->info.lsa->bind_local); + + if (status) + status = openvpn_getaddrinfo(flags, sock->local_host, sock->local_port, 0, + NULL, af, &sock->info.lsa->bind_local); + if(status !=0) { - msg (M_FATAL, "getaddrinfo() failed for local \"%s:%s\": %s", - sock->local_host, sock->local_port, - gai_strerror(status)); + msg (M_FATAL, "getaddrinfo() failed for local \"%s:%s\": %s", + sock->local_host, sock->local_port, + gai_strerror(status)); } } gc_free (&gc); } -static void bind_local (struct link_socket *sock) -{ - /* bind to local address/port */ - if (sock->bind_local) - { -#ifdef ENABLE_SOCKS - if (sock->socks_proxy && sock->info.proto == PROTO_UDP) - socket_bind (sock->ctrl_sd, sock->info.lsa->bind_local, - sock->info.lsa->actual.ai_family, "SOCKS"); - else -#endif - socket_bind (sock->sd, sock->info.lsa->bind_local, - sock->info.lsa->actual.ai_family, "TCP/UDP"); - } -} - static void resolve_remote (struct link_socket *sock, int phase, @@ -1182,103 +1377,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) { - unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags); - int retry = 0; - int status = -1; - - 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) + { + 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); + } - struct addrinfo* ai; - 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; - } + + status = get_cached_dns_entry (sock->dns_cache, + sock->remote_host, + sock->remote_port, + sock->info.af, + flags, &ai); + if (status) + 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) *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 ....*/ + /* 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 + { + CLEAR (sock->info.lsa->actual); + if(sock->info.lsa->current_remote) { - CLEAR (sock->info.lsa->actual); - if(sock->info.lsa->current_remote) - { - set_actual_address (&sock->info.lsa->actual, - 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; } done: @@ -1294,61 +1490,24 @@ link_socket_new (void) ALLOC_OBJ_CLEAR (sock, struct link_socket); sock->sd = SOCKET_UNDEFINED; -#ifdef ENABLE_SOCKS sock->ctrl_sd = SOCKET_UNDEFINED; -#endif return sock; } void -create_new_socket (struct link_socket* sock) -{ - if (sock->bind_local) { - 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.af && sock->info.lsa->actual.ai_family==0 && sock->bind_local) - { - /* Copy sock parameters from bind addr */ - set_actual_address (&sock->info.lsa->actual, sock->info.lsa->bind_local); - /* 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 && sock->info.lsa->actual.ai_family) - { - create_socket (sock); - - if (sock->bind_local) - bind_local(sock); - } -} - - -/* bind socket if necessary */ -void link_socket_init_phase1 (struct link_socket *sock, const char *local_host, const char *local_port, const char *remote_host, const char *remote_port, + struct cached_dns_entry *dns_cache, int proto, - sa_family_t af, + sa_family_t af, + bool bind_ipv6_only, int mode, const struct link_socket *accept_from, -#ifdef ENABLE_HTTP_PROXY struct http_proxy_info *http_proxy, -#endif -#ifdef ENABLE_SOCKS struct socks_proxy_info *socks_proxy, -#endif #ifdef ENABLE_DEBUG int gremlin, #endif @@ -1372,15 +1531,9 @@ link_socket_init_phase1 (struct link_socket *sock, sock->local_port = local_port; sock->remote_host = remote_host; sock->remote_port = remote_port; - -#ifdef ENABLE_HTTP_PROXY + sock->dns_cache = dns_cache; sock->http_proxy = http_proxy; -#endif - -#ifdef ENABLE_SOCKS sock->socks_proxy = socks_proxy; -#endif - sock->bind_local = bind_local; sock->inetd = inetd; sock->resolve_retry_seconds = resolve_retry_seconds; @@ -1401,6 +1554,7 @@ link_socket_init_phase1 (struct link_socket *sock, sock->info.af = af; sock->info.remote_float = remote_float; sock->info.lsa = lsa; + sock->info.bind_ipv6_only = bind_ipv6_only; sock->info.ipchange_command = ipchange_command; sock->info.plugins = plugins; @@ -1412,10 +1566,9 @@ link_socket_init_phase1 (struct link_socket *sock, ASSERT (!sock->inetd); sock->sd = accept_from->sd; } - + if (false) ; -#ifdef ENABLE_HTTP_PROXY /* are we running in HTTP proxy mode? */ else if (sock->http_proxy) { @@ -1430,12 +1583,9 @@ link_socket_init_phase1 (struct link_socket *sock, sock->proxy_dest_host = remote_host; sock->proxy_dest_port = remote_port; } -#endif -#ifdef ENABLE_SOCKS /* or in Socks proxy mode? */ else if (sock->socks_proxy) { - ASSERT (sock->info.af == AF_INET); ASSERT (!sock->inetd); /* the proxy server */ @@ -1446,7 +1596,6 @@ link_socket_init_phase1 (struct link_socket *sock, sock->proxy_dest_host = remote_host; sock->proxy_dest_port = remote_port; } -#endif else { sock->remote_host = remote_host; @@ -1454,7 +1603,7 @@ link_socket_init_phase1 (struct link_socket *sock, } /* bind behavior for TCP server vs. client */ - if (sock->info.proto == PROTO_TCP_SERVER && sock->info.af==AF_INET) + if (sock->info.proto == PROTO_TCP_SERVER) { if (sock->mode == LS_MODE_TCP_ACCEPT_FROM) sock->bind_local = false; @@ -1471,13 +1620,16 @@ link_socket_init_phase1 (struct link_socket *sock, } else if (mode != LS_MODE_TCP_ACCEPT_FROM) { - create_new_socket (sock); + if (sock->bind_local) { + resolve_bind_local (sock, sock->info.af); + } + resolve_remote (sock, 1, NULL, NULL); } } static void phase2_inetd (struct link_socket* sock, const struct frame *frame, - const char *remote_dynamic, volatile int *signal_received) + const char *remote_dynamic, volatile int *signal_received) { bool remote_changed = false; @@ -1490,27 +1642,28 @@ void phase2_inetd (struct link_socket* sock, const struct frame *frame, struct openvpn_sockaddr local_addr; socklen_t addrlen = sizeof(local_addr); if (getsockname (sock->sd, &local_addr.addr.sa, &addrlen) == 0) { - sock->info.lsa->actual.dest.addr.sa.sa_family = local_addr.addr.sa.sa_family; - dmsg (D_SOCKET_DEBUG, "inetd(%s): using sa_family=%d from getsockname(%d)", - proto2ascii(sock->info.proto, sock->info.af, false), local_addr.addr.sa.sa_family, - sock->sd); + sock->info.lsa->actual.dest.addr.sa.sa_family = local_addr.addr.sa.sa_family; + dmsg (D_SOCKET_DEBUG, "inetd(%s): using sa_family=%d from getsockname(%d)", + proto2ascii(sock->info.proto, sock->info.af, false), + local_addr.addr.sa.sa_family, sock->sd); } else - msg (M_WARN, "inetd(%s): getsockname(%d) failed, using AF_INET", - proto2ascii(sock->info.proto, sock->info.af, false), sock->sd); + msg (M_WARN, "inetd(%s): getsockname(%d) failed, using AF_INET", + proto2ascii(sock->info.proto, sock->info.af, false), sock->sd); } #else msg (M_WARN, "inetd(%s): this OS does not provide the getsockname() " - "function, using AF_INET", - proto2ascii(sock->info.proto, false)); + "function, using AF_INET", + proto2ascii(sock->info.proto, false)); #endif sock->sd = socket_listen_accept (sock->sd, - &sock->info.lsa->actual, - remote_dynamic, - sock->info.lsa->bind_local, - false, - sock->inetd == INETD_NOWAIT, - signal_received); + &sock->info.lsa->actual, + remote_dynamic, + sock->info.lsa->bind_local, + false, + sock->inetd == INETD_NOWAIT, + signal_received); + } ASSERT (!remote_changed); } @@ -1528,10 +1681,8 @@ phase2_set_socket_flags (struct link_socket* sock) scripts don't have access to it */ set_cloexec (sock->sd); -#ifdef ENABLE_SOCKS if (socket_defined (sock->ctrl_sd)) set_cloexec (sock->ctrl_sd); -#endif /* set Path MTU discovery options on the socket */ set_mtu_discover_type (sock->sd, sock->mtu_discover_type); @@ -1547,171 +1698,161 @@ 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", - 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)); - } + if (sock->inetd) + msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, sock->info.af, true)); + else if (sock->bind_local) + { + sa_family_t ai_family = sock->info.lsa->actual.dest.addr.sa.sa_family; + /* Socket is always bound on the first matching address, + * For bound sockets with no remote addr this is the element of + * the list */ + struct addrinfo *cur; + for (cur = sock->info.lsa->bind_local; cur; cur=cur->ai_next) + { + if(!ai_family || ai_family == cur->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)); gc_free(&gc); } static void phase2_tcp_server (struct link_socket *sock, const char *remote_dynamic, - volatile int *signal_received) + volatile int *signal_received) { switch (sock->mode) { case LS_MODE_DEFAULT: sock->sd = socket_listen_accept (sock->sd, - &sock->info.lsa->actual, - remote_dynamic, - sock->info.lsa->bind_local, - true, - false, - signal_received); + &sock->info.lsa->actual, + remote_dynamic, + sock->info.lsa->bind_local, + true, + false, + signal_received); break; case LS_MODE_TCP_LISTEN: socket_do_listen (sock->sd, - sock->info.lsa->bind_local->ai_addr, - true, - false); + sock->info.lsa->bind_local, + true, + false); break; case LS_MODE_TCP_ACCEPT_FROM: sock->sd = socket_do_accept (sock->sd, - &sock->info.lsa->actual, - false); + &sock->info.lsa->actual, + false); if (!socket_defined (sock->sd)) - { - *signal_received = SIGTERM; - return; - } + { + *signal_received = SIGTERM; + return; + } tcp_connection_established (&sock->info.lsa->actual); break; default: ASSERT (0); } - } static void phase2_tcp_client (struct link_socket *sock, struct signal_info *sig_info) { -#ifdef GENERAL_PROXY_SUPPORT - bool proxy_retry = false; -#else - const bool proxy_retry = false; -#endif - do { - socket_connect (&sock->sd, - sock->info.lsa, - sock->connect_timeout, - sig_info); - - if (sig_info->signal_received) - return; - - if (false) - ; -#ifdef ENABLE_HTTP_PROXY - else if (sock->http_proxy) - { - proxy_retry = establish_http_proxy_passthru (sock->http_proxy, - sock->sd, - sock->proxy_dest_host, - sock->proxy_dest_port, - &sock->stream_buf.residual, - &sig_info->signal_received); - } -#endif -#ifdef ENABLE_SOCKS - else if (sock->socks_proxy) - { - establish_socks_proxy_passthru (sock->socks_proxy, - sock->sd, - sock->proxy_dest_host, - sock->proxy_dest_port, - &sig_info->signal_received); - } -#endif - if (proxy_retry) - { - /* TODO (schwabe): This code assumes AF_INET for the proxy socket - * when retrying a connection */ - openvpn_close_socket (sock->sd); - sock->sd = create_socket_tcp (AF_INET); - } - } while (proxy_retry); + bool proxy_retry = false; + do { + socket_connect (&sock->sd, + sock->info.lsa->current_remote->ai_addr, + sock->connect_timeout, + sig_info); + + if (sig_info->signal_received) + return; + + if (false) + ; + else if (sock->http_proxy) + { + proxy_retry = establish_http_proxy_passthru (sock->http_proxy, + sock->sd, + sock->proxy_dest_host, + sock->proxy_dest_port, + &sock->stream_buf.residual, + &sig_info->signal_received); + } + else if (sock->socks_proxy) + { + establish_socks_proxy_passthru (sock->socks_proxy, + sock->sd, + sock->proxy_dest_host, + sock->proxy_dest_port, + &sig_info->signal_received); + } + if (proxy_retry) + { + openvpn_close_socket (sock->sd); + sock->sd = create_socket_tcp (sock->info.lsa->current_remote); + } + + } while (proxy_retry); } -#ifdef ENABLE_SOCKS static void phase2_socks_client (struct link_socket *sock, struct signal_info *sig_info) { socket_connect (&sock->ctrl_sd, - sock->info.lsa, - sock->connect_timeout, - sig_info); - + sock->info.lsa->current_remote->ai_addr, + sock->connect_timeout, + sig_info); + if (sig_info->signal_received) - return; - + return; + establish_socks_proxy_udpassoc (sock->socks_proxy, - sock->ctrl_sd, - sock->sd, - &sock->socks_relay.dest, - &sig_info->signal_received); - + sock->ctrl_sd, + sock->sd, + &sock->socks_relay.dest, + &sig_info->signal_received); + if (sig_info->signal_received) - return; - + return; + 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) - freeaddrinfo(sock->info.lsa->remote_list); - + { + freeaddrinfo(sock->info.lsa->remote_list); + sock->info.lsa->current_remote = NULL; + sock->info.lsa->remote_list = NULL; + } + resolve_remote (sock, 1, NULL, &sig_info->signal_received); - } -#endif /* finalize socket initialization */ void link_socket_init_phase2 (struct link_socket *sock, - const struct frame *frame, - struct signal_info *sig_info) + const struct frame *frame, + struct signal_info *sig_info) { const char *remote_dynamic = NULL; int sig_save = 0; @@ -1740,69 +1881,77 @@ link_socket_init_phase2 (struct link_socket *sock, { phase2_inetd (sock, frame, remote_dynamic, &sig_info->signal_received); if (sig_info && sig_info->signal_received) - goto done; + goto done; } else { /* Second chance to resolv/create socket */ resolve_remote (sock, 2, &remote_dynamic, &sig_info->signal_received); - + + /* If a valid remote has been found, create the socket with its addrinfo */ + if (sock->info.lsa->current_remote) + create_socket (sock, sock->info.lsa->current_remote); + /* If socket has not already been created create it now */ if (sock->sd == SOCKET_UNDEFINED) - { - if (sock->info.lsa->actual.ai_family) - { - create_socket (sock); - } - else - { - msg (M_WARN, "Could not determine IPv4/IPv6 protocol"); - sig_info->signal_received = SIGUSR1; - goto done; - } - - if (sock->bind_local) - bind_local(sock); - } + { + /* If we have no --remote and have still not figured out the + * protocol family to use we will use the first of the bind */ + + if (sock->bind_local && !sock->remote_host && sock->info.lsa->bind_local) + { + /* Warn if this is because neither v4 or v6 was specified + * and we should not connect a remote */ + if (sock->info.af == AF_UNSPEC) + msg (M_WARN, "Could not determine IPv4/IPv6 protocol. Using %s", + addr_family_name(sock->info.lsa->bind_local->ai_family)); + + create_socket (sock, sock->info.lsa->bind_local); + } + } + + /* Socket still undefined, give a warning and abort connection */ + if (sock->sd == SOCKET_UNDEFINED) + { + msg (M_WARN, "Could not determine IPv4/IPv6 protocol"); + sig_info->signal_received = SIGUSR1; + goto done; + } - if (sig_info && sig_info->signal_received) - goto done; + goto done; if (sock->info.proto == PROTO_TCP_SERVER) - { - phase2_tcp_server (sock, remote_dynamic, - &sig_info->signal_received); - } + { + phase2_tcp_server (sock, remote_dynamic, + &sig_info->signal_received); + } else if (sock->info.proto == PROTO_TCP_CLIENT) - { - phase2_tcp_client (sock, sig_info); - - } - else if (sock->info.proto == PROTO_UDP) - { -#ifdef ENABLE_SOCKS - if (sock->info.proto == PROTO_UDP && sock->socks_proxy) - { - phase2_socks_client (sock, sig_info); -#endif - } - protect_fd_nonlocal (sock->sd, &sock->info.lsa->actual.dest.addr.sa); - } + { + phase2_tcp_client (sock, sig_info); + } + else if (sock->info.proto == PROTO_UDP && sock->socks_proxy) + { + phase2_socks_client (sock, sig_info); + } +#ifdef TARGET_ANDROID + if (sock->sd != -1) + protect_fd_nonlocal (sock->sd, &sock->info.lsa->actual.dest.addr.sa); +#endif if (sig_info && sig_info->signal_received) - goto done; + goto done; } phase2_set_socket_flags(sock); linksock_print_addr(sock); - + done: if (sig_save && sig_info) { if (!sig_info->signal_received) - sig_info->signal_received = sig_save; + sig_info->signal_received = sig_save; } } @@ -1838,14 +1987,12 @@ link_socket_close (struct link_socket *sock) #endif } -#ifdef ENABLE_SOCKS if (socket_defined (sock->ctrl_sd)) { if (openvpn_close_socket (sock->ctrl_sd)) msg (M_WARN | M_ERRNO, "TCP/UDP: Close Socket (ctrl_sd) failed"); sock->ctrl_sd = SOCKET_UNDEFINED; } -#endif stream_buf_close (&sock->stream_buf); free_buf (&sock->stream_buf_data); @@ -2251,10 +2398,10 @@ print_sockaddr_ex (const struct sockaddr *sa, { if (separator) buf_puts (&out, separator); - + buf_puts (&out, servname); } - + return BSTR (&out); } @@ -2468,12 +2615,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}, @@ -2535,7 +2687,7 @@ proto2ascii (int proto, sa_family_t af, bool display_form) unsigned int i; for (i = 0; i < SIZE (proto_names); ++i) { - if(proto_names[i].proto_af == af && proto_names[i].proto == proto) + if(proto_names[i].proto_af == af && proto_names[i].proto == proto) { if(display_form) return proto_names[i].display_form; @@ -2562,30 +2714,6 @@ proto2ascii_all (struct gc_arena *gc) return BSTR (&out); } -int -addr_guess_family(sa_family_t af, const char *name) -{ - unsigned short ret; - if (af) - { - return af; /* already stamped */ - } - else - { - struct addrinfo hints , *ai; - int err; - CLEAR(hints); - hints.ai_flags = AI_NUMERICHOST; - err = getaddrinfo(name, NULL, &hints, &ai); - if ( 0 == err ) - { - ret=ai->ai_family; - freeaddrinfo(ai); - return ret; - } - } - return AF_INET; /* default */ -} const char * addr_family_name (int af) { @@ -2615,13 +2743,16 @@ proto_remote (int proto, bool remote) ASSERT (proto >= 0 && proto < PROTO_N); if (proto == PROTO_UDP) return "UDPv4"; - - if ( (remote && proto == PROTO_TCP_CLIENT) || proto == PROTO_TCP_SERVER) + + if ( (remote && proto == PROTO_TCP_CLIENT) || + (!remote && proto == PROTO_TCP_SERVER)) return "TCPv4_SERVER"; - if ( (remote && proto == PROTO_TCP_SERVER) || proto == PROTO_TCP_CLIENT) + if ( (remote && proto == PROTO_TCP_SERVER) || + (!remote && proto == PROTO_TCP_CLIENT)) return "TCPv4_CLIENT"; ASSERT (0); + return ""; /* Make the compiler happy */ } /* @@ -2757,7 +2888,12 @@ link_socket_read_udp_posix_recvmsg (struct link_socket *sock, from->pi.in6.ipi6_ifindex = pkti6->ipi6_ifindex; from->pi.in6.ipi6_addr = pkti6->ipi6_addr; } + else if (cmsg != NULL) + { + msg(M_WARN, "CMSG received that cannot be parsed (cmsg_level=%d, cmsg_type=%d, cmsg=len=%d)", (int)cmsg->cmsg_level, (int)cmsg->cmsg_type, (int)cmsg->cmsg_len ); + } } + return fromlen; } #endif @@ -2774,7 +2910,7 @@ link_socket_read_udp_posix (struct link_socket *sock, ASSERT (buf_safe (buf, maxsize)); #if ENABLE_IP_PKTINFO /* Both PROTO_UDPv4 and PROTO_UDPv6 */ - if (proto_is_udp(sock->info.proto) && sock->sockflags & SF_USE_IP_PKTINFO) + if (sock->info.proto == PROTO_UDP && sock->sockflags & SF_USE_IP_PKTINFO) fromlen = link_socket_read_udp_posix_recvmsg (sock, buf, maxsize, from); else #endif @@ -2818,24 +2954,24 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock, struct iovec iov; struct msghdr mesg; struct cmsghdr *cmsg; + union openvpn_pktinfo opi; iov.iov_base = BPTR (buf); iov.iov_len = BLEN (buf); mesg.msg_iov = &iov; mesg.msg_iovlen = 1; - switch (to->ai_family) + switch (to->dest.addr.sa.sa_family) { case AF_INET: { - struct openvpn_in4_pktinfo msgpi4; mesg.msg_name = &to->dest.addr.sa; mesg.msg_namelen = sizeof (struct sockaddr_in); - mesg.msg_control = &msgpi4; - mesg.msg_controllen = sizeof msgpi4; + mesg.msg_control = &opi; mesg.msg_flags = 0; +#ifdef HAVE_IN_PKTINFO + mesg.msg_controllen = sizeof (struct openvpn_in4_pktinfo); cmsg = CMSG_FIRSTHDR (&mesg); cmsg->cmsg_len = sizeof (struct openvpn_in4_pktinfo); -#ifdef HAVE_IN_PKTINFO cmsg->cmsg_level = SOL_IP; cmsg->cmsg_type = IP_PKTINFO; { @@ -2846,6 +2982,10 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock, pkti->ipi_addr.s_addr = 0; } #elif defined(IP_RECVDSTADDR) + ASSERT( CMSG_SPACE(sizeof (struct in_addr)) <= sizeof(opi) ); + mesg.msg_controllen = CMSG_SPACE(sizeof (struct in_addr)); + cmsg = CMSG_FIRSTHDR (&mesg); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); cmsg->cmsg_level = IPPROTO_IP; cmsg->cmsg_type = IP_RECVDSTADDR; *(struct in_addr *) CMSG_DATA (cmsg) = to->pi.in4; @@ -2856,12 +2996,11 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock, } case AF_INET6: { - struct openvpn_in6_pktinfo msgpi6; struct in6_pktinfo *pkti6; mesg.msg_name = &to->dest.addr.sa; mesg.msg_namelen = sizeof (struct sockaddr_in6); - mesg.msg_control = &msgpi6; - mesg.msg_controllen = sizeof msgpi6; + mesg.msg_control = &opi; + mesg.msg_controllen = sizeof (struct openvpn_in6_pktinfo); mesg.msg_flags = 0; cmsg = CMSG_FIRSTHDR (&mesg); cmsg->cmsg_len = sizeof (struct openvpn_in6_pktinfo); @@ -2921,10 +3060,10 @@ socket_recv_queue (struct link_socket *sock, int maxsize) if (proto_is_udp(sock->info.proto)) { sock->reads.addr_defined = true; - if (sock->info.proto == PROTO_UDPv6) - sock->reads.addrlen = sizeof (sock->reads.addr6); - else + if (sock->info.af == AF_INET) sock->reads.addrlen = sizeof (sock->reads.addr); + else + sock->reads.addrlen = sizeof (sock->reads.addr6); status = WSARecvFrom( sock->sd, wsabuf, @@ -3020,7 +3159,7 @@ socket_send_queue (struct link_socket *sock, struct buffer *buf, const struct li { /* set destination address for UDP writes */ sock->writes.addr_defined = true; - if (sock->info.proto == PROTO_UDPv6) + if (sock->info.af == AF_INET6) { sock->writes.addr6 = to->dest.addr.in6; sock->writes.addrlen = sizeof (sock->writes.addr6); |