Browse Source

openconnect: made server IP resolving on reconnection conditional

Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
lilik-openwrt-22.03
Nikos Mavrogiannopoulos 10 years ago
parent
commit
be753f0208
2 changed files with 147 additions and 8 deletions
  1. +1
    -1
      net/openconnect/Makefile
  2. +146
    -7
      net/openconnect/patches/001-always-resolve-ips.patch

+ 1
- 1
net/openconnect/Makefile View File

@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=openconnect PKG_NAME:=openconnect
PKG_VERSION:=7.00 PKG_VERSION:=7.00
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=ftp://ftp.infradead.org/pub/openconnect/ PKG_SOURCE_URL:=ftp://ftp.infradead.org/pub/openconnect/


+ 146
- 7
net/openconnect/patches/001-always-resolve-ips.patch View File

@ -1,22 +1,161 @@
diff --git a/cstp.c b/cstp.c diff --git a/cstp.c b/cstp.c
index b1235ef..05c3444 100644
index b1235ef..f955b82 100644
--- a/cstp.c --- a/cstp.c
+++ b/cstp.c +++ b/cstp.c
@@ -591,6 +591,8 @@ static int cstp_reconnect(struct openconnect_info *vpninfo)
@@ -570,7 +570,10 @@ int openconnect_make_cstp_connection(struct openconnect_info *vpninfo)
return ret;
}
-static int cstp_reconnect(struct openconnect_info *vpninfo)
+/* When dead peer is set, this function will re-attempt resolving
+ * the peer in case its IP changed.
+ */
+static int cstp_reconnect(struct openconnect_info *vpninfo, unsigned dead_peer)
{
int ret;
int timeout;
@@ -591,6 +594,16 @@ static int cstp_reconnect(struct openconnect_info *vpninfo)
timeout = vpninfo->reconnect_timeout; timeout = vpninfo->reconnect_timeout;
interval = vpninfo->reconnect_interval; interval = vpninfo->reconnect_interval;
+ free(vpninfo->peer_addr);
+ vpninfo->peer_addr = NULL;
+ /* handle cases with dynamic DNS by forcing a new resolve.
+ * The original IP is saved to retry as fallback if resolving
+ * fails.
+ */
+ if (dead_peer && vpninfo->first_peer_addr == NULL) {
+ vpninfo->first_peer_addr = vpninfo->peer_addr;
+ vpninfo->first_peer_addrlen = vpninfo->peer_addrlen;
+ vpninfo->peer_addr = NULL;
+ }
+
while ((ret = openconnect_make_cstp_connection(vpninfo))) { while ((ret = openconnect_make_cstp_connection(vpninfo))) {
if (timeout <= 0) if (timeout <= 0)
return ret; return ret;
@@ -611,6 +613,8 @@ static int cstp_reconnect(struct openconnect_info *vpninfo)
@@ -611,6 +624,11 @@ static int cstp_reconnect(struct openconnect_info *vpninfo)
interval += vpninfo->reconnect_interval; interval += vpninfo->reconnect_interval;
if (interval > RECONNECT_INTERVAL_MAX) if (interval > RECONNECT_INTERVAL_MAX)
interval = RECONNECT_INTERVAL_MAX; interval = RECONNECT_INTERVAL_MAX;
+ free(vpninfo->peer_addr);
+ vpninfo->peer_addr = NULL;
+
+ if (dead_peer && vpninfo->first_peer_addr != NULL) {
+ free(vpninfo->peer_addr);
+ vpninfo->peer_addr = NULL;
+ }
} }
script_config_tun(vpninfo, "reconnect"); script_config_tun(vpninfo, "reconnect");
return 0; return 0;
@@ -903,8 +921,15 @@ int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
/* Not that this will ever happen; we don't even process
the setting when we're asked for it. */
vpn_progress(vpninfo, PRG_INFO, _("CSTP rekey due\n"));
- if (vpninfo->ssl_times.rekey_method == REKEY_TUNNEL)
- goto do_reconnect;
+ if (vpninfo->ssl_times.rekey_method == REKEY_TUNNEL) {
+ ret = cstp_reconnect(vpninfo, 0);
+ if (ret) {
+ vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
+ vpninfo->quit_reason = "CSTP reconnect failed";
+ return ret;
+ }
+ goto do_dtls_reconnect;
+ }
else if (vpninfo->ssl_times.rekey_method == REKEY_SSL) {
ret = cstp_handshake(vpninfo, 0);
if (ret) {
@@ -922,7 +947,7 @@ int cstp_mainloop(struct openconnect_info *vpninfo, int *timeout)
vpn_progress(vpninfo, PRG_ERR,
_("CSTP Dead Peer Detection detected dead peer!\n"));
do_reconnect:
- ret = cstp_reconnect(vpninfo);
+ ret = cstp_reconnect(vpninfo, 1);
if (ret) {
vpn_progress(vpninfo, PRG_ERR, _("Reconnect failed\n"));
vpninfo->quit_reason = "CSTP reconnect failed";
diff --git a/library.c b/library.c
index f5d3dc9..7c8d5ec 100644
--- a/library.c
+++ b/library.c
@@ -178,6 +178,7 @@ void openconnect_vpninfo_free(struct openconnect_info *vpninfo)
CloseHandle(vpninfo->dtls_event);
#endif
free(vpninfo->peer_addr);
+ free(vpninfo->first_peer_addr);
free_optlist(vpninfo->csd_env);
free_optlist(vpninfo->script_env);
free_optlist(vpninfo->cookies);
@@ -291,6 +292,8 @@ int openconnect_set_hostname(struct openconnect_info *vpninfo,
vpninfo->unique_hostname = NULL;
free(vpninfo->peer_addr);
vpninfo->peer_addr = NULL;
+ free(vpninfo->first_peer_addr);
+ vpninfo->first_peer_addr = NULL;
return 0;
}
diff --git a/openconnect-internal.h b/openconnect-internal.h
index 1bc79e5..cafbb3c 100644
--- a/openconnect-internal.h
+++ b/openconnect-internal.h
@@ -424,6 +424,9 @@ struct openconnect_info {
struct sockaddr *peer_addr;
struct sockaddr *dtls_addr;
+ struct sockaddr *first_peer_addr;
+ socklen_t first_peer_addrlen;
+
int dtls_local_port;
int deflate;
diff --git a/ssl.c b/ssl.c
index b50652d..e341871 100644
--- a/ssl.c
+++ b/ssl.c
@@ -110,6 +110,7 @@ int connect_https_socket(struct openconnect_info *vpninfo)
{
int ssl_sock = -1;
int err;
+ unsigned retry_old_ip = 0;
if (!vpninfo->port)
vpninfo->port = 443;
@@ -230,6 +231,8 @@ int connect_https_socket(struct openconnect_info *vpninfo)
if (hints.ai_flags & AI_NUMERICHOST)
free(hostname);
ssl_sock = -EINVAL;
+ if (vpninfo->first_peer_addr != NULL)
+ retry_old_ip = 1;
goto out;
}
if (hints.ai_flags & AI_NUMERICHOST)
@@ -291,7 +294,10 @@ int connect_https_socket(struct openconnect_info *vpninfo)
}
freeaddrinfo(result);
+
if (ssl_sock < 0) {
+ if (vpninfo->first_peer_addr != NULL)
+ retry_old_ip = 1;
vpn_progress(vpninfo, PRG_ERR,
_("Failed to connect to host %s\n"),
vpninfo->proxy?:vpninfo->hostname);
@@ -314,6 +320,21 @@ int connect_https_socket(struct openconnect_info *vpninfo)
}
}
out:
+ if (retry_old_ip != 0 && vpninfo->first_peer_addr != NULL) {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Retrying connection to host %s with original IP\n"),
+ vpninfo->proxy?:vpninfo->hostname);
+
+ retry_old_ip = 0;
+ if (vpninfo->first_peer_addrlen > vpninfo->peer_addrlen || vpninfo->peer_addr == NULL)
+ realloc_inplace(vpninfo->peer_addr, vpninfo->first_peer_addrlen);
+
+ if (vpninfo->peer_addr != NULL) {
+ memcpy(vpninfo->peer_addr, vpninfo->first_peer_addr, vpninfo->first_peer_addrlen);
+ goto reconnect;
+ }
+ }
+
/* If proxy processing returned -EAGAIN to reconnect before attempting
further auth, and we failed to reconnect, we have to clean up here. */
cleanup_proxy_auth(vpninfo);

Loading…
Cancel
Save