From 2213561e3a08507b11bdcd3c05076dfc0d3aa7d5 Mon Sep 17 00:00:00 2001 From: Alexandr Date: Wed, 22 Jan 2025 14:21:24 +0300 Subject: [PATCH] Add infinite reconnect_timeout and configurable reconnect_interval Signed-off-by: Alexandr --- .../libopenconnect/LibOpenConnect.java | 1 + jni.c | 10 +++++++ libopenconnect.map.in | 5 ++++ libopenconnect5.symbols | 1 + library.c | 5 ++++ main.c | 14 ++++++++- openconnect-internal.h | 1 + openconnect.h | 4 ++- ssl.c | 29 +++++++++++++++---- 9 files changed, 62 insertions(+), 8 deletions(-) diff --git a/java/src/org/infradead/libopenconnect/LibOpenConnect.java b/java/src/org/infradead/libopenconnect/LibOpenConnect.java index d13931796..d1de6a1ee 100644 --- a/java/src/org/infradead/libopenconnect/LibOpenConnect.java +++ b/java/src/org/infradead/libopenconnect/LibOpenConnect.java @@ -129,6 +129,7 @@ public abstract class LibOpenConnect { public synchronized native void setCertExpiryWarning(int seconds); public synchronized native void setDPD(int minSeconds); public synchronized native void setTrojanInterval(int seconds); + public synchronized native void setProgressiveReconnectInterval(boolean isEnabled); public synchronized native void setPassTOS(boolean isEnabled); public synchronized native int setProxyAuth(String methods); public synchronized native int setHTTPProxy(String proxy); diff --git a/jni.c b/jni.c index 112080c3c..19de8c127 100644 --- a/jni.c +++ b/jni.c @@ -1155,6 +1155,16 @@ JNIEXPORT jint JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_mainloop return openconnect_mainloop(ctx->vpninfo, arg0, arg1); } +JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setProgressiveReconnectInterval( + JNIEnv *jenv, jobject jobj, jboolean arg) +{ + struct libctx *ctx = getctx(jenv, jobj); + + if (!ctx) + return; + openconnect_set_progressive_reconnect_interval(ctx->vpninfo, arg); +} + JNIEXPORT void JNICALL Java_org_infradead_libopenconnect_LibOpenConnect_setLogLevel( JNIEnv *jenv, jobject jobj, jint arg) { diff --git a/libopenconnect.map.in b/libopenconnect.map.in index f036c0718..f63634f60 100644 --- a/libopenconnect.map.in +++ b/libopenconnect.map.in @@ -132,6 +132,11 @@ OPENCONNECT_5_9 { openconnect_set_sni; } OPENCONNECT_5_8; +OPENCONNECT_5_10 { +global: + openconnect_set_progressive_reconnect_interval; +} OPENCONNECT_5_9; + OPENCONNECT_PRIVATE { global: @SYMVER_TIME@ @SYMVER_GETLINE@ @SYMVER_JAVA@ @SYMVER_ASPRINTF@ @SYMVER_VASPRINTF@ @SYMVER_WIN32_STRERROR@ @SYMVER_WIN32_SETENV@ openconnect_get_tls_library_version; diff --git a/libopenconnect5.symbols b/libopenconnect5.symbols index 7cb04d059..251d1a6a3 100644 --- a/libopenconnect5.symbols +++ b/libopenconnect5.symbols @@ -103,3 +103,4 @@ libopenconnect.so.5 libopenconnect5 #MINVER# openconnect_set_mca_key_password@OPENCONNECT_5_8 9.00 openconnect_set_useragent@OPENCONNECT_5_8 9.00 openconnect_set_sni@OPENCONNECT_5_9 9.12 + openconnect_set_progressive_reconnect_interval@OPENCONNECT_5_10 9.12 diff --git a/library.c b/library.c index d5021594d..c1eda5224 100644 --- a/library.c +++ b/library.c @@ -101,6 +101,7 @@ struct openconnect_info *openconnect_vpninfo_new(const char *useragent, vpninfo->try_http_auth = 1; vpninfo->proxy_auth[AUTH_TYPE_BASIC].state = AUTH_DEFAULT_DISABLED; vpninfo->http_auth[AUTH_TYPE_BASIC].state = AUTH_DEFAULT_DISABLED; + vpninfo->is_progressive_reconnect_interval = 1; openconnect_set_reported_os(vpninfo, NULL); #ifdef HAVE_EPOLL vpninfo->epoll_fd = epoll_create1(EPOLL_CLOEXEC); @@ -1767,3 +1768,7 @@ int openconnect_webview_load_changed(struct openconnect_info *vpninfo, return -EOPNOTSUPP; } + +void openconnect_set_progressive_reconnect_interval(struct openconnect_info *vpninfo, unsigned val) { + vpninfo->is_progressive_reconnect_interval = val; +} diff --git a/main.c b/main.c index be0e3cd75..5c60d22e3 100644 --- a/main.c +++ b/main.c @@ -199,6 +199,7 @@ enum { OPT_PASSWORD_ON_STDIN, OPT_PRINTCOOKIE, OPT_RECONNECT_TIMEOUT, + OPT_RECONNECT_INTERVAL, OPT_SERVERCERT, OPT_RESOLVE, OPT_SNI, @@ -285,6 +286,7 @@ static const struct option long_options[] = { OPTION("passwd-on-stdin", 0, OPT_PASSWORD_ON_STDIN), OPTION("no-passwd", 0, OPT_NO_PASSWD), OPTION("reconnect-timeout", 1, OPT_RECONNECT_TIMEOUT), + OPTION("reconnect-interval", 1, OPT_RECONNECT_INTERVAL), OPTION("dtls-ciphers", 1, OPT_DTLS_CIPHERS), OPTION("dtls12-ciphers", 1, OPT_DTLS12_CIPHERS), OPTION("authgroup", 1, OPT_AUTHGROUP), @@ -1582,6 +1584,7 @@ static int autocomplete(int argc, char **argv) case 'u': /* --user */ case 'Q': /* --queue-len */ case OPT_RECONNECT_TIMEOUT: /* --reconnect-timeout */ + case OPT_RECONNECT_INTERVAL: /* --reconnect-interval */ case OPT_AUTHGROUP: /* --authgroup */ case OPT_RESOLVE: /* --resolve */ case OPT_SNI: /* --sni */ @@ -1789,6 +1792,8 @@ int main(int argc, char *argv[]) char *token_str = NULL; oc_token_mode_t token_mode = OC_TOKEN_MODE_NONE; int reconnect_timeout = 300; + int reconnect_interval = RECONNECT_INTERVAL_MIN; + unsigned is_progressive_reconnect_interval = 1; int ret; int verbose = PRG_INFO; #ifdef HAVE_NL_LANGINFO @@ -2043,6 +2048,11 @@ int main(int argc, char *argv[]) assert_nonnull_config_arg("reconnect-timeout", config_arg); reconnect_timeout = atoi(config_arg); break; + case OPT_RECONNECT_INTERVAL: + assert_nonnull_config_arg("reconnect-interval", config_arg); + reconnect_interval = atoi(config_arg); + is_progressive_reconnect_interval = 0; + break; case OPT_DTLS_CIPHERS: vpninfo->dtls_ciphers = keep_config_arg(); break; @@ -2300,6 +2310,8 @@ int main(int argc, char *argv[]) } } + openconnect_set_progressive_reconnect_interval(vpninfo, is_progressive_reconnect_interval); + if (gai_overrides) openconnect_override_getaddrinfo(vpninfo, gai_override_cb); @@ -2467,7 +2479,7 @@ int main(int argc, char *argv[]) openconnect_set_stats_handler(vpninfo, print_connection_stats); while (1) { - ret = openconnect_mainloop(vpninfo, reconnect_timeout, RECONNECT_INTERVAL_MIN); + ret = openconnect_mainloop(vpninfo, reconnect_timeout, reconnect_interval); if (ret) break; diff --git a/openconnect-internal.h b/openconnect-internal.h index 7ec0f21c1..b9329f836 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -644,6 +644,7 @@ struct openconnect_info { int disable_ipv6; int reconnect_timeout; int reconnect_interval; + unsigned is_progressive_reconnect_interval; int dtls_attempt_period; int udp_probes_sent; time_t auth_expiration; diff --git a/openconnect.h b/openconnect.h index 136f181ab..e653c6a2d 100644 --- a/openconnect.h +++ b/openconnect.h @@ -33,7 +33,7 @@ extern "C" { #endif #define OPENCONNECT_API_VERSION_MAJOR 5 -#define OPENCONNECT_API_VERSION_MINOR 9 +#define OPENCONNECT_API_VERSION_MINOR 10 /* * API version 5.9 (v9.12; 2023-05-20): @@ -731,6 +731,8 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, int reconnect_timeout, int reconnect_interval); +void openconnect_set_progressive_reconnect_interval(struct openconnect_info *vpninfo, unsigned val); + /* The first (privdata) argument to each of these functions is either the privdata argument provided to openconnect_vpninfo_new_with_cbdata(), or if that argument was NULL then it'll be the vpninfo itself. */ diff --git a/ssl.c b/ssl.c index 22bd04d19..18b0c7505 100644 --- a/ssl.c +++ b/ssl.c @@ -1216,25 +1216,42 @@ int ssl_reconnect(struct openconnect_info *vpninfo) if (!ret) break; - if (timeout <= 0) + /* -1 timeout is infinite reconnect */ + if (timeout <= 0 && timeout != -1) return ret; if (ret == -EPERM) { vpn_progress(vpninfo, PRG_ERR, _("Cookie is no longer valid, ending session\n")); return ret; } - vpn_progress(vpninfo, PRG_INFO, + /* -1 timeout is infinite reconnect */ + if (timeout == -1) { + vpn_progress(vpninfo, PRG_INFO, + _("sleep %ds\n"), + interval); + } + else { + vpn_progress(vpninfo, PRG_INFO, _("sleep %ds, remaining timeout %ds\n"), interval, timeout); + } poll_cmd_fd(vpninfo, interval); if (vpninfo->got_cancel_cmd) return -EINTR; if (vpninfo->got_pause_cmd) return 0; - timeout -= interval; - interval += vpninfo->reconnect_interval; - if (interval > RECONNECT_INTERVAL_MAX) - interval = RECONNECT_INTERVAL_MAX; + /* -1 timeout is infinite reconnect */ + if (timeout != -1) { + timeout -= interval; + /* to avoid wrong infinite loop */ + if (timeout == -1) + timeout = 0; + } + if (vpninfo->is_progressive_reconnect_interval) { + interval += vpninfo->reconnect_interval; + if (interval > RECONNECT_INTERVAL_MAX) + interval = RECONNECT_INTERVAL_MAX; + } } if (tun_up) { -- GitLab