diff options
author | james <james@e7ae566f-a301-0410-adde-c780ea21d3b5> | 2005-11-25 00:05:56 +0000 |
---|---|---|
committer | james <james@e7ae566f-a301-0410-adde-c780ea21d3b5> | 2005-11-25 00:05:56 +0000 |
commit | 1ae9d05173a5960eaf84dcb55b91374fa2bb6639 (patch) | |
tree | 0b82d974ee07015fe307ca213c88253252a57d51 | |
parent | --remap-usr1 will now also remap signals thrown during initialization. (diff) | |
download | openvpn-1ae9d05173a5960eaf84dcb55b91374fa2bb6639.tar.xz |
Added --connect-timeout option to control the timeout
on TCP client connection attempts (doesn't work on all
OSes). This patch also makes OpenVPN signalable during
TCP connection attempts.
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@823 e7ae566f-a301-0410-adde-c780ea21d3b5
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | init.c | 5 | ||||
-rw-r--r-- | options.c | 14 | ||||
-rw-r--r-- | options.h | 2 | ||||
-rw-r--r-- | socket.c | 94 | ||||
-rw-r--r-- | socket.h | 2 | ||||
-rw-r--r-- | syshead.h | 7 |
7 files changed, 122 insertions, 7 deletions
@@ -7,7 +7,10 @@ $Id$ * --remap-usr1 will now also remap signals thrown during initialization. - +* Added --connect-timeout option to control the timeout + on TCP client connection attempts (doesn't work on all + OSes). This patch also makes OpenVPN signalable during + TCP connection attempts. 2005.11.12 -- Version 2.1-beta7 * Allow blank passwords to be passed via the management @@ -1673,7 +1673,11 @@ do_option_warnings (struct context *c) && !(o->ns_cert_type & NS_SSL_SERVER)) msg (M_WARN, "WARNING: No server certificate verification method has been enabled. See http://openvpn.net/howto.html#mitm for more info."); #endif +#endif +#ifndef CONNECT_NONBLOCK + if (o->connect_timeout_defined) + msg (M_WARN, "NOTE: --connect-timeout option is not supported on this OS"); #endif } @@ -1813,6 +1817,7 @@ do_init_socket_1 (struct context *c, int mode) c->plugins, c->options.resolve_retry_seconds, c->options.connect_retry_seconds, + c->options.connect_timeout, c->options.connect_retry_max, c->options.mtu_discover_type, c->options.rcvbuf, @@ -94,7 +94,8 @@ static const char usage_message[] = "--proto p : Use protocol p for communicating with peer.\n" " p = udp (default), tcp-server, or tcp-client\n" "--connect-retry n : For --proto tcp-client, number of seconds to wait\n" - " between connection retries (default=%d).\n" + " between connection retries (default=%d).\n" + "--connect-timeout n : For --proto tcp-client, connection timeout (in seconds).\n" "--connect-retry-max n : Maximum connection attempt retries, default infinite.\n" #ifdef ENABLE_HTTP_PROXY "--http-proxy s p [up] [auth] : Connect to remote host through an HTTP proxy at\n" @@ -598,6 +599,7 @@ init_options (struct options *o) o->topology = TOP_NET30; o->proto = PROTO_UDPv4; o->connect_retry_seconds = 5; + o->connect_timeout = 10; o->connect_retry_max = 0; o->local_port = o->remote_port = OPENVPN_PORT; o->verbosity = 1; @@ -1099,6 +1101,7 @@ show_settings (const struct options *o) SHOW_INT (resolve_retry_seconds); SHOW_INT (connect_retry_seconds); + SHOW_INT (connect_timeout); SHOW_INT (connect_retry_max); SHOW_STR (username); @@ -1381,6 +1384,9 @@ options_postprocess (struct options *options, bool first_time) if (options->connect_retry_defined && options->proto != PROTO_TCPv4_CLIENT) msg (M_USAGE, "--connect-retry doesn't make sense unless also used with --proto tcp-client"); + if (options->connect_timeout_defined && options->proto != PROTO_TCPv4_CLIENT) + msg (M_USAGE, "--connect-timeout doesn't make sense unless also used with --proto tcp-client"); + /* * Sanity check on MTU parameters */ @@ -3240,6 +3246,12 @@ add_option (struct options *options, options->connect_retry_seconds = positive_atoi (p[1]); options->connect_retry_defined = true; } + else if (streq (p[0], "connect-timeout") && p[1]) + { + VERIFY_PERMISSION (OPT_P_GENERAL); + options->connect_timeout = positive_atoi (p[1]); + options->connect_timeout_defined = true; + } else if (streq (p[0], "connect-retry-max") && p[1]) { VERIFY_PERMISSION (OPT_P_GENERAL); @@ -149,6 +149,8 @@ struct options int connect_retry_seconds; int connect_retry_max; bool connect_retry_defined; + int connect_timeout; + bool connect_timeout_defined; /* Advanced MTU negotiation and datagram fragmentation options */ int mtu_discover_type; /* used if OS supports setting Path MTU discovery options on socket */ @@ -712,6 +712,79 @@ socket_bind (socket_descriptor_t sd, gc_free (&gc); } +static int +openvpn_connect (socket_descriptor_t sd, + struct openvpn_sockaddr *remote, + int connect_timeout, + volatile int *signal_received) +{ + int status = 0; + +#ifdef CONNECT_NONBLOCK + set_nonblock (sd); + status = connect (sd, (struct sockaddr *) &remote->sa, sizeof (remote->sa)); + if (status) + status = openvpn_errno_socket (); + if (status == EINPROGRESS) + { + while (true) + { + fd_set writes; + struct timeval tv; + + FD_ZERO (&writes); + FD_SET (sd, &writes); + tv.tv_sec = 0; + tv.tv_usec = 0; + + status = select (sd + 1, NULL, &writes, NULL, &tv); + + get_signal (signal_received); + if (*signal_received) + { + status = 0; + break; + } + if (status < 0) + { + status = openvpn_errno_socket (); + break; + } + if (status <= 0) + { + if (--connect_timeout < 0) + { + status = ETIMEDOUT; + break; + } + openvpn_sleep (1); + continue; + } + + /* got it */ + { + int val = 0; + socklen_t len; + + len = sizeof (val); + if (getsockopt (sd, SOL_SOCKET, SO_ERROR, (void *) &val, &len) == 0 + && len == sizeof (val)) + status = val; + else + status = openvpn_errno_socket (); + break; + } + } + } +#else + status = connect (sd, (struct sockaddr *) &remote->sa, sizeof (remote->sa)); + if (status) + status = openvpn_errno_socket (); +#endif + + return status; +} + static void socket_connect (socket_descriptor_t *sd, struct openvpn_sockaddr *local, @@ -721,18 +794,24 @@ socket_connect (socket_descriptor_t *sd, const char *remote_dynamic, bool *remote_changed, const int connect_retry_seconds, + const int connect_timeout, const int connect_retry_max, volatile int *signal_received) { struct gc_arena gc = gc_new (); int retry = 0; +#ifdef CONNECT_NONBLOCK + msg (M_INFO, "Attempting to establish TCP connection with %s [nonblock]", + print_sockaddr (remote, &gc)); +#else msg (M_INFO, "Attempting to establish TCP connection with %s", print_sockaddr (remote, &gc)); +#endif + while (true) { - const int status = connect (*sd, (struct sockaddr *) &remote->sa, - sizeof (remote->sa)); + const int status = openvpn_connect (*sd, remote, connect_timeout, signal_received); if (connect_retry_max != 0 && retry++ >= connect_retry_max) *signal_received = SIGUSR1; @@ -744,10 +823,11 @@ socket_connect (socket_descriptor_t *sd, if (!status) break; - msg (D_LINK_ERRORS | M_ERRNO_SOCK, - "TCP: connect to %s failed, will try again in %d seconds", + msg (D_LINK_ERRORS, + "TCP: connect to %s failed, will try again in %d seconds: %s", print_sockaddr (remote, &gc), - connect_retry_seconds); + connect_retry_seconds, + strerror_ts (status, &gc)); openvpn_close_socket (*sd); openvpn_sleep (connect_retry_seconds); @@ -992,6 +1072,7 @@ link_socket_init_phase1 (struct link_socket *sock, 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, @@ -1023,6 +1104,7 @@ link_socket_init_phase1 (struct link_socket *sock, 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; @@ -1222,6 +1304,7 @@ link_socket_init_phase2 (struct link_socket *sock, remote_dynamic, &remote_changed, sock->connect_retry_seconds, + sock->connect_timeout, sock->connect_retry_max, signal_received); @@ -1263,6 +1346,7 @@ link_socket_init_phase2 (struct link_socket *sock, remote_dynamic, &remote_changed, sock->connect_retry_seconds, + sock->connect_timeout, sock->connect_retry_max, signal_received); @@ -189,6 +189,7 @@ struct link_socket int resolve_retry_seconds; int connect_retry_seconds; + int connect_timeout; int connect_retry_max; int mtu_discover_type; @@ -300,6 +301,7 @@ link_socket_init_phase1 (struct link_socket *sock, 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, @@ -478,4 +478,11 @@ socket_defined (const socket_descriptor_t sd) */ #define TIME_BACKTRACK_PROTECTION 1 +/* + * Is non-blocking connect() supported? + */ +#if defined(HAVE_GETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_ERROR) && defined(EINPROGRESS) && defined(ETIMEDOUT) +#define CONNECT_NONBLOCK +#endif + #endif |