diff options
Diffstat (limited to 'openvpn/src/openvpn/socket.c')
-rw-r--r-- | openvpn/src/openvpn/socket.c | 83 |
1 files changed, 63 insertions, 20 deletions
diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c index 04a21357..29a15a63 100644 --- a/openvpn/src/openvpn/socket.c +++ b/openvpn/src/openvpn/socket.c @@ -234,18 +234,20 @@ openvpn_getaddrinfo (unsigned int flags, get_signal (signal_received); if (*signal_received) /* were we interrupted by a signal? */ { - if (0 == status) { - ASSERT(res); - freeaddrinfo(*res); - res = NULL; - } if (*signal_received == SIGUSR1) /* ignore SIGUSR1 */ { msg (level, "RESOLVE: Ignored SIGUSR1 signal received during DNS resolution attempt"); *signal_received = 0; } else - goto done; + { + if (0 == status) { + ASSERT(res); + freeaddrinfo(*res); + res = NULL; + } + goto done; + } } } @@ -674,7 +676,7 @@ create_socket (struct link_socket *sock) #ifdef ENABLE_SOCKS if (sock->socks_proxy) - sock->ctrl_sd = create_socket_tcp (AF_INET); + sock->ctrl_sd = create_socket_tcp (ai_family); #endif } else if (ai_proto == IPPROTO_TCP) @@ -685,6 +687,12 @@ create_socket (struct link_socket *sock) { 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); + #ifdef TARGET_ANDROID struct user_pass up; strcpy(up.username ,__func__); @@ -895,7 +903,8 @@ socket_bind (socket_descriptor_t sd, break; } if (!cur) - msg (M_FATAL, "%s: Socket bind failed: No addr to bind has no v4/v6 record", prefix); + msg (M_FATAL, "%s: Socket bind failed: Addr to bind has no %s record", + prefix, addr_family_name(ai_family)); if (bind (sd, cur->ai_addr, cur->ai_addrlen)) { @@ -1143,7 +1152,7 @@ static void bind_local (struct link_socket *sock) if (sock->bind_local) { #ifdef ENABLE_SOCKS - if (sock->socks_proxy && sock->info.proto == PROTO_UDP && sock->info.af == AF_INET) + 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 @@ -1280,23 +1289,34 @@ link_socket_new (void) } void -create_new_socket (struct link_socket* sock, int mark) +create_new_socket (struct link_socket* sock) { if (sock->bind_local) { resolve_bind_local (sock, sock->info.af); } resolve_remote (sock, 1, NULL, NULL); - create_socket (sock); - - /* set socket buffers based on --sndbuf and --rcvbuf options */ - socket_set_buffers (sock->sd, &sock->socket_buffer_sizes); + /* + * In P2P or server mode we must create the socket even when resolving + * the remote site fails/is not specified. */ - /* set socket to --mark packets with given value */ - socket_set_mark (sock->sd, mark); - - if (sock->bind_local) - bind_local(sock); + 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); + } } @@ -1363,6 +1383,7 @@ link_socket_init_phase1 (struct link_socket *sock, sock->socket_buffer_sizes.sndbuf = sndbuf; sock->sockflags = sockflags; + sock->mark = mark; sock->info.proto = proto; sock->info.af = af; @@ -1438,7 +1459,7 @@ link_socket_init_phase1 (struct link_socket *sock, } else if (mode != LS_MODE_TCP_ACCEPT_FROM) { - create_new_socket (sock, mark); + create_new_socket (sock); } } @@ -1712,8 +1733,28 @@ link_socket_init_phase2 (struct link_socket *sock, } else { + /* Second chance to resolv/create socket */ resolve_remote (sock, 2, &remote_dynamic, &sig_info->signal_received); + + /* 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 (sig_info && sig_info->signal_received) goto done; @@ -2167,6 +2208,8 @@ print_sockaddr_ex (const struct sockaddr *sa, salen = sizeof (struct sockaddr_in6); addr_is_defined = !IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6*) sa)->sin6_addr); break; + case AF_UNSPEC: + return "[AF_UNSPEC]"; default: ASSERT(0); } |