diff options
author | Arne Schwabe <arne@rfc2549.org> | 2013-12-05 07:07:51 +0100 |
---|---|---|
committer | Arne Schwabe <arne@rfc2549.org> | 2013-12-05 07:07:51 +0100 |
commit | 137cc5c10327306f0dc15f063e069d2cbc497519 (patch) | |
tree | 57951d2ac173a6738315fb422a6cefd4a2a1a9f4 /openvpn/src | |
parent | ac1934d9e06d72fbe5bdacd5c0c1a89a377e508d (diff) |
Add pre resolve patch
Diffstat (limited to 'openvpn/src')
-rw-r--r-- | openvpn/src/openvpn/init.c | 37 | ||||
-rw-r--r-- | openvpn/src/openvpn/manage.c | 2 | ||||
-rw-r--r-- | openvpn/src/openvpn/options.c | 23 | ||||
-rw-r--r-- | openvpn/src/openvpn/options.h | 6 | ||||
-rw-r--r-- | openvpn/src/openvpn/push.c | 3 | ||||
-rw-r--r-- | openvpn/src/openvpn/socket.c | 360 | ||||
-rw-r--r-- | openvpn/src/openvpn/socket.h | 98 | ||||
-rw-r--r-- | openvpn/src/openvpn/ssl_openssl.c | 3 | ||||
-rw-r--r-- | openvpn/src/openvpn/tun.c | 4 |
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, |