aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--forward-inline.h11
-rw-r--r--forward.c17
-rw-r--r--init.c10
-rw-r--r--openvpn.87
-rw-r--r--openvpn.h2
-rw-r--r--options.c15
-rw-r--r--options.h2
-rw-r--r--ssl.h6
8 files changed, 70 insertions, 0 deletions
diff --git a/forward-inline.h b/forward-inline.h
index c87996d..bb8f542 100644
--- a/forward-inline.h
+++ b/forward-inline.h
@@ -119,6 +119,17 @@ check_inactivity_timeout (struct context *c)
}
#if P2MP
+
+static inline void
+check_server_poll_timeout (struct context *c)
+{
+ void check_server_poll_timeout_dowork (struct context *c);
+
+ if (c->options.server_poll_timeout
+ && event_timeout_trigger (&c->c2.server_poll_interval, &c->c2.timeval, ETT_DEFAULT))
+ check_server_poll_timeout_dowork (c);
+}
+
/*
* Scheduled exit?
*/
diff --git a/forward.c b/forward.c
index 2205054..87f3350 100644
--- a/forward.c
+++ b/forward.c
@@ -314,6 +314,19 @@ check_inactivity_timeout_dowork (struct context *c)
#if P2MP
+void
+check_server_poll_timeout_dowork (struct context *c)
+{
+ event_timeout_reset (&c->c2.server_poll_interval);
+ if (!tls_initial_packet_received (c->c2.tls_multi))
+ {
+ msg (M_INFO, "Server poll timeout, restarting");
+ c->sig->signal_received = SIGUSR1;
+ c->sig->signal_text = "server_poll";
+ c->persist.restart_sleep_seconds = -1;
+ }
+}
+
/*
* Schedule a SIGTERM n_seconds from now.
*/
@@ -516,6 +529,10 @@ process_coarse_timers (struct context *c)
return;
#if P2MP
+ check_server_poll_timeout (c);
+ if (c->sig->signal_received)
+ return;
+
check_scheduled_exit (c);
if (c->sig->signal_received)
return;
diff --git a/init.c b/init.c
index 9d29af7..20ca0a5 100644
--- a/init.c
+++ b/init.c
@@ -792,6 +792,11 @@ do_init_timers (struct context *c, bool deferred)
if (c->options.ping_rec_timeout)
event_timeout_init (&c->c2.ping_rec_interval, c->options.ping_rec_timeout, now);
+#if P2MP
+ if (c->options.server_poll_timeout)
+ event_timeout_init (&c->c2.server_poll_interval, c->options.server_poll_timeout, now);
+#endif
+
if (!deferred)
{
/* initialize connection establishment timer */
@@ -1444,10 +1449,15 @@ socket_restart_pause (struct context *c)
#if P2MP
if (auth_retry_get () == AR_NOINTERACT)
sec = 10;
+
+ if (c->options.server_poll_timeout && sec > 1)
+ sec = 1;
#endif
if (c->persist.restart_sleep_seconds > 0 && c->persist.restart_sleep_seconds > sec)
sec = c->persist.restart_sleep_seconds;
+ else if (c->persist.restart_sleep_seconds == -1)
+ sec = 0;
c->persist.restart_sleep_seconds = 0;
/* do managment hold on context restart, i.e. second, third, fourth, etc. initialization */
diff --git a/openvpn.8 b/openvpn.8
index e9bc113..6f6138b 100644
--- a/openvpn.8
+++ b/openvpn.8
@@ -3279,6 +3279,13 @@ Note that while this option cannot be pushed, it can be controlled
from the management interface.
.\"*********************************************************
.TP
+.B --server-poll-timeout n
+when polling possible remote servers to connect to
+in a round-robin fashion, spend no more than
+.B n
+seconds waiting for a response before trying the next server.
+.\"*********************************************************
+.TP
.B --explicit-exit-notify [n]
In UDP client mode or point-to-point mode, send server/peer an exit notification
if tunnel is restarted or OpenVPN process is exited. In client mode, on
diff --git a/openvpn.h b/openvpn.h
index b850fd0..70df9e0 100644
--- a/openvpn.h
+++ b/openvpn.h
@@ -433,6 +433,8 @@ struct context_2
struct md5_state pulled_options_state;
struct md5_digest pulled_options_digest;
+ struct event_timeout server_poll_interval;
+
struct event_timeout scheduled_exit;
#endif
diff --git a/options.c b/options.c
index ce16b56..afd804f 100644
--- a/options.c
+++ b/options.c
@@ -432,6 +432,9 @@ static const char usage_message[] =
" when connecting to a '--mode server' remote host.\n"
"--auth-retry t : How to handle auth failures. Set t to\n"
" none (default), interact, or nointeract.\n"
+ "--server-poll-timeout n : when polling possible remote servers to connect to\n"
+ " in a round-robin fashion, spend no more than n seconds\n"
+ " waiting for a response before trying the next server.\n"
#endif
#ifdef ENABLE_OCC
"--explicit-exit-notify [n] : On exit/restart, send exit signal to\n"
@@ -726,6 +729,7 @@ init_options (struct options *o, const bool init_gc)
#endif
#if P2MP
o->scheduled_exit_interval = 5;
+ o->server_poll_timeout = 0;
#endif
#ifdef USE_CRYPTO
o->ciphername = "BF-CBC";
@@ -4464,6 +4468,12 @@ add_option (struct options *options,
{
options->sockflags |= SF_HOST_RANDOMIZE;
}
+#if P2MP
+ else if (streq (p[1], "SERVER_POLL_TIMEOUT") && p[2])
+ {
+ options->server_poll_timeout = positive_atoi(p[2]);
+ }
+#endif
else
{
if (streq (p[1], "FORWARD_COMPATIBLE") && p[2] && streq (p[2], "1"))
@@ -4887,6 +4897,11 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_PULL_MODE);
options->push_continuation = atoi(p[1]);
}
+ else if (streq (p[0], "server-poll-timeout") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->server_poll_timeout = positive_atoi(p[1]);
+ }
else if (streq (p[0], "auth-user-pass"))
{
VERIFY_PERMISSION (OPT_P_GENERAL);
diff --git a/options.h b/options.h
index fbf0e3c..740e18e 100644
--- a/options.h
+++ b/options.h
@@ -399,6 +399,8 @@ struct options
const char *auth_user_pass_file;
struct options_pre_pull *pre_pull;
+ int server_poll_timeout;
+
int scheduled_exit_interval;
#endif
diff --git a/ssl.h b/ssl.h
index 910c77c..e7ccb42 100644
--- a/ssl.h
+++ b/ssl.h
@@ -703,6 +703,12 @@ bool tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_i
*/
static inline bool
+tls_initial_packet_received (const struct tls_multi *multi)
+{
+ return multi->n_sessions > 0;
+}
+
+static inline bool
tls_test_auth_deferred_interval (const struct tls_multi *multi)
{
if (multi)