aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2018-06-15 03:58:29 +0000
committerNIIBE Yutaka <[email protected]>2018-06-15 03:58:29 +0000
commitbcdbf8b8ebe9d61160e0b007dabe1b6462ffbc93 (patch)
tree4914b336320478ea20a7a5f481c7d3b8fc4b92cf
parentlibdns: Clear struct sockaddr_storage by zero. (diff)
downloadgnupg-bcdbf8b8ebe9d61160e0b007dabe1b6462ffbc93.tar.gz
gnupg-bcdbf8b8ebe9d61160e0b007dabe1b6462ffbc93.zip
libdns: Fix connect and try next nameserver when ECONNREFUSED.
* dirmngr/dns.c (dns_so_check): When EINVAL, release the association by connect with AF_UNSPEC and try again. Also try again for ECONNREFUSED. (dns_res_exec): Try next nameserver when ECONNREFUSED. -- GnuPG-bug-id: T3374 Signed-off-by: NIIBE Yutaka <[email protected]>
-rw-r--r--dirmngr/dns.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/dirmngr/dns.c b/dirmngr/dns.c
index 178070a90..d2445a0c6 100644
--- a/dirmngr/dns.c
+++ b/dirmngr/dns.c
@@ -7614,8 +7614,23 @@ retry:
so->state++; /* FALL THROUGH */
case DNS_SO_UDP_CONN:
+ udp_connect_retry:
error = dns_connect(so->udp, (struct sockaddr *)&so->remote, dns_sa_len(&so->remote));
dns_trace_sys_connect(so->trace, so->udp, SOCK_DGRAM, (struct sockaddr *)&so->remote, error);
+
+ /* Linux returns EINVAL when address was bound to
+ localhost and it's external IP address now. */
+ if (error == EINVAL) {
+ struct sockaddr unspec_addr;
+ memset (&unspec_addr, 0, sizeof unspec_addr);
+ unspec_addr.sa_family = AF_UNSPEC;
+ connect(so->udp, &unspec_addr, sizeof unspec_addr);
+ goto udp_connect_retry;
+ } else if (error == ECONNREFUSED)
+ /* Error for previous socket operation may
+ be reserverd asynchronously. */
+ goto udp_connect_retry;
+
if (error)
goto error;
@@ -8824,7 +8839,10 @@ exec:
if (dns_so_elapsed(&R->so) >= dns_resconf_timeout(R->resconf))
dgoto(R->sp, DNS_R_FOREACH_A);
- if ((error = dns_so_check(&R->so)))
+ error = dns_so_check(&R->so);
+ if (error == ECONNREFUSED)
+ dgoto(R->sp, DNS_R_FOREACH_A);
+ else if (error)
goto error;
if (!dns_p_setptr(&F->answer, dns_so_fetch(&R->so, &error)))
@@ -8957,7 +8975,10 @@ exec:
if (dns_so_elapsed(&R->so) >= dns_resconf_timeout(R->resconf))
dgoto(R->sp, DNS_R_FOREACH_AAAA);
- if ((error = dns_so_check(&R->so)))
+ error = dns_so_check(&R->so);
+ if (error == ECONNREFUSED)
+ dgoto(R->sp, DNS_R_FOREACH_AAAA);
+ else if (error)
goto error;
if (!dns_p_setptr(&F->answer, dns_so_fetch(&R->so, &error)))