diff options
-rw-r--r-- | doc/openvpn.8 | 24 | ||||
-rw-r--r-- | src/openvpn/error.c | 2 | ||||
-rw-r--r-- | src/openvpn/init.c | 234 | ||||
-rw-r--r-- | src/openvpn/manage.c | 25 | ||||
-rw-r--r-- | src/openvpn/manage.h | 2 | ||||
-rw-r--r-- | src/openvpn/options.c | 133 | ||||
-rw-r--r-- | src/openvpn/options.h | 26 | ||||
-rw-r--r-- | src/openvpn/ps.c | 8 | ||||
-rw-r--r-- | src/openvpn/push.c | 3 | ||||
-rw-r--r-- | src/openvpn/sig.c | 22 | ||||
-rw-r--r-- | src/openvpn/sig.h | 11 | ||||
-rw-r--r-- | src/openvpn/socket.c | 745 | ||||
-rw-r--r-- | src/openvpn/socket.h | 81 | ||||
-rw-r--r-- | src/openvpn/tun.c | 9 | ||||
-rw-r--r-- | src/openvpn/tun.h | 2 |
15 files changed, 684 insertions, 643 deletions
diff --git a/doc/openvpn.8 b/doc/openvpn.8 index 99b4d22..d5376f9 100644 --- a/doc/openvpn.8 +++ b/doc/openvpn.8 @@ -221,6 +221,9 @@ options. indicates the protocol to use when connecting with the remote, and may be "tcp" or "udp". +For forcing IPv4 or IPv6 connection suffix tcp or udp +with 4/6 like udp4/udp6/tcp4/tcp6. + The client will move on to the next host in the list, in the event of connection failure. Note that at any given time, the OpenVPN client @@ -463,13 +466,9 @@ possess a built-in reliability layer. .\"********************************************************* .TP .B \-\-connect-retry n -For -.B \-\-proto tcp-client, -take +Wait .B n -as the -number of seconds to wait -between connection retries (default=5). +seconds between connection attempts (default=5). .\"********************************************************* .TP .B \-\-connect-timeout n @@ -481,12 +480,15 @@ seconds (default=10). .\"********************************************************* .TP .B \-\-connect-retry-max n -For -.B \-\-proto tcp-client, -take .B n -as the -number of retries of connection attempt (default=infinite). +specifies the number of times all +.B \-\-remote +respectively +.B <connection> +statements are tried. Specifiying +.B n +as one would try each entry exactly once. A sucessful connection +resets the counter. (default=umlimited). .\"********************************************************* .TP .B \-\-show-proxy-settings diff --git a/src/openvpn/error.c b/src/openvpn/error.c index 4a0418a..ebe9a52 100644 --- a/src/openvpn/error.c +++ b/src/openvpn/error.c @@ -259,7 +259,7 @@ void x_msg_va (const unsigned int flags, const char *format, va_list arglist) if (flags & M_SSL) { int nerrs = 0; - int err; + size_t err; while ((err = ERR_get_error ())) { openvpn_snprintf (m2, ERR_BUF_SIZE, "%s: %s", diff --git a/src/openvpn/init.c b/src/openvpn/init.c index e7f733b..41d6fad 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -284,84 +284,127 @@ static void init_connection_list (struct context *c) { struct connection_list *l = c->options.connection_list; - if (l) + + l->current = -1; + if (c->options.remote_random) { - l->current = -1; - if (c->options.remote_random) - { - int i; - for (i = 0; i < l->len; ++i) - { - const int j = get_random () % l->len; - if (i != j) - { - struct connection_entry *tmp; - tmp = l->array[i]; - l->array[i] = l->array[j]; - l->array[j] = tmp; - } - } - } + int i; + for (i = 0; i < l->len; ++i) + { + const int j = get_random () % l->len; + if (i != j) + { + struct connection_entry *tmp; + tmp = l->array[i]; + l->array[i] = l->array[j]; + l->array[j] = tmp; + } + } } } /* + * Clear the remote address list + */ +static void clear_remote_addrlist (struct link_socket_addr *lsa) +{ + if (lsa->remote_list) { + freeaddrinfo(lsa->remote_list); + } + lsa->remote_list = NULL; + lsa->current_remote = NULL; +} + +/* * Increment to next connection entry */ static void next_connection_entry (struct context *c) { struct connection_list *l = c->options.connection_list; - if (l) - { - bool ce_defined; - struct connection_entry *ce; - int n_cycles = 0; + bool ce_defined; + struct connection_entry *ce; + int n_cycles = 0; - do { - ce_defined = true; - if (l->no_advance && l->current >= 0) - { - l->no_advance = false; - } - else - { - if (++l->current >= l->len) - { - l->current = 0; - ++l->n_cycles; - if (++n_cycles >= 2) - msg (M_FATAL, "No usable connection profiles are present"); - } - } + do { + ce_defined = true; + if (c->options.no_advance && l->current >= 0) + { + c->options.no_advance = false; + } + else + { + /* Check if there is another resolved address to try for + * the current connection */ + if (c->c1.link_socket_addr.current_remote && + c->c1.link_socket_addr.current_remote->ai_next) + { + c->c1.link_socket_addr.current_remote = + c->c1.link_socket_addr.current_remote->ai_next; + } + else + { + /* FIXME (schwabe) fix the persist-remote-ip option for real, + * 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); + 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) + { + + l->current = 0; + if (++n_cycles >= 2) + msg (M_FATAL, "No usable connection profiles are present"); + } + } + } - ce = l->array[l->current]; + ce = l->array[l->current]; - if (ce->flags & CE_DISABLED) - ce_defined = false; + if (ce->flags & CE_DISABLED) + ce_defined = false; - c->options.ce = *ce; + c->options.ce = *ce; #ifdef ENABLE_MANAGEMENT - if (ce_defined && management && management_query_remote_enabled(management)) - { - /* allow management interface to override connection entry details */ - ce_defined = ce_management_query_remote(c); - if (IS_SIG (c)) - break; - } - else + if (ce_defined && management && management_query_remote_enabled(management)) + { + /* allow management interface to override connection entry details */ + ce_defined = ce_management_query_remote(c); + if (IS_SIG (c)) + break; + } + else #endif #ifdef ENABLE_MANAGEMENT - if (ce_defined && management && management_query_proxy_enabled (management)) - { - ce_defined = ce_management_query_proxy (c); - if (IS_SIG (c)) - break; - } + if (ce_defined && management && management_query_proxy_enabled (management)) + { + ce_defined = ce_management_query_proxy (c); + if (IS_SIG (c)) + break; + } #endif - } while (!ce_defined); - } + } 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)) + msg(M_FATAL, "All connections have been connect-retry-max (%d) times unsuccessful, exiting", + c->options.connect_retry_max); update_options_ce_post (&c->options); } @@ -396,12 +439,6 @@ init_query_passwords (struct context *c) #ifdef GENERAL_PROXY_SUPPORT -static int -proxy_scope (struct context *c) -{ - return connection_list_defined (&c->options) ? 2 : 1; -} - static void uninit_proxy_dowork (struct context *c) { @@ -463,17 +500,15 @@ init_proxy_dowork (struct context *c) } static void -init_proxy (struct context *c, const int scope) +init_proxy (struct context *c) { - if (scope == proxy_scope (c)) - init_proxy_dowork (c); + init_proxy_dowork (c); } static void uninit_proxy (struct context *c) { - if (c->sig->signal_received != SIGUSR1 || proxy_scope (c) == 2) - uninit_proxy_dowork (c); + uninit_proxy_dowork (c); } #else @@ -525,8 +560,6 @@ context_init_1 (struct context *c) } #endif - /* initialize HTTP or SOCKS proxy object at scope level 1 */ - init_proxy (c, 1); } void @@ -1222,6 +1255,9 @@ 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; + /* If we delayed UID/GID downgrade or chroot, do it now */ do_uid_gid_chroot (c, true); @@ -1239,9 +1275,9 @@ initialization_sequence_completed (struct context *c, const unsigned int flags) else msg (M_INFO, "%s", message); - /* Flag connection_list that we initialized */ - if ((flags & (ISC_ERRORS|ISC_SERVER)) == 0 && connection_list_defined (&c->options)) - connection_list_set_no_advance (&c->options); + /* Flag that we initialized */ + if ((flags & (ISC_ERRORS|ISC_SERVER)) == 0) + c->options.no_advance=true; #ifdef WIN32 fork_register_dns_action (c->c1.tuntap); @@ -1355,7 +1391,7 @@ do_init_tun (struct context *c) c->options.ifconfig_ipv6_local, c->options.ifconfig_ipv6_netbits, c->options.ifconfig_ipv6_remote, - addr_host (&c->c1.link_socket_addr.local), + c->c1.link_socket_addr.bind_local, c->c1.link_socket_addr.remote_list, !c->options.ifconfig_nowarn, c->c2.es); @@ -1545,7 +1581,7 @@ do_close_tun (struct context *c, bool force) /* delete any routes we added */ if (c->c1.route_list || c->c1.route_ipv6_list ) - { + { run_up_down (c->options.route_predown_script, c->plugins, OPENVPN_PLUGIN_ROUTE_PREDOWN, @@ -1832,13 +1868,10 @@ socket_restart_pause (struct context *c) switch (c->options.ce.proto) { - case PROTO_UDP: - if (proxy) - sec = c->options.ce.connect_retry_seconds; - break; case PROTO_TCP_SERVER: sec = 1; break; + case PROTO_UDP: case PROTO_TCP_CLIENT: sec = c->options.ce.connect_retry_seconds; break; @@ -2651,7 +2684,6 @@ do_init_socket_1 (struct context *c, const int mode) #endif link_socket_init_phase1 (c->c2.link_socket, - connection_list_defined (&c->options), c->options.ce.local, c->options.ce.local_port, c->options.ce.remote, @@ -2676,9 +2708,7 @@ do_init_socket_1 (struct context *c, const int mode) c->options.ipchange, c->plugins, c->options.resolve_retry_seconds, - c->options.ce.connect_retry_seconds, c->options.ce.connect_timeout, - c->options.ce.connect_retry_max, c->options.ce.mtu_discover_type, c->options.rcvbuf, c->options.sndbuf, @@ -2693,7 +2723,7 @@ static void do_init_socket_2 (struct context *c) { link_socket_init_phase2 (c->c2.link_socket, &c->c2.frame, - &c->sig->signal_received); + c->sig); } /* @@ -2865,15 +2895,30 @@ do_close_link_socket (struct context *c) c->c2.link_socket = NULL; } - if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_remote_ip)) - { - if (c->c1.link_socket_addr.remote_list) - freeaddrinfo(c->c1.link_socket_addr.remote_list); + + /* Preserve the resolved list of remote if the user request to or if we want + * reconnect to the same host again or there are still addresses that need + * to be tried */ + if (!(c->sig->signal_received == SIGUSR1 && + ( (c->options.persist_remote_ip) + || + ( c->sig->source != SIG_SOURCE_HARD && + ((c->c1.link_socket_addr.current_remote && c->c1.link_socket_addr.current_remote->ai_next) + || c->options.no_advance)) + ))) + { + clear_remote_addrlist(&c->c1.link_socket_addr); + } + + /* Clear the remote actual address when persist_remote_ip is not in use */ + if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_remote_ip)) CLEAR (c->c1.link_socket_addr.actual); - } - if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_local_ip)) - CLEAR (c->c1.link_socket_addr.local); + if (!(c->sig->signal_received == SIGUSR1 && c->options.persist_local_ip)) { + if (c->c1.link_socket_addr.bind_local) + freeaddrinfo(c->c1.link_socket_addr.bind_local); + c->c1.link_socket_addr.bind_local=NULL; + } } /* @@ -3296,7 +3341,7 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int /* signals caught here will abort */ c->sig->signal_received = 0; c->sig->signal_text = NULL; - c->sig->hard = false; + c->sig->source = SIG_SOURCE_SOFT; if (c->mode == CM_P2P) init_management_callback_p2p (c); @@ -3382,7 +3427,7 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int do_event_set_init (c, false); /* initialize HTTP or SOCKS proxy object at scope level 2 */ - init_proxy (c, 2); + init_proxy (c); /* allocate our socket object */ if (c->mode == CM_P2P || c->mode == CM_TOP || c->mode == CM_CHILD_TCP) @@ -3720,7 +3765,7 @@ close_context (struct context *c, int sig, unsigned int flags) if (c->sig->signal_received == SIGUSR1) { if ((flags & CC_USR1_TO_HUP) - || (c->sig->hard && (flags & CC_HARD_USR1_TO_HUP))) + || (c->sig->source == SIG_SOURCE_HARD && (flags & CC_HARD_USR1_TO_HUP))) c->sig->signal_received = SIGHUP; } @@ -3746,6 +3791,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/src/openvpn/manage.c b/src/openvpn/manage.c index 3816740..dc6293a 100644 --- a/src/openvpn/manage.c +++ b/src/openvpn/manage.c @@ -1461,7 +1461,7 @@ man_new_connection_post (struct management *man, const char *description) #endif msg (D_MANAGEMENT, "MANAGEMENT: %s %s", description, - print_sockaddr (&man->settings.local, &gc)); + print_sockaddr (man->settings.local->ai_addr, &gc)); buffer_list_reset (man->connection.out); @@ -1569,7 +1569,8 @@ man_listen (struct management *man) #endif { man->connection.sd_top = create_socket_tcp (AF_INET); - socket_bind (man->connection.sd_top, &man->settings.local, "MANAGEMENT"); + socket_bind (man->connection.sd_top, man->settings.local, + AF_INET, "MANAGEMENT"); } /* @@ -1593,7 +1594,7 @@ man_listen (struct management *man) else #endif msg (D_MANAGEMENT, "MANAGEMENT: TCP Socket listening on %s", - print_sockaddr (&man->settings.local, &gc)); + print_sockaddr (man->settings.local->ai_addr, &gc)); } #ifdef WIN32 @@ -1636,7 +1637,7 @@ man_connect (struct management *man) { man->connection.sd_cli = create_socket_tcp (AF_INET); status = openvpn_connect (man->connection.sd_cli, - &man->settings.local, + man->settings.local->ai_addr, 5, &signal_received); } @@ -1661,7 +1662,7 @@ man_connect (struct management *man) #endif msg (D_LINK_ERRORS, "MANAGEMENT: connect to %s failed: %s", - print_sockaddr (&man->settings.local, &gc), + print_sockaddr (man->settings.local->ai_addr, &gc), strerror_ts (status, &gc)); throw_signal_soft (SIGTERM, "management-connect-failed"); goto done; @@ -2122,13 +2123,9 @@ man_settings_init (struct man_settings *ms, } else { - struct addrinfo* ai; int status = openvpn_getaddrinfo(GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, - addr, port, 0, NULL, AF_INET, &ai); + addr, port, 0, NULL, AF_INET, &ms->local); ASSERT(status==0); - ms->local.addr.in4 = *((struct sockaddr_in*)ai->ai_addr); - freeaddrinfo(ai); - } } @@ -2587,7 +2584,13 @@ management_post_tunnel_open (struct management *man, const in_addr_t tun_local_i && man->connection.state == MS_INITIAL) { /* listen on our local TUN/TAP IP address */ - man->settings.local.addr.in4.sin_addr.s_addr = htonl (tun_local_ip); + 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); + ASSERT (ret==0); man_connection_init (man); } diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h index a54d0b6..962b5bc 100644 --- a/src/openvpn/manage.h +++ b/src/openvpn/manage.h @@ -212,7 +212,7 @@ struct man_persist { struct man_settings { bool defined; unsigned int flags; /* MF_x flags */ - struct openvpn_sockaddr local; + struct addrinfo* local; #if UNIX_SOCK_SUPPORT struct sockaddr_un local_unix; #endif diff --git a/src/openvpn/options.c b/src/openvpn/options.c index aa12cbd..3edab58 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -778,10 +778,10 @@ init_options (struct options *o, const bool init_gc) o->mode = MODE_POINT_TO_POINT; o->topology = TOP_NET30; o->ce.proto = PROTO_UDP; - o->ce.af = AF_INET; + o->ce.af = AF_UNSPEC; o->ce.connect_retry_seconds = 5; o->ce.connect_timeout = 10; - o->ce.connect_retry_max = 0; + o->connect_retry_max = 0; o->ce.local_port = o->ce.remote_port = OPENVPN_PORT; o->verbosity = 1; o->status_file_update_freq = 60; @@ -1369,7 +1369,6 @@ show_connection_entry (const struct connection_entry *o) SHOW_BOOL (bind_local); SHOW_INT (connect_retry_seconds); SHOW_INT (connect_timeout); - SHOW_INT (connect_retry_max); #ifdef ENABLE_HTTP_PROXY if (o->http_proxy_options) @@ -1446,6 +1445,7 @@ show_settings (const struct options *o) #endif #endif + SHOW_INT (connect_retry_max); show_connection_entries (o); SHOW_BOOL (remote_random); @@ -1727,32 +1727,31 @@ void options_postprocess_http_proxy_override (struct options *o) { const struct connection_list *l = o->connection_list; - if (l) + int i; + bool succeed = false; + for (i = 0; i < l->len; ++i) + { + struct connection_entry *ce = l->array[i]; + if (ce->proto == PROTO_TCP_CLIENT || ce->proto == PROTO_TCP) + { + ce->http_proxy_options = o->http_proxy_override; + succeed = true; + } + } + if (succeed) { - int i; - bool succeed = false; for (i = 0; i < l->len; ++i) - { - struct connection_entry *ce = l->array[i]; - if (ce->proto == PROTO_TCP_CLIENT || ce->proto == PROTO_TCP) - { - ce->http_proxy_options = o->http_proxy_override; - succeed = true; - } - } - if (succeed) - { - for (i = 0; i < l->len; ++i) - { - struct connection_entry *ce = l->array[i]; - if (ce->proto == PROTO_UDP) - { - ce->flags |= CE_DISABLED; - } - } - } - else - msg (M_WARN, "Note: option http-proxy-override ignored because no TCP-based connection profiles are defined"); + { + struct connection_entry *ce = l->array[i]; + if (ce->proto == PROTO_UDP) + { + ce->flags |= CE_DISABLED; + } + } + } + else + { + msg (M_WARN, "Note: option http-proxy-override ignored because no TCP-based connection profiles are defined"); } } @@ -1882,11 +1881,6 @@ options_postprocess_verify_ce (const struct options *options, const struct conne /* * Sanity check on TCP mode options */ - - if (ce->connect_retry_defined && ce->proto != PROTO_TCP_CLIENT) - msg (M_USAGE, "--connect-retry doesn't make sense unless also used with " - "--proto tcp-client or tcp6-client"); - if (ce->connect_timeout_defined && ce->proto != PROTO_TCP_CLIENT) msg (M_USAGE, "--connect-timeout doesn't make sense unless also used with " "--proto tcp-client or tcp6-client"); @@ -2004,7 +1998,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne msg (M_USAGE, "--socks-proxy can not be used in TCP Server mode"); #endif - if (ce->proto == PROTO_TCP_SERVER && connection_list_defined (options)) + if (ce->proto == PROTO_TCP_SERVER && (options->connection_list->len > 1)) msg (M_USAGE, "TCP server mode allows at most one --remote address"); #if P2MP_SERVER @@ -2041,8 +2035,12 @@ 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 - if (options->connection_list) - msg (M_USAGE, "<connection> cannot be used with --mode server"); + /* <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) + msg (M_USAGE, "<connection> cannot be used with --mode server"); + #if 0 if (options->tun_ipv6) msg (M_USAGE, "--tun-ipv6 cannot be used with --mode server"); @@ -2485,6 +2483,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. @@ -2498,48 +2497,38 @@ options_postprocess_mutate (struct options *o) if (o->remote_list && !o->connection_list) { /* - * For compatibility with 2.0.x, map multiple --remote options - * into connection list (connection lists added in 2.1). + * Convert remotes into connection list */ - if (o->remote_list->len > 1 || o->force_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); - ASSERT (ace); - *ace = ce; - } - } - else if (o->remote_list->len == 1) /* one --remote option specified */ - { - connection_entry_load_re (&o->ce, o->remote_list->array[0]); - } - else - { - ASSERT (0); - } + const struct remote_list *rl = o->remote_list; + 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); + ASSERT (ace); + *ace = ce; + } } - if (o->connection_list) + else if(!o->remote_list && !o->connection_list) { - int i; - for (i = 0; i < o->connection_list->len; ++i) + struct connection_entry *ace; + ace = alloc_connection_entry (o, M_USAGE); + ASSERT (ace); + *ace = o->ce; + } + + ASSERT (o->connection_list); + 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) + if (o->http_proxy_override) options_postprocess_http_proxy_override(o); #endif - } - else - options_postprocess_mutate_ce (o, &o->ce); #if P2MP /* @@ -4169,7 +4158,6 @@ add_option (struct options *options, { VERIFY_PERMISSION (OPT_P_GENERAL); options->management_flags |= MF_QUERY_PROXY; - options->force_connection_list = true; } else if (streq (p[0], "management-hold")) { @@ -4442,7 +4430,6 @@ add_option (struct options *options, options->http_proxy_override = parse_http_proxy_override(p[1], p[2], p[3], msglevel, &options->gc); if (!options->http_proxy_override) goto err; - options->force_connection_list = true; } #endif else if (streq (p[0], "remote") && p[1]) @@ -4494,7 +4481,6 @@ add_option (struct options *options, { VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION); options->ce.connect_retry_seconds = positive_atoi (p[1]); - options->ce.connect_retry_defined = true; } else if (streq (p[0], "connect-timeout") && p[1]) { @@ -4505,7 +4491,7 @@ add_option (struct options *options, else if (streq (p[0], "connect-retry-max") && p[1]) { VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION); - options->ce.connect_retry_max = positive_atoi (p[1]); + options->connect_retry_max = positive_atoi (p[1]); } else if (streq (p[0], "ipchange") && p[1]) { @@ -4930,7 +4916,6 @@ add_option (struct options *options, goto err; } options->proto_force = proto_force; - options->force_connection_list = true; } #ifdef ENABLE_HTTP_PROXY else if (streq (p[0], "http-proxy") && p[1]) diff --git a/src/openvpn/options.h b/src/openvpn/options.h index b320ca1..86760bb 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -97,8 +97,6 @@ struct connection_entry bool bind_defined; bool bind_local; int connect_retry_seconds; - bool connect_retry_defined; - int connect_retry_max; int connect_timeout; bool connect_timeout_defined; #ifdef ENABLE_HTTP_PROXY @@ -155,8 +153,6 @@ struct connection_list { int len; int current; - int n_cycles; - bool no_advance; struct connection_entry *array[CONNECTION_LIST_SIZE]; }; @@ -209,10 +205,15 @@ struct options #endif /* Networking parms */ + int connect_retry_max; struct connection_entry ce; struct connection_list *connection_list; + struct remote_list *remote_list; - bool force_connection_list; + /* Do not advanced the connection or remote addr list*/ + bool no_advance; + /* Counts the number of unsuccessful connection attempts */ + unsigned int unsuccessful_attempts; #if HTTP_PROXY_OVERRIDE struct http_proxy_options *http_proxy_override; @@ -775,20 +776,5 @@ bool get_ipv6_addr( const char * prefix_str, struct in6_addr *network, unsigned int * netbits, char ** printable_ipv6, int msglevel ); -/* - * inline functions - */ -static inline bool -connection_list_defined (const struct options *o) -{ - return o->connection_list != NULL; -} - -static inline void -connection_list_set_no_advance (struct options *o) -{ - if (o->connection_list) - o->connection_list->no_advance = true; -} #endif diff --git a/src/openvpn/ps.c b/src/openvpn/ps.c index 8714266..b22653b 100644 --- a/src/openvpn/ps.c +++ b/src/openvpn/ps.c @@ -330,8 +330,8 @@ journal_add (const char *journal_dir, struct proxy_connection *pc, struct proxy_ if (!getpeername (pc->sd, (struct sockaddr *) &from.addr.sa, &slen) && !getsockname (cp->sd, (struct sockaddr *) &to.addr.sa, &dlen)) { - const char *f = print_sockaddr (&from, &gc); - const char *t = print_sockaddr (&to, &gc); + const char *f = print_openvpn_sockaddr (&from, &gc); + const char *t = print_openvpn_sockaddr (&to, &gc); fnlen = strlen(journal_dir) + strlen(t) + 2; jfn = (char *) malloc(fnlen); check_malloc_return (jfn); @@ -408,20 +408,18 @@ proxy_entry_new (struct proxy_connection **list, struct buffer *initial_data, const char *journal_dir) { - struct openvpn_sockaddr osaddr; socket_descriptor_t sd_server; int status; struct proxy_connection *pc; struct proxy_connection *cp; /* connect to port share server */ - osaddr.addr.in4 = server_addr; if ((sd_server = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { msg (M_WARN|M_ERRNO, "PORT SHARE PROXY: cannot create socket"); return false; } - status = openvpn_connect (sd_server, &osaddr, 5, NULL); + status = openvpn_connect (sd_server,(const struct sockaddr*) &server_addr, 5, NULL); if (status) { msg (M_WARN, "PORT SHARE PROXY: connect to port-share server failed"); diff --git a/src/openvpn/push.c b/src/openvpn/push.c index be50bef..bd08cff 100644 --- a/src/openvpn/push.c +++ b/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)); - connection_list_set_no_advance(&c->options); + c->options.no_advance=true; + if (c->options.pull) { switch (auth_retry_get ()) diff --git a/src/openvpn/sig.c b/src/openvpn/sig.c index 5dee92b..90e39a4 100644 --- a/src/openvpn/sig.c +++ b/src/openvpn/sig.c @@ -97,14 +97,14 @@ void throw_signal (const int signum) { siginfo_static.signal_received = signum; - siginfo_static.hard = true; + siginfo_static.source = SIG_SOURCE_HARD; } void throw_signal_soft (const int signum, const char *signal_text) { siginfo_static.signal_received = signum; - siginfo_static.hard = false; + siginfo_static.source = SIG_SOURCE_SOFT; siginfo_static.signal_text = signal_text; } @@ -115,7 +115,7 @@ signal_reset (struct signal_info *si) { si->signal_received = 0; si->signal_text = NULL; - si->hard = false; + si->source = SIG_SOURCE_SOFT; } } @@ -124,9 +124,23 @@ print_signal (const struct signal_info *si, const char *title, int msglevel) { if (si) { - const char *hs = (si->hard ? "hard" : "soft"); const char *type = (si->signal_text ? si->signal_text : ""); const char *t = (title ? title : "process"); + const char *hs; + switch (si->source) + { + case SIG_SOURCE_SOFT: + hs= "soft"; + break; + case SIG_SOURCE_HARD: + hs = "hard"; + break; + case SIG_SOURCE_CONNECTION_FAILED: + hs = "connection failed(soft)"; + break; + default: + ASSERT(0); + } switch (si->signal_received) { diff --git a/src/openvpn/sig.h b/src/openvpn/sig.h index 987efef..c2c7b54 100644 --- a/src/openvpn/sig.h +++ b/src/openvpn/sig.h @@ -28,6 +28,15 @@ #include "status.h" #include "win32.h" + + +#define SIG_SOURCE_SOFT 0 +#define SIG_SOURCE_HARD 1 +/* CONNECTION_FAILED is also a "soft" status, + * It is thrown if a connection attempt fails + */ +#define SIG_SOURCE_CONNECTION_FAILED 2 + /* * Signal information, including signal code * and descriptive text. @@ -35,7 +44,7 @@ struct signal_info { volatile int signal_received; - volatile bool hard; + volatile int source; const char *signal_text; }; diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index d176537..5ba1ee3 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -148,6 +148,9 @@ openvpn_getaddrinfo (unsigned int flags, ASSERT (hostname || servname); ASSERT (!(flags & GETADDR_HOST_ORDER)); + if (hostname && (flags & GETADDR_RANDOMIZE)) + hostname = hostname_randomize(hostname, &gc); + if(hostname) print_hostname = hostname; else @@ -158,10 +161,6 @@ openvpn_getaddrinfo (unsigned int flags, else print_servname = ""; - - if (flags & GETADDR_RANDOMIZE) - hostname = hostname_randomize(hostname, &gc); - if (flags & GETADDR_MSG_VIRT_OUT) msglevel |= M_MSG_VIRT_OUT; @@ -173,17 +172,23 @@ 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 + hints.ai_socktype = SOCK_STREAM; + status = getaddrinfo(hostname, servname, &hints, res); if (status != 0) /* parse as numeric address failed? */ { const int fail_wait_interval = 5; /* seconds */ - int resolve_retries = (flags & GETADDR_TRY_ONCE) ? 1 : (resolve_retry_seconds / fail_wait_interval); + /* Add +4 to cause integer division rounding up (1 + 4) = 5, (0+4)/5=0 */ + int resolve_retries = (flags & GETADDR_TRY_ONCE) ? 1 : + ((resolve_retry_seconds + 4)/ fail_wait_interval); const char *fmt; int level = 0; @@ -270,7 +275,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 * */ } @@ -440,60 +446,6 @@ mac_addr_safe (const char *mac_addr) return true; } -static void -update_remote (const char* host, - struct openvpn_sockaddr *addr, - bool *changed, - const unsigned int sockflags) -{ - switch(addr->addr.sa.sa_family) - { - case AF_INET: - if (host && addr) - { - const in_addr_t new_addr = getaddr ( - sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sockflags), - host, - 1, - NULL, - NULL); - if (new_addr && addr->addr.in4.sin_addr.s_addr != new_addr) - { - addr->addr.in4.sin_addr.s_addr = new_addr; - *changed = true; - } - } - break; - case AF_INET6: - if (host && addr) - { - int status; - struct addrinfo* ai; - - status = openvpn_getaddrinfo(sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sockflags), - host, NULL, 1, NULL, AF_INET6, &ai); - - if ( status ==0 ) - { - struct sockaddr_in6 sin6; - CLEAR(sin6); - sin6 = *((struct sockaddr_in6*)ai->ai_addr); - if (!IN6_ARE_ADDR_EQUAL(&sin6.sin6_addr, &addr->addr.in6.sin6_addr)) - { - int port = addr->addr.in6.sin6_port; - /* ipv6 requires also eg. sin6_scope_id => easier to fully copy and override port */ - addr->addr.in6 = sin6; - addr->addr.in6.sin6_port = port; - } - freeaddrinfo(ai); - } - } - break; - default: - ASSERT(0); - } -} - static int socket_get_sndbuf (int sd) { @@ -665,51 +617,41 @@ create_socket_tcp (int af) } static socket_descriptor_t -create_socket_udp (const unsigned int flags) +create_socket_udp (const int af, const unsigned int flags) { socket_descriptor_t sd; - if ((sd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) - msg (M_ERR, "UDP: Cannot create UDP socket"); + if ((sd = socket (af, SOCK_DGRAM, IPPROTO_UDP)) < 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) + { #ifdef IP_PKTINFO - if (setsockopt (sd, SOL_IP, IP_PKTINFO, - (void*)&pad, sizeof(pad)) < 0) - msg(M_ERR, "UDP: failed setsockopt for IP_PKTINFO"); + if (setsockopt (sd, SOL_IP, IP_PKTINFO, + (void*)&pad, sizeof(pad)) < 0) + msg(M_ERR, "UDP: failed setsockopt for IP_PKTINFO"); #elif defined(IP_RECVDSTADDR) - if (setsockopt (sd, IPPROTO_IP, IP_RECVDSTADDR, - (void*)&pad, sizeof(pad)) < 0) - msg(M_ERR, "UDP: failed setsockopt for IP_RECVDSTADDR"); + if (setsockopt (sd, IPPROTO_IP, IP_RECVDSTADDR, + (void*)&pad, sizeof(pad)) < 0) + msg(M_ERR, "UDP: failed setsockopt for IP_RECVDSTADDR"); #else #error ENABLE_IP_PKTINFO is set without IP_PKTINFO xor IP_RECVDSTADDR (fix syshead.h) #endif - } -#endif - return sd; -} - -static socket_descriptor_t -create_socket_udp6 (const unsigned int flags) -{ - socket_descriptor_t sd; - - if ((sd = socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) - msg (M_ERR, "UDP: Cannot create UDP6 socket"); -#if ENABLE_IP_PKTINFO - else if (flags & SF_USE_IP_PKTINFO) - { - int pad = 1; + } + else if (af == AF_INET6 ) + { #ifndef IPV6_RECVPKTINFO /* Some older Darwin platforms require this */ - if (setsockopt (sd, IPPROTO_IPV6, IPV6_PKTINFO, - (void*)&pad, sizeof(pad)) < 0) + if (setsockopt (sd, IPPROTO_IPV6, IPV6_PKTINFO, + (void*)&pad, sizeof(pad)) < 0) #else - if (setsockopt (sd, IPPROTO_IPV6, IPV6_RECVPKTINFO, - (void*)&pad, sizeof(pad)) < 0) + if (setsockopt (sd, IPPROTO_IPV6, IPV6_RECVPKTINFO, + (void*)&pad, sizeof(pad)) < 0) #endif - msg(M_ERR, "UDP: failed setsockopt for IPV6_RECVPKTINFO"); + msg(M_ERR, "UDP: failed setsockopt for IPV6_RECVPKTINFO"); + } } #endif return sd; @@ -718,31 +660,37 @@ create_socket_udp6 (const unsigned int flags) static void create_socket (struct link_socket *sock) { - /* create socket */ - if (sock->info.proto == PROTO_UDP && sock->info.af == AF_INET) + /* 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); + + + if (ai_proto == IPPROTO_UDP) { - sock->sd = create_socket_udp (sock->sockflags); + sock->sd = create_socket_udp (ai_family, sock->sockflags); sock->sockflags |= SF_GETADDRINFO_DGRAM; #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 (sock->info.proto == PROTO_TCP_SERVER - || sock->info.proto == PROTO_TCP_CLIENT) + else if (ai_proto == IPPROTO_TCP) { - sock->sd = create_socket_tcp (sock->info.af); - } - else if (sock->info.proto == PROTO_UDP && sock->info.af == AF_INET6) - { - sock->sd = create_socket_udp6 (sock->sockflags); - sock->sockflags |= SF_GETADDRINFO_DGRAM; + sock->sd = create_socket_tcp (ai_family); } 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); + #ifdef TARGET_ANDROID /* pass socket FD to management interface to pass on to VPNService API * as "protected socket" (exempt from being routed into tunnel) @@ -757,10 +705,9 @@ create_socket (struct link_socket *sock) /* * Functions used for establishing a TCP stream connection. */ - static void socket_do_listen (socket_descriptor_t sd, - const struct openvpn_sockaddr *local, + const struct sockaddr *local, bool do_listen, bool do_set_nonblock) { @@ -850,8 +797,7 @@ static int socket_listen_accept (socket_descriptor_t sd, struct link_socket_actual *act, const char *remote_dynamic, - bool *remote_changed, - const struct openvpn_sockaddr *local, + const struct addrinfo *local, bool do_listen, bool nowait, volatile int *signal_received) @@ -862,7 +808,7 @@ socket_listen_accept (socket_descriptor_t sd, int new_sd = SOCKET_UNDEFINED; CLEAR (*act); - socket_do_listen (sd, local, do_listen, true); + socket_do_listen (sd, local->ai_addr, do_listen, true); while (true) { @@ -897,18 +843,26 @@ socket_listen_accept (socket_descriptor_t sd, if (socket_defined (new_sd)) { - update_remote (remote_dynamic, &remote_verify, remote_changed, 0); - if (addr_defined (&remote_verify) - && !addr_match (&remote_verify, &act->dest)) - { - msg (M_WARN, - "TCP NOTE: Rejected connection attempt from %s due to --remote setting", - print_link_socket_actual (act, &gc)); - if (openvpn_close_socket (new_sd)) - msg (M_ERR, "TCP: close socket failed (new_sd)"); - } + struct addrinfo* ai; + if(remote_dynamic) + openvpn_getaddrinfo(0, remote_dynamic, NULL, 1, NULL, + remote_verify.addr.sa.sa_family, &ai); + + if(ai && !addrlist_match(&remote_verify, ai)) + { + msg (M_WARN, + "TCP NOTE: Rejected connection attempt from %s due to --remote setting", + print_link_socket_actual (act, &gc)); + if (openvpn_close_socket (new_sd)) + msg (M_ERR, "TCP: close socket failed (new_sd)"); + freeaddrinfo(ai); + } else - break; + { + if(ai) + freeaddrinfo(ai); + break; + } } openvpn_sleep (1); } @@ -924,17 +878,38 @@ socket_listen_accept (socket_descriptor_t sd, void socket_bind (socket_descriptor_t sd, - struct openvpn_sockaddr *local, + struct addrinfo *local, + int ai_family, const char *prefix) { struct gc_arena gc = gc_new (); - if (bind (sd, &local->addr.sa, af_addr_size(local->addr.sa.sa_family))) + /* FIXME (schwabe) + * getaddrinfo for the bind address might return multiple AF_INET/AF_INET6 + * entries for the requested protocol. + * For example if an address has multiple A records + * What is the correct way to deal with it? + */ + + ASSERT(local); + struct addrinfo* cur; + + /* find the first addrinfo with correct ai_family */ + for (cur = local; cur; cur=cur->ai_next) + { + if(cur->ai_family == ai_family) + break; + } + if (!cur) + 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)) { const int errnum = openvpn_errno (); msg (M_FATAL, "%s: Socket bind failed on local address %s: %s", prefix, - print_sockaddr (local, &gc), + print_sockaddr_ex (local->ai_addr, ":", PS_SHOW_PORT, &gc), strerror_ts (errnum, &gc)); } gc_free (&gc); @@ -942,7 +917,7 @@ socket_bind (socket_descriptor_t sd, int openvpn_connect (socket_descriptor_t sd, - struct openvpn_sockaddr *remote, + const struct sockaddr *remote, int connect_timeout, volatile int *signal_received) { @@ -950,7 +925,7 @@ openvpn_connect (socket_descriptor_t sd, #ifdef CONNECT_NONBLOCK set_nonblock (sd); - status = connect (sd, &remote->addr.sa, af_addr_size(remote->addr.sa.sa_family)); + status = connect (sd, remote, af_addr_size(remote->sa_family)); if (status) status = openvpn_errno (); if ( @@ -1022,37 +997,47 @@ openvpn_connect (socket_descriptor_t sd, return status; } +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); + else if (ai->ai_family == AF_INET6) + actual->dest.addr.in6 = + *((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 openvpn_sockaddr *local, - bool bind_local, - struct openvpn_sockaddr *remote, - const bool connection_profiles_defined, - const char *remote_dynamic, - bool *remote_changed, - const int connect_retry_seconds, - const int connect_timeout, - const int connect_retry_max, - const unsigned int sockflags, - volatile int *signal_received) + struct link_socket_addr *lsa, + const int connect_timeout, + struct signal_info* sig_info) { struct gc_arena gc = gc_new (); - int retry = 0; + 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 (remote, &gc)); + msg (M_INFO, "Attempting to establish TCP connection with %s [nonblock]", + print_sockaddr (dest, &gc)); #else - msg (M_INFO, "Attempting to establish TCP connection with %s", - print_sockaddr (remote, &gc)); + msg (M_INFO, "Attempting to establish TCP connection with %s", + print_sockaddr (dest, &gc)); #endif - while (true) - { - int status; - #ifdef ENABLE_MANAGEMENT - if (management) + if (management) management_set_state (management, OPENVPN_STATE_TCP_CONNECT, NULL, @@ -1060,47 +1045,28 @@ socket_connect (socket_descriptor_t *sd, (in_addr_t)0); #endif - status = openvpn_connect (*sd, remote, connect_timeout, signal_received); + /* Set the actual address */ + status = openvpn_connect (*sd, dest, connect_timeout, &sig_info->signal_received); - get_signal (signal_received); - if (*signal_received) + get_signal (&sig_info->signal_received); + if (sig_info->signal_received) goto done; - if (!status) - break; + if (status) { - msg (D_LINK_ERRORS, - "TCP: connect to %s failed, will try again in %d seconds: %s", - print_sockaddr (remote, &gc), - connect_retry_seconds, - strerror_ts (status, &gc)); + msg (D_LINK_ERRORS, + "TCP: connect to %s failed: %s", + print_sockaddr (dest, &gc), + strerror_ts (status, &gc)); - gc_reset (&gc); - - openvpn_close_socket (*sd); - *sd = SOCKET_UNDEFINED; - - if ((connect_retry_max > 0 && ++retry >= connect_retry_max) || connection_profiles_defined) - { - *signal_received = SIGUSR1; - goto done; - } - - openvpn_sleep (connect_retry_seconds); - - get_signal (signal_received); - if (*signal_received) - goto done; - - *sd = create_socket_tcp (local->addr.sa.sa_family); - - if (bind_local) - socket_bind (*sd, local, "TCP Client"); - update_remote (remote_dynamic, remote, remote_changed, sockflags); - } - - msg (M_INFO, "TCP connection established with %s", - print_sockaddr (remote, &gc)); + openvpn_close_socket (*sd); + *sd = SOCKET_UNDEFINED; + sig_info->signal_received = SIGUSR1; + sig_info->source = SIG_SOURCE_CONNECTION_FAILED; + } else { + msg (M_INFO, "TCP connection established with %s", + print_sockaddr (dest, &gc)); + } done: gc_free (&gc); @@ -1151,48 +1117,48 @@ frame_adjust_path_mtu (struct frame *frame, int pmtu, int proto) } static void -resolve_bind_local (struct link_socket *sock) +resolve_bind_local (struct link_socket *sock, const sa_family_t af) { struct gc_arena gc = gc_new (); /* resolve local address if undefined */ - if (!addr_defined (&sock->info.lsa->local)) + if (!sock->info.lsa->bind_local) { + int flags = GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | + GETADDR_FATAL | GETADDR_PASSIVE; int status; - struct addrinfo *ai; - - /* may return AF_{INET|INET6} guessed from local_host */ - const int af = addr_guess_family(sock->info.af, sock->local_host); - status = openvpn_getaddrinfo(GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | GETADDR_FATAL | GETADDR_PASSIVE, - sock->local_host, sock->local_port, 0, NULL, af, &ai); - if(status ==0) { - switch(af) { - case AF_INET: - sock->info.lsa->local.addr.in4 = *((struct sockaddr_in*)(ai->ai_addr)); - - case AF_INET6: - sock->info.lsa->local.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr)); - break; - freeaddrinfo(ai); - } - } else { - msg (M_FATAL, "getaddrinfo() failed for local \"%s:%s\": %s", - sock->local_host, sock->local_port, - gai_strerror(status)); + + if(proto_is_dgram(sock->info.proto)) + 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); + + if(status !=0) { + msg (M_FATAL, "getaddrinfo() failed for local \"%s:%s\": %s", + sock->local_host, sock->local_port, + gai_strerror(status)); } } - /* bind to local address/port */ - if (sock->bind_local) - { + 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 && sock->info.af == AF_INET) - socket_bind (sock->ctrl_sd, &sock->info.lsa->local, "SOCKS"); - else + 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->local, "TCP/UDP"); - } - gc_free (&gc); + socket_bind (sock->sd, sock->info.lsa->bind_local, + sock->info.lsa->actual.ai_family, "TCP/UDP"); + } } static void @@ -1202,7 +1168,6 @@ resolve_remote (struct link_socket *sock, volatile int *signal_received) { struct gc_arena gc = gc_new (); - int af; if (!sock->did_resolve_remote) { @@ -1214,9 +1179,11 @@ resolve_remote (struct link_socket *sock, unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags); int retry = 0; int status = -1; - struct addrinfo* ai; + struct addrinfo* ai; + if (proto_is_dgram(sock->info.proto)) + flags |= GETADDR_DATAGRAM; - if (sock->connection_profiles_defined && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE) + if (sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE) { if (phase == 2) flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL); @@ -1251,19 +1218,20 @@ resolve_remote (struct link_socket *sock, ASSERT (0); } - /* Temporary fix, this need to be changed for dual stack */ - status = openvpn_getaddrinfo(flags, sock->remote_host, sock->remote_port, - retry, signal_received, af, &ai); - if(status == 0) { - sock->info.lsa->remote_list = 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); - } + 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) @@ -1289,16 +1257,10 @@ resolve_remote (struct link_socket *sock, else { CLEAR (sock->info.lsa->actual); - /* TODO(schwabe) will only use first address als dest address */ - if(sock->info.lsa->remote_list) { - if (sock->info.lsa->remote_list->ai_family == AF_INET) - sock->info.lsa->actual.dest.addr.in4 = - *((struct sockaddr_in*) sock->info.lsa->remote_list->ai_addr); - else if (sock->info.lsa->remote_list->ai_family == AF_INET6) - sock->info.lsa->actual.dest.addr.in6 = - *((struct sockaddr_in6*) sock->info.lsa->remote_list->ai_addr); - else - ASSERT(0); + if(sock->info.lsa->current_remote) + { + set_actual_address (&sock->info.lsa->actual, + sock->info.lsa->current_remote); } } @@ -1310,6 +1272,8 @@ resolve_remote (struct link_socket *sock, gc_free (&gc); } + + struct link_socket * link_socket_new (void) { @@ -1324,26 +1288,40 @@ link_socket_new (void) } void -create_new_socket (struct link_socket* sock, int mark) +create_new_socket (struct link_socket* sock) { - create_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. */ - /* set socket buffers based on --sndbuf and --rcvbuf options */ - socket_set_buffers (sock->sd, &sock->socket_buffer_sizes); + 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); + } - /* set socket to --mark packets with given value */ - socket_set_mark (sock->sd, mark); + /* + * 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) - resolve_bind_local (sock); - resolve_remote (sock, 1, NULL, NULL); + if (sock->bind_local) + bind_local(sock); + } } /* bind socket if necessary */ void link_socket_init_phase1 (struct link_socket *sock, - const bool connection_profiles_defined, const char *local_host, const char *local_port, const char *remote_host, @@ -1368,9 +1346,7 @@ link_socket_init_phase1 (struct link_socket *sock, const char *ipchange_command, const struct plugin_list *plugins, int resolve_retry_seconds, - int connect_retry_seconds, int connect_timeout, - int connect_retry_max, int mtu_discover_type, int rcvbuf, int sndbuf, @@ -1379,8 +1355,6 @@ link_socket_init_phase1 (struct link_socket *sock, { ASSERT (sock); - sock->connection_profiles_defined = connection_profiles_defined; - sock->local_host = local_host; sock->local_port = local_port; sock->remote_host = remote_host; @@ -1397,9 +1371,7 @@ link_socket_init_phase1 (struct link_socket *sock, sock->bind_local = bind_local; sock->inetd = inetd; sock->resolve_retry_seconds = resolve_retry_seconds; - sock->connect_retry_seconds = connect_retry_seconds; sock->connect_timeout = connect_timeout; - sock->connect_retry_max = connect_retry_max; sock->mtu_discover_type = mtu_discover_type; #ifdef ENABLE_DEBUG @@ -1410,6 +1382,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; @@ -1484,7 +1457,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); } } @@ -1502,11 +1475,11 @@ void phase2_inetd (struct link_socket* sock, const struct frame *frame, /* inetd: hint family type for dest = local's */ struct openvpn_sockaddr local_addr; socklen_t addrlen = sizeof(local_addr); - if (getsockname (sock->sd, (struct sockaddr *)&local_addr, &addrlen) == 0) { + 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); + 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); @@ -1520,11 +1493,11 @@ void phase2_inetd (struct link_socket* sock, const struct frame *frame, socket_listen_accept (sock->sd, &sock->info.lsa->actual, remote_dynamic, - &remote_changed, - &sock->info.lsa->local, + sock->info.lsa->bind_local, false, sock->inetd == INETD_NOWAIT, signal_received); + } ASSERT (!remote_changed); } @@ -1566,11 +1539,23 @@ linksock_print_addr (struct link_socket *sock) /* print local address */ if (sock->inetd) msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, sock->info.af, true)); - else - msg (msglevel, "%s link local%s: %s", + 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), - (sock->bind_local ? " (bound)" : ""), - print_openvpn_sockaddr_ex (&sock->info.lsa->local, ":", sock->bind_local ? PS_SHOW_PORT : 0, &gc)); + 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", @@ -1583,8 +1568,8 @@ linksock_print_addr (struct link_socket *sock) } static void -phase2_tcp_server (struct link_socket *sock, bool *remote_changed, - const char *remote_dynamic, volatile int *signal_received) +phase2_tcp_server (struct link_socket *sock, const char *remote_dynamic, + volatile int *signal_received) { switch (sock->mode) { @@ -1592,15 +1577,14 @@ phase2_tcp_server (struct link_socket *sock, bool *remote_changed, sock->sd = socket_listen_accept (sock->sd, &sock->info.lsa->actual, remote_dynamic, - remote_changed, - &sock->info.lsa->local, + sock->info.lsa->bind_local, true, false, signal_received); break; case LS_MODE_TCP_LISTEN: socket_do_listen (sock->sd, - &sock->info.lsa->local, + sock->info.lsa->bind_local->ai_addr, true, false); break; @@ -1622,90 +1606,76 @@ phase2_tcp_server (struct link_socket *sock, bool *remote_changed, static void -phase2_tcp_client (struct link_socket *sock, bool *remote_changed, - const char *remote_dynamic, volatile int *signal_received) +phase2_tcp_client (struct link_socket *sock, struct signal_info *sig_info) { #ifdef GENERAL_PROXY_SUPPORT - bool proxy_retry = false; + bool proxy_retry = false; #else - const bool proxy_retry = false; -#endif - do { - socket_connect (&sock->sd, - &sock->info.lsa->local, - sock->bind_local, - &sock->info.lsa->actual.dest, - sock->connection_profiles_defined, - remote_dynamic, - remote_changed, - sock->connect_retry_seconds, - sock->connect_timeout, - sock->connect_retry_max, - sock->sockflags, - signal_received); - - if (*signal_received) - return; - - if (false) - ; + 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, - signal_received); - } + 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, - 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); + } #endif - if (proxy_retry) - { - openvpn_close_socket (sock->sd); - sock->sd = create_socket_tcp (AF_INET); - } - } while (proxy_retry); + 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); + } #ifdef ENABLE_SOCKS static void -phase2_socks_client (struct link_socket *sock, bool *remote_changed, - const char *remote_dynamic, volatile int *signal_received) +phase2_socks_client (struct link_socket *sock, struct signal_info *sig_info) { socket_connect (&sock->ctrl_sd, - &sock->info.lsa->local, - sock->bind_local, - &sock->info.lsa->actual.dest, - sock->connection_profiles_defined, - remote_dynamic, - remote_changed, - sock->connect_retry_seconds, + sock->info.lsa, sock->connect_timeout, - sock->connect_retry_max, - sock->sockflags, - signal_received); + sig_info); - if (*signal_received) + if (sig_info->signal_received) return; establish_socks_proxy_udpassoc (sock->socks_proxy, sock->ctrl_sd, sock->sd, &sock->socks_relay.dest, - signal_received); + &sig_info->signal_received); - if (*signal_received) + if (sig_info->signal_received) return; sock->remote_host = sock->proxy_dest_host; @@ -1713,12 +1683,14 @@ phase2_socks_client (struct link_socket *sock, bool *remote_changed, sock->did_resolve_remote = false; addr_zero_host(&sock->info.lsa->actual.dest); - if (sock->info.lsa->remote_list) { + if (sock->info.lsa->remote_list) + { freeaddrinfo(sock->info.lsa->remote_list); - sock->info.lsa->remote_list=NULL; - } + sock->info.lsa->current_remote = NULL; + sock->info.lsa->remote_list = NULL; + } - resolve_remote (sock, 1, NULL, signal_received); + resolve_remote (sock, 1, NULL, &sig_info->signal_received); } #endif @@ -1726,18 +1698,17 @@ phase2_socks_client (struct link_socket *sock, bool *remote_changed, void link_socket_init_phase2 (struct link_socket *sock, const struct frame *frame, - volatile int *signal_received) + struct signal_info *sig_info) { const char *remote_dynamic = NULL; - bool remote_changed = false; int sig_save = 0; ASSERT (sock); - if (signal_received && *signal_received) + if (sig_info && sig_info->signal_received) { - sig_save = *signal_received; - *signal_received = 0; + sig_save = sig_info->signal_received; + sig_info->signal_received = 0; } /* initialize buffers */ @@ -1754,56 +1725,65 @@ link_socket_init_phase2 (struct link_socket *sock, /* were we started by inetd or xinetd? */ if (sock->inetd) { - phase2_inetd (sock, frame, remote_dynamic, signal_received); - if (*signal_received) + phase2_inetd (sock, frame, remote_dynamic, &sig_info->signal_received); + if (sig_info && sig_info->signal_received) goto done; } else { - resolve_remote (sock, 2, &remote_dynamic, signal_received); + /* Second chance to resolv/create socket */ + resolve_remote (sock, 2, &remote_dynamic, &sig_info->signal_received); - if (*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; if (sock->info.proto == PROTO_TCP_SERVER) { - phase2_tcp_server(sock, &remote_changed, remote_dynamic, - signal_received); + phase2_tcp_server (sock, remote_dynamic, + &sig_info->signal_received); } else if (sock->info.proto == PROTO_TCP_CLIENT) { - phase2_tcp_client(sock, &remote_changed, remote_dynamic, - signal_received); + phase2_tcp_client (sock, sig_info); } #ifdef ENABLE_SOCKS - else if (sock->info.proto == PROTO_UDP && sock->socks_proxy && sock->info.af == AF_INET) + else if (sock->info.proto == PROTO_UDP && sock->socks_proxy) { - phase2_socks_client(sock, &remote_changed, remote_dynamic, - signal_received); + phase2_socks_client (sock, sig_info); #endif } - if (*signal_received) + if (sig_info && sig_info->signal_received) goto done; - - if (remote_changed) - { - msg (M_INFO, "TCP/UDP: Dynamic remote address changed during TCP connection establishment"); - /* TODO(schwabe) handle multiple addresses */ - ASSERT(0); - addr_copy_host(&sock->info.lsa->remote_list->ai_addr, &sock->info.lsa->actual.dest); - } } phase2_set_socket_flags(sock); linksock_print_addr(sock); done: - if (sig_save && signal_received) + if (sig_save && sig_info) { - if (!*signal_received) - *signal_received = sig_save; + if (!sig_info->signal_received) + sig_info->signal_received = sig_save; } } @@ -1936,10 +1916,7 @@ link_socket_bad_incoming_addr (struct buffer *buf, const struct link_socket_actual *from_addr) { struct gc_arena gc = gc_new (); - struct openvpn_sockaddr firstremoteaddr; - - /* TODO(schwabe) Fix this and print all remote addresses */ - firstremoteaddr.addr.in6 = *(struct sockaddr_in6*)info->lsa->remote_list->ai_addr; + struct addrinfo* ai; switch(from_addr->dest.addr.sa.sa_family) { @@ -1949,7 +1926,12 @@ link_socket_bad_incoming_addr (struct buffer *buf, "TCP/UDP: Incoming packet rejected from %s[%d], expected peer address: %s (allow this incoming source address/port by removing --remote or adding --float)", print_link_socket_actual (from_addr, &gc), (int)from_addr->dest.addr.sa.sa_family, - print_sockaddr (&firstremoteaddr, &gc)); + print_sockaddr_ex (info->lsa->remote_list->ai_addr,":" ,PS_SHOW_PORT, &gc)); + /* print additional remote addresses */ + for(ai=info->lsa->remote_list->ai_next;ai;ai=ai->ai_next) { + msg(D_LINK_ERRORS,"or from peer address: %s", + print_sockaddr_ex(ai->ai_addr,":",PS_SHOW_PORT, &gc)); + } break; } buf->len = 0; @@ -1974,15 +1956,17 @@ link_socket_current_remote (const struct link_socket_info *info) * Maybe in the future consider PF_INET6 endpoints also ... * by now just ignore it * + * For --remote entries with multiple addresses this + * only return the actual endpoint we have sucessfully connected to */ -/* TODO(schwabe) what to do for a remote with multiple IPs? */ if (lsa->actual.dest.addr.sa.sa_family != AF_INET) return IPV4_INVALID_ADDR; if (link_socket_actual_defined (&lsa->actual)) return ntohl (lsa->actual.dest.addr.in4.sin_addr.s_addr); - else if (lsa->remote_list) - return ntohl (((struct sockaddr_in*)lsa->remote_list->ai_addr)->sin_addr.s_addr); + else if (lsa->current_remote) + return ntohl (((struct sockaddr_in*)lsa->current_remote->ai_addr) + ->sin_addr.s_addr); else return 0; } @@ -2465,10 +2449,17 @@ struct proto_names { /* Indexed by PROTO_x */ static const struct proto_names proto_names[] = { {"proto-uninitialized", "proto-NONE", AF_UNSPEC, PROTO_NONE}, - {"udp", "UDPv4", AF_INET, PROTO_UDP}, - {"tcp-server", "TCPv4_SERVER", AF_INET, PROTO_TCP_SERVER}, - {"tcp-client", "TCPv4_CLIENT", AF_INET, PROTO_TCP_CLIENT}, - {"tcp", "TCPv4", AF_INET, PROTO_TCP}, + /* try IPv4 and IPv6 (client), bind dual-stack (server) */ + {"udp", "UDP", AF_UNSPEC, PROTO_UDP}, + {"tcp-server", "TCP_SERVER", AF_UNSPEC, PROTO_TCP_SERVER}, + {"tcp-client", "TCP_CLIENT", AF_UNSPEC, PROTO_TCP_CLIENT}, + {"tcp", "TCP", AF_UNSPEC, 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}, @@ -2807,7 +2798,7 @@ link_socket_write_tcp (struct link_socket *sock, #if ENABLE_IP_PKTINFO -int +size_t link_socket_write_udp_posix_sendmsg (struct link_socket *sock, struct buffer *buf, struct link_socket_actual *to) @@ -2821,7 +2812,7 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock, iov.iov_len = BLEN (buf); mesg.msg_iov = &iov; mesg.msg_iovlen = 1; - switch (sock->info.lsa->remote_list->ai_family) + switch (to->ai_family) { case AF_INET: { diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index 65def10..5c93474 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -81,6 +81,11 @@ struct openvpn_sockaddr struct link_socket_actual { /*int dummy;*/ /* add offset to force a bug if dest not explicitly dereferenced */ + int ai_family; /* PF_xxx */ + 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 { @@ -97,8 +102,10 @@ struct link_socket_actual /* IP addresses which are persistant across SIGUSR1s */ struct link_socket_addr { - struct openvpn_sockaddr local; - struct addrinfo* remote_list; /* initial remote */ + struct addrinfo* bind_local; + struct addrinfo* remote_list; /* complete remote list */ + struct addrinfo* current_remote; /* remote used in the + current connection attempt */ struct link_socket_actual actual; /* reply to this address */ }; @@ -176,9 +183,6 @@ struct link_socket /* used for long-term queueing of pre-accepted socket listen */ bool listen_persistent_queued; - /* Does config file contain any <connection> ... </connection> blocks? */ - bool connection_profiles_defined; - const char *remote_host; const char *remote_port; const char *local_host; @@ -196,9 +200,7 @@ struct link_socket int mode; int resolve_retry_seconds; - int connect_retry_seconds; int connect_timeout; - int connect_retry_max; int mtu_discover_type; struct socket_buffer_size socket_buffer_sizes; @@ -213,6 +215,7 @@ struct link_socket # define SF_HOST_RANDOMIZE (1<<3) # define SF_GETADDRINFO_DGRAM (1<<4) unsigned int sockflags; + int mark; /* for stream sockets */ struct stream_buf stream_buf; @@ -284,11 +287,12 @@ int socket_finalize ( struct link_socket *link_socket_new (void); void socket_bind (socket_descriptor_t sd, - struct openvpn_sockaddr *local, + struct addrinfo *local, + int af_family, const char *prefix); int openvpn_connect (socket_descriptor_t sd, - struct openvpn_sockaddr *remote, + const struct sockaddr *remote, int connect_timeout, volatile int *signal_received); @@ -298,7 +302,6 @@ int openvpn_connect (socket_descriptor_t sd, void link_socket_init_phase1 (struct link_socket *sock, - const bool connection_profiles_defined, const char *local_host, const char *local_port, const char *remote_host, @@ -323,9 +326,7 @@ link_socket_init_phase1 (struct link_socket *sock, const char *ipchange_command, const struct plugin_list *plugins, int resolve_retry_seconds, - int connect_retry_seconds, int connect_timeout, - int connect_retry_max, int mtu_discover_type, int rcvbuf, int sndbuf, @@ -334,7 +335,7 @@ link_socket_init_phase1 (struct link_socket *sock, void link_socket_init_phase2 (struct link_socket *sock, const struct frame *frame, - volatile int *signal_received); + struct signal_info *sig_info); void socket_adjust_frame_parameters (struct frame *frame, int proto); @@ -364,12 +365,21 @@ const char *print_openvpn_sockaddr_ex (const struct openvpn_sockaddr *addr, } static inline -const char *print_sockaddr (const struct openvpn_sockaddr *addr, +const char *print_openvpn_sockaddr (const struct openvpn_sockaddr *addr, struct gc_arena *gc) { return print_sockaddr_ex (&addr->addr.sa, ":", PS_SHOW_PORT, gc); } +static inline +const char *print_sockaddr (const struct sockaddr *addr, + struct gc_arena *gc) +{ + return print_sockaddr_ex (addr, ":", PS_SHOW_PORT, gc); +} + + + const char *print_link_socket_actual_ex (const struct link_socket_actual *act, const char* separator, const unsigned int flags, @@ -420,6 +430,9 @@ void link_socket_bad_incoming_addr (struct buffer *buf, const struct link_socket_info *info, const struct link_socket_actual *from_addr); +void set_actual_address (struct link_socket_actual* actual, + struct addrinfo* ai); + void link_socket_bad_outgoing_addr (void); void setenv_trusted (struct env_set *es, const struct link_socket_info *info); @@ -496,6 +509,7 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int * #define GETADDR_UPDATE_MANAGEMENT_STATE (1<<8) #define GETADDR_RANDOMIZE (1<<9) #define GETADDR_PASSIVE (1<<10) +#define GETADDR_DATAGRAM (1<<11) in_addr_t getaddr (unsigned int flags, const char *hostname, @@ -741,19 +755,6 @@ addr_copy_sa(struct openvpn_sockaddr *dst, const struct openvpn_sockaddr *src) dst->addr = src->addr; } -static inline void -addr_copy_host(struct openvpn_sockaddr *dst, const struct openvpn_sockaddr *src) -{ - switch(src->addr.sa.sa_family) { - case AF_INET: - dst->addr.in4.sin_addr.s_addr = src->addr.in4.sin_addr.s_addr; - break; - case AF_INET6: - dst->addr.in6.sin6_addr = src->addr.in6.sin6_addr; - break; - } -} - static inline bool addr_inet4or6(struct sockaddr *addr) { @@ -838,7 +839,7 @@ link_socket_verify_incoming_addr (struct buffer *buf, case AF_INET: if (!link_socket_actual_defined (from_addr)) return false; - if (info->remote_float || !info->lsa->remote_list) + if (info->remote_float || (!info->lsa->remote_list)) return true; if (addrlist_match_proto (&from_addr->dest, info->lsa->remote_list, info->proto)) return true; @@ -877,13 +878,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)) - /* address undef or address == remote or --float */ - && (info->remote_float - || !lsa->remote_list - || addrlist_match_proto (&act->dest, lsa->remote_list, info->proto)) + /* new or changed address? */ + (!info->connection_established + || !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)) + ) ) { link_socket_connection_initiated (buf, info, act, common_name, es); @@ -1007,13 +1010,13 @@ link_socket_write_win32 (struct link_socket *sock, #else -static inline int +static inline size_t link_socket_write_udp_posix (struct link_socket *sock, struct buffer *buf, struct link_socket_actual *to) { #if ENABLE_IP_PKTINFO - int link_socket_write_udp_posix_sendmsg (struct link_socket *sock, + size_t link_socket_write_udp_posix_sendmsg (struct link_socket *sock, struct buffer *buf, struct link_socket_actual *to); @@ -1027,7 +1030,7 @@ link_socket_write_udp_posix (struct link_socket *sock, (socklen_t) af_addr_size(to->dest.addr.sa.sa_family)); } -static inline int +static inline size_t link_socket_write_tcp_posix (struct link_socket *sock, struct buffer *buf, struct link_socket_actual *to) @@ -1037,7 +1040,7 @@ link_socket_write_tcp_posix (struct link_socket *sock, #endif -static inline int +static inline size_t link_socket_write_udp (struct link_socket *sock, struct buffer *buf, struct link_socket_actual *to) diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 0f30e2f..a300275 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -411,7 +411,7 @@ init_tun (const char *dev, /* --dev option */ const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 IPv6 */ int ifconfig_ipv6_netbits_parm, const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 IPv6 */ - in_addr_t local_public, + struct addrinfo *local_public, struct addrinfo *remote_public, const bool strict_warn, struct env_set *es) @@ -474,11 +474,14 @@ init_tun (const char *dev, /* --dev option */ * make sure they do not clash with our virtual subnet. */ - check_addr_clash ("local", + for(curele=local_public;curele;curele=curele->ai_next) { + if(curele->ai_family == AF_INET) + check_addr_clash ("local", tt->type, - local_public, + ((struct sockaddr_in*)curele->ai_addr)->sin_addr.s_addr, tt->local, tt->remote_netmask); + } for (curele=remote_public;curele;curele=curele->ai_next) { if (curele->ai_family == AF_INET) diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index ea2290c..631b53c 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -232,7 +232,7 @@ struct tuntap *init_tun (const char *dev, /* --dev option */ const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 / IPv6 */ int ifconfig_ipv6_netbits_parm, /* --ifconfig parm 1 / bits */ const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 / IPv6 */ - in_addr_t local_public, + struct addrinfo *local_public, struct addrinfo *remote_public, const bool strict_warn, struct env_set *es); |