Commit 2f55fec3 authored by Nikos Mavrogiannopoulos's avatar Nikos Mavrogiannopoulos Committed by David Woodhouse

Re-resolve when reconnecting CSTP and the X-CSTP-DynDNS is set by the server

That is, when reconnecting CSTP due to peer tearing the connection
down attempt to re-resolve its IP. That handles the case where
the server is using dynamic DNS and is advertising it.

[dwmw2: refactored to simplify it somewhat]
Signed-off-by: default avatarNikos Mavrogiannopoulos <nmav@gnutls.org>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 8af8f547
......@@ -378,6 +378,9 @@ static int start_cstp_connection(struct openconnect_info *vpninfo)
int cstpmtu = atol(colon);
if (cstpmtu > mtu)
mtu = cstpmtu;
} else if (!strcmp(buf + 7, "DynDNS")) {
if (!strcmp(colon, "true"))
vpninfo->is_dyndns = 1;
} else if (!strcmp(buf + 7, "Address-IP6")) {
vpninfo->ip_info.netmask6 = new_option->value;
} else if (!strcmp(buf + 7, "Address")) {
......
......@@ -427,6 +427,7 @@ struct openconnect_info {
int dtls_local_port;
int deflate;
int is_dyndns; /* Attempt to redo DNS lookup on each CSTP reconnect */
char *useragent;
const char *quit_reason;
......
......@@ -106,6 +106,23 @@ unsigned string_is_hostname(const char *str)
return 1;
}
static int match_sockaddr(struct sockaddr *a, struct sockaddr *b)
{
if (a->sa_family == AF_INET) {
struct sockaddr_in *a4 = (void *)a;
struct sockaddr_in *b4 = (void *)b;
return (a4->sin_addr.s_addr == b4->sin_addr.s_addr) &&
(a4->sin_port == b4->sin_port);
} else if (a->sa_family == AF_INET6) {
struct sockaddr_in6 *a6 = (void *)a;
struct sockaddr_in6 *b6 = (void *)b;
return !memcmp(&a6->sin6_addr, &b6->sin6_addr, sizeof(a6->sin6_addr) &&
a6->sin6_port == b6->sin6_port);
} else
return 0;
}
int connect_https_socket(struct openconnect_info *vpninfo)
{
int ssl_sock = -1;
......@@ -114,7 +131,11 @@ int connect_https_socket(struct openconnect_info *vpninfo)
if (!vpninfo->port)
vpninfo->port = 443;
if (vpninfo->peer_addr) {
/* If we're talking to a server which told us it has dynamic DNS, don't
just re-use its previous IP address. If we're talking to a proxy, we
can use *its* previous IP address. We expect it'll re-do the DNS
lookup for the server anyway. */
if (vpninfo->peer_addr && (!vpninfo->is_dyndns || vpninfo->proxy)) {
reconnect:
#ifdef SOCK_CLOEXEC
ssl_sock = socket(vpninfo->peer_addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_IP);
......@@ -230,6 +251,13 @@ int connect_https_socket(struct openconnect_info *vpninfo)
if (hints.ai_flags & AI_NUMERICHOST)
free(hostname);
ssl_sock = -EINVAL;
/* If we were just retrying for dynamic DNS, reconnct using
the previously-known IP address */
if (vpninfo->peer_addr) {
vpn_progress(vpninfo, PRG_ERR,
_("Reconnecting to DynDNS server using previously cached IP address\n"));
goto reconnect;
}
goto out;
}
if (hints.ai_flags & AI_NUMERICHOST)
......@@ -257,6 +285,8 @@ int connect_https_socket(struct openconnect_info *vpninfo)
if (cancellable_connect(vpninfo, ssl_sock, rp->ai_addr, rp->ai_addrlen) >= 0) {
/* Store the peer address we actually used, so that DTLS can
use it again later */
free(vpninfo->peer_addr);
vpninfo->peer_addrlen = 0;
vpninfo->peer_addr = malloc(rp->ai_addrlen);
if (!vpninfo->peer_addr) {
vpn_progress(vpninfo, PRG_ERR,
......@@ -288,6 +318,17 @@ int connect_https_socket(struct openconnect_info *vpninfo)
}
closesocket(ssl_sock);
ssl_sock = -1;
/* If we're in DynDNS mode but this *was* the cached IP address,
* don't bother falling back to it if it didn't work. */
if (vpninfo->peer_addr && vpninfo->peer_addrlen == rp->ai_addrlen &&
match_sockaddr(vpninfo->peer_addr, rp->ai_addr)) {
vpn_progress(vpninfo, PRG_TRACE,
_("Forgetting non-functional previous peer address\n"));
free(vpninfo->peer_addr);
vpninfo->peer_addr = 0;
vpninfo->peer_addrlen = 0;
}
}
freeaddrinfo(result);
......@@ -296,6 +337,11 @@ int connect_https_socket(struct openconnect_info *vpninfo)
_("Failed to connect to host %s\n"),
vpninfo->proxy?:vpninfo->hostname);
ssl_sock = -EINVAL;
if (vpninfo->peer_addr) {
vpn_progress(vpninfo, PRG_ERR,
_("Reconnecting to DynDNS server using previously cached IP address\n"));
goto reconnect;
}
goto out;
}
}
......
......@@ -15,7 +15,7 @@
<ul>
<li><b>OpenConnect HEAD</b>
<ul>
<li><i>No changelog entries yet</i></li>
<li>Add support for <tt>X-CSTP-DynDNS</tt>, to trigger DNS lookup on each reconnect.</li>
</ul><br/>
</li>
<li><b><a href="ftp://ftp.infradead.org/pub/openconnect/openconnect-7.00.tar.gz">OpenConnect v7.00</a></b>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment