summaryrefslogtreecommitdiff
path: root/openvpn/src
diff options
context:
space:
mode:
Diffstat (limited to 'openvpn/src')
-rw-r--r--openvpn/src/openvpn/init.c37
-rw-r--r--openvpn/src/openvpn/manage.c2
-rw-r--r--openvpn/src/openvpn/options.c23
-rw-r--r--openvpn/src/openvpn/options.h6
-rw-r--r--openvpn/src/openvpn/push.c3
-rw-r--r--openvpn/src/openvpn/socket.c360
-rw-r--r--openvpn/src/openvpn/socket.h98
-rw-r--r--openvpn/src/openvpn/ssl_openssl.c3
-rw-r--r--openvpn/src/openvpn/tun.c4
9 files changed, 319 insertions, 217 deletions
diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c
index 1beca959..5979e0bb 100644
--- a/openvpn/src/openvpn/init.c
+++ b/openvpn/src/openvpn/init.c
@@ -1,4 +1,4 @@
-/*
+ /*
* OpenVPN -- An application to securely tunnel IP networks
* over a single TCP/UDP port, with support for SSL/TLS-based
* session authentication and key exchange,
@@ -306,9 +306,9 @@ init_connection_list (struct context *c)
/*
* Clear the remote address list
*/
-static void clear_remote_addrlist (struct link_socket_addr *lsa)
+static void clear_remote_addrlist (struct link_socket_addr *lsa, bool freeaddr)
{
- if (lsa->remote_list) {
+ if (lsa->remote_list && freeaddr) {
freeaddrinfo(lsa->remote_list);
}
lsa->remote_list = NULL;
@@ -325,7 +325,7 @@ next_connection_entry (struct context *c)
bool ce_defined;
struct connection_entry *ce;
int n_cycles = 0;
-
+
do {
ce_defined = true;
if (c->options.no_advance && l->current >= 0)
@@ -348,19 +348,18 @@ next_connection_entry (struct context *c)
* this is broken probably ever since connection lists and multiple
* remote existed
*/
-
if (!c->options.persist_remote_ip)
- clear_remote_addrlist (&c->c1.link_socket_addr);
+ clear_remote_addrlist (&c->c1.link_socket_addr, !c->options.resolve_in_advance);
else
c->c1.link_socket_addr.current_remote =
c->c1.link_socket_addr.remote_list;
-
+
/*
* Increase the number of connection attempts
* If this is connect-retry-max * size(l)
* OpenVPN will quit
*/
-
+
c->options.unsuccessful_attempts++;
if (++l->current >= l->len)
@@ -399,7 +398,7 @@ next_connection_entry (struct context *c)
}
#endif
} while (!ce_defined);
-
+
/* Check if this connection attempt would bring us over the limit */
if (c->options.connect_retry_max > 0 &&
c->options.unsuccessful_attempts > (l->len * c->options.connect_retry_max))
@@ -560,6 +559,8 @@ context_init_1 (struct context *c)
}
#endif
+ if (c->options.resolve_in_advance)
+ do_preresolve(c);
}
void
@@ -1254,7 +1255,7 @@ void
initialization_sequence_completed (struct context *c, const unsigned int flags)
{
static const char message[] = "Initialization Sequence Completed";
-
+
/* Reset the unsuccessful connection counter on complete initialisation */
c->options.unsuccessful_attempts=0;
@@ -2686,8 +2687,10 @@ do_init_socket_1 (struct context *c, const int mode)
link_socket_init_phase1 (c->c2.link_socket,
c->options.ce.local,
c->options.ce.local_port,
+ c->options.ce.preresolved_local,
c->options.ce.remote,
c->options.ce.remote_port,
+ c->options.ce.preresolved_remote,
c->options.ce.proto,
c->options.ce.af,
c->options.ce.bind_ipv6_only,
@@ -2908,7 +2911,7 @@ do_close_link_socket (struct context *c)
|| c->options.no_advance))
)))
{
- clear_remote_addrlist(&c->c1.link_socket_addr);
+ clear_remote_addrlist(&c->c1.link_socket_addr, !c->options.resolve_in_advance);
}
/* Clear the remote actual address when persist_remote_ip is not in use */
@@ -2916,7 +2919,7 @@ do_close_link_socket (struct context *c)
CLEAR (c->c1.link_socket_addr.actual);
if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_local_ip)) {
- if (c->c1.link_socket_addr.bind_local)
+ if (c->c1.link_socket_addr.bind_local && !c->options.resolve_in_advance)
freeaddrinfo(c->c1.link_socket_addr.bind_local);
c->c1.link_socket_addr.bind_local=NULL;
}
@@ -3359,6 +3362,13 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
goto sig;
}
+ if (c->options.resolve_in_advance)
+ {
+ do_preresolve(c);
+ if (IS_SIG (c))
+ goto sig;
+ }
+
/* map in current connection entry */
next_connection_entry (c);
@@ -3433,7 +3443,7 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
/* allocate our socket object */
if (c->mode == CM_P2P || c->mode == CM_TOP || c->mode == CM_CHILD_TCP)
do_link_socket_new (c);
-
+
#ifdef ENABLE_FRAGMENT
/* initialize internal fragmentation object */
if (options->ce.fragment && (c->mode == CM_P2P || child))
@@ -3795,6 +3805,7 @@ test_crypto_thread (void *arg)
ASSERT (options->test_crypto);
init_verb_mute (c, IVM_LEVEL_1);
context_init_1 (c);
+ next_connection_entry(c);
do_init_crypto_static (c, 0);
frame_finalize_options (c, options);
diff --git a/openvpn/src/openvpn/manage.c b/openvpn/src/openvpn/manage.c
index 8217ead2..352021bd 100644
--- a/openvpn/src/openvpn/manage.c
+++ b/openvpn/src/openvpn/manage.c
@@ -2611,7 +2611,7 @@ management_post_tunnel_open (struct management *man, const in_addr_t tun_local_i
/* listen on our local TUN/TAP IP address */
struct in_addr ia;
int ret;
-
+
ia.s_addr = htonl(tun_local_ip);
ret = openvpn_getaddrinfo(0, inet_ntoa(ia), NULL, 0, NULL,
AF_INET, &man->settings.local);
diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c
index cfbbfb4f..07a9b896 100644
--- a/openvpn/src/openvpn/options.c
+++ b/openvpn/src/openvpn/options.c
@@ -780,7 +780,7 @@ init_options (struct options *o, const bool init_gc)
o->topology = TOP_NET30;
o->ce.proto = PROTO_UDP;
o->ce.af = AF_UNSPEC;
- o->ce.bind_local=false;
+ o->ce.bind_ipv6_only = false;
o->ce.connect_retry_seconds = 5;
o->ce.connect_timeout = 10;
o->connect_retry_max = 0;
@@ -796,6 +796,7 @@ init_options (struct options *o, const bool init_gc)
o->route_delay_window = 30;
o->max_routes = MAX_ROUTES_DEFAULT;
o->resolve_retry_seconds = RESOLV_RETRY_INFINITE;
+ o->resolve_in_advance = false;
o->proto_force = -1;
#ifdef ENABLE_OCC
o->occ = true;
@@ -1369,6 +1370,7 @@ show_connection_entry (const struct connection_entry *o)
SHOW_BOOL (remote_float);
SHOW_BOOL (bind_defined);
SHOW_BOOL (bind_local);
+ SHOW_BOOL (bind_ipv6_only);
SHOW_INT (connect_retry_seconds);
SHOW_INT (connect_timeout);
@@ -1494,6 +1496,7 @@ show_settings (const struct options *o)
#endif
SHOW_INT (resolve_retry_seconds);
+ SHOW_BOOL (resolve_in_advance);
SHOW_STR (username);
SHOW_STR (groupname);
@@ -2038,7 +2041,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
if (ce->socks_proxy_server)
msg (M_USAGE, "--socks-proxy cannot be used with --mode server");
#endif
- /* <connection> blocks force to have a remote embedded, so we check for the
+ /* <connection> blocks force to have a remote embedded, so we check for the
* --remote and bail out if it is present */
if (options->connection_list->len >1 ||
options->connection_list->array[0]->remote)
@@ -2486,6 +2489,7 @@ options_postprocess_verify (const struct options *o)
static void
options_postprocess_mutate (struct options *o)
{
+ int i;
/*
* Process helper-type options which map to other, more complex
* sequences of options.
@@ -2502,13 +2506,12 @@ options_postprocess_mutate (struct options *o)
* Convert remotes into connection list
*/
const struct remote_list *rl = o->remote_list;
- int i;
for (i = 0; i < rl->len; ++i)
{
const struct remote_entry *re = rl->array[i];
struct connection_entry ce = o->ce;
struct connection_entry *ace;
-
+
ASSERT (re->remote);
connection_entry_load_re (&ce, re);
ace = alloc_connection_entry (o, M_USAGE);
@@ -2525,10 +2528,9 @@ options_postprocess_mutate (struct options *o)
}
ASSERT (o->connection_list);
- int i;
for (i = 0; i < o->connection_list->len; ++i)
options_postprocess_mutate_ce (o, o->connection_list->array[i]);
-
+
#if HTTP_PROXY_OVERRIDE
if (o->http_proxy_override)
options_postprocess_http_proxy_override(o);
@@ -4481,6 +4483,15 @@ add_option (struct options *options,
else
options->resolve_retry_seconds = positive_atoi (p[1]);
}
+ else if (streq (p[0], "preresolve") || streq (p[0], "ip-remote-hint"))
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->resolve_in_advance = true;
+ /* Note the ip-remote-hint and the argument p[1] are for
+ backward compatibility */
+ if (p[1])
+ options->ip_remote_hint=p[1];
+ }
else if (streq (p[0], "connect-retry") && p[1])
{
VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
diff --git a/openvpn/src/openvpn/options.h b/openvpn/src/openvpn/options.h
index dda9658a..ddeb8b38 100644
--- a/openvpn/src/openvpn/options.h
+++ b/openvpn/src/openvpn/options.h
@@ -90,9 +90,11 @@ struct connection_entry
sa_family_t af;
const char* local_port;
bool local_port_defined;
- const char* remote_port;
+ const char *remote_port;
const char *local;
const char *remote;
+ struct addrinfo *preresolved_remote;
+ struct addrinfo *preresolved_local;
bool remote_float;
bool bind_defined;
bool bind_ipv6_only;
@@ -278,6 +280,8 @@ struct options
#endif
int resolve_retry_seconds; /* If hostname resolve fails, retry for n seconds */
+ bool resolve_in_advance;
+ const char *ip_remote_hint;
struct tuntap_options tuntap_options;
diff --git a/openvpn/src/openvpn/push.c b/openvpn/src/openvpn/push.c
index 994b7ba7..bd08cff7 100644
--- a/openvpn/src/openvpn/push.c
+++ b/openvpn/src/openvpn/push.c
@@ -49,7 +49,8 @@ void
receive_auth_failed (struct context *c, const struct buffer *buffer)
{
msg (M_VERB0, "AUTH: Received control message: %s", BSTR(buffer));
- c->options.no_advance=true;
+ c->options.no_advance=true;
+
if (c->options.pull)
{
switch (auth_retry_get ())
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},
diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h
index 3f8318f5..8a118cd1 100644
--- a/openvpn/src/openvpn/socket.h
+++ b/openvpn/src/openvpn/socket.h
@@ -85,7 +85,7 @@ struct link_socket_actual
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
-
+
struct openvpn_sockaddr dest;
#if ENABLE_IP_PKTINFO
union {
@@ -104,7 +104,7 @@ struct link_socket_addr
{
struct addrinfo* bind_local;
struct addrinfo* remote_list; /* complete remote list */
- struct addrinfo* current_remote; /* remote used in the
+ struct addrinfo* current_remote; /* remote used in the
current connection attempt */
struct link_socket_actual actual; /* reply to this address */
};
@@ -186,8 +186,10 @@ struct link_socket
const char *remote_host;
const char *remote_port;
+ struct addrinfo *preresolved_remote;
const char *local_host;
const char *local_port;
+ struct addrinfo *preresolved_local;
bool bind_local;
# define INETD_NONE 0
@@ -208,8 +210,6 @@ struct link_socket
int mtu; /* OS discovered MTU, or 0 if unknown */
- bool did_resolve_remote;
-
# define SF_USE_IP_PKTINFO (1<<0)
# define SF_TCP_NODELAY (1<<1)
# define SF_PORT_SHARE (1<<2)
@@ -298,6 +298,8 @@ int openvpn_connect (socket_descriptor_t sd,
int connect_timeout,
volatile int *signal_received);
+
+
/*
* Initialize link_socket object.
*/
@@ -306,8 +308,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,
@@ -340,6 +344,8 @@ void link_socket_init_phase2 (struct link_socket *sock,
const struct frame *frame,
struct signal_info *sig_info);
+void do_preresolve(struct context *c);
+
void socket_adjust_frame_parameters (struct frame *frame, int proto);
void frame_adjust_path_mtu (struct frame *frame, int pmtu, int proto);
@@ -644,35 +650,36 @@ link_socket_actual_defined (const struct link_socket_actual *act)
static inline bool
addr_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2)
{
- switch(a1->addr.sa.sa_family) {
- case AF_INET:
- return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr;
- case AF_INET6:
- return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr);
- }
- ASSERT(0);
- return false;
+ switch(a1->addr.sa.sa_family) {
+ case AF_INET:
+ return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr;
+ case AF_INET6:
+ return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr);
+ }
+ ASSERT(0);
+ return false;
}
static inline bool
addrlist_match (const struct openvpn_sockaddr *a1, const struct addrinfo *addrlist)
{
const struct addrinfo *curele;
- for (curele = addrlist; curele; curele=curele->ai_next) {
-
- switch(a1->addr.sa.sa_family) {
- case AF_INET:
- if (a1->addr.in4.sin_addr.s_addr == ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr)
- return true;
- break;
- case AF_INET6:
- if (IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &((struct sockaddr_in6*) curele->ai_addr)->sin6_addr))
- return true;
- break;
- default:
- ASSERT(0);
+ for (curele = addrlist; curele; curele=curele->ai_next)
+ {
+ switch(a1->addr.sa.sa_family)
+ {
+ case AF_INET:
+ if (a1->addr.in4.sin_addr.s_addr == ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr)
+ return true;
+ break;
+ case AF_INET6:
+ if (IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &((struct sockaddr_in6*) curele->ai_addr)->sin6_addr))
+ return true;
+ break;
+ default:
+ ASSERT(0);
+ }
}
- }
return false;
}
@@ -693,26 +700,28 @@ addr_host (const struct openvpn_sockaddr *addr)
static inline bool
addrlist_port_match (const struct openvpn_sockaddr *a1, const struct addrinfo *a2)
{
- const struct addrinfo *curele;
- for(curele=a2;curele;curele = curele->ai_next) {
- switch(a1->addr.sa.sa_family) {
- case AF_INET:
+ const struct addrinfo *curele;
+ for(curele=a2;curele;curele = curele->ai_next)
+ {
+ switch(a1->addr.sa.sa_family)
+ {
+ case AF_INET:
if (curele->ai_family == AF_INET
&& a1->addr.in4.sin_addr.s_addr == ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr
&& a1->addr.in4.sin_port == ((struct sockaddr_in*)curele->ai_addr)->sin_port)
return true;
break;
- case AF_INET6:
+ case AF_INET6:
if (curele->ai_family == AF_INET6
&& IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &((struct sockaddr_in6*) curele->ai_addr)->sin6_addr)
&& a1->addr.in6.sin6_port == ((struct sockaddr_in6*) curele->ai_addr)->sin6_port)
return true;
break;
- default:
+ default:
ASSERT(0);
}
}
- return false;
+ return false;
}
@@ -725,7 +734,7 @@ addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockadd
return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr
&& a1->addr.in4.sin_port == a2->addr.in4.sin_port;
case AF_INET6:
- return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr)
+ return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr)
&& a1->addr.in6.sin6_port == a2->addr.in6.sin6_port;
}
ASSERT(0);
@@ -734,10 +743,10 @@ addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockadd
static inline bool
addr_match_proto (const struct openvpn_sockaddr *a1,
- const struct openvpn_sockaddr *a2,
- const int proto)
+ const struct openvpn_sockaddr *a2,
+ const int proto)
{
- return link_socket_proto_connection_oriented (proto)
+ return link_socket_proto_connection_oriented (proto)
? addr_match (a1, a2)
: addr_port_match (a1, a2);
}
@@ -745,8 +754,8 @@ addr_match_proto (const struct openvpn_sockaddr *a1,
static inline bool
addrlist_match_proto (const struct openvpn_sockaddr *a1,
- struct addrinfo *addr_list,
- const int proto)
+ struct addrinfo *addr_list,
+ const int proto)
{
return link_socket_proto_connection_oriented (proto)
? addrlist_match (a1, addr_list)
@@ -895,14 +904,15 @@ link_socket_set_outgoing_addr (const struct buffer *buf,
{
struct link_socket_addr *lsa = info->lsa;
if (
- (
/* new or changed address? */
(!info->connection_established
- || !addr_match_proto (&act->dest, &lsa->actual.dest, info->proto))
+ || !addr_match_proto (&act->dest, &lsa->actual.dest, info->proto)
+ )
+ &&
/* address undef or address == remote or --float */
- && (info->remote_float
- || !lsa->remote_list))
- || addrlist_match_proto (&act->dest, lsa->remote_list, info->proto)
+ (info->remote_float ||
+ (!lsa->remote_list || addrlist_match_proto (&act->dest, lsa->remote_list, info->proto))
+ )
)
{
link_socket_connection_initiated (buf, info, act, common_name, es);
diff --git a/openvpn/src/openvpn/ssl_openssl.c b/openvpn/src/openvpn/ssl_openssl.c
index 120aa666..f41bb711 100644
--- a/openvpn/src/openvpn/ssl_openssl.c
+++ b/openvpn/src/openvpn/ssl_openssl.c
@@ -682,10 +682,11 @@ tls_ctx_use_external_private_key (struct tls_root_ctx *ctx,
X509 *cert = NULL;
ASSERT (NULL != ctx);
- ASSERT (NULL != cert);
tls_ctx_load_cert_file_and_copy (ctx, cert_file, cert_file_inline, &cert);
+ ASSERT (NULL != cert);
+
/* allocate custom RSA method object */
ALLOC_OBJ_CLEAR (rsa_meth, RSA_METHOD);
rsa_meth->name = "OpenVPN external private key RSA Method";
diff --git a/openvpn/src/openvpn/tun.c b/openvpn/src/openvpn/tun.c
index c1dcc5e2..9e3e8b9e 100644
--- a/openvpn/src/openvpn/tun.c
+++ b/openvpn/src/openvpn/tun.c
@@ -473,8 +473,8 @@ init_tun (const char *dev, /* --dev option */
* If local_public or remote_public addresses are defined,
* make sure they do not clash with our virtual subnet.
*/
-
- for(curele=remote_public;curele;curele=curele->ai_next) {
+
+ for(curele=local_public;curele;curele=curele->ai_next) {
if(curele->ai_family == AF_INET)
check_addr_clash ("local",
tt->type,