Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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: Nikos Mavrogiannopoulos <nmav@gnutls.org>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
nmav authored and David Woodhouse committed Dec 5, 2014
1 parent 8af8f54 commit 2f55fec
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 2 deletions.
3 changes: 3 additions & 0 deletions cstp.c
Expand Up @@ -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")) {
Expand Down
1 change: 1 addition & 0 deletions openconnect-internal.h
Expand Up @@ -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;
Expand Down
48 changes: 47 additions & 1 deletion ssl.c
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand All @@ -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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion www/changelog.xml
Expand Up @@ -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>
Expand Down

0 comments on commit 2f55fec

Please sign in to comment.