123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- diff --git a/cstp.c b/cstp.c
- index b1235ef..f955b82 100644
- --- a/cstp.c
- +++ b/cstp.c
- @@ -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;
- interval = vpninfo->reconnect_interval;
-
- + /* 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))) {
- if (timeout <= 0)
- return ret;
- @@ -611,6 +624,11 @@ static int cstp_reconnect(struct openconnect_info *vpninfo)
- interval += vpninfo->reconnect_interval;
- if (interval > RECONNECT_INTERVAL_MAX)
- interval = RECONNECT_INTERVAL_MAX;
- +
- + if (dead_peer && vpninfo->first_peer_addr != NULL) {
- + free(vpninfo->peer_addr);
- + vpninfo->peer_addr = NULL;
- + }
- }
- script_config_tun(vpninfo, "reconnect");
- 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);
|