aboutsummaryrefslogtreecommitdiff
path: root/resolv
diff options
context:
space:
mode:
Diffstat (limited to 'resolv')
-rw-r--r--resolv/res_init.c9
-rw-r--r--resolv/res_send.c15
-rw-r--r--resolv/resolv.h6
3 files changed, 19 insertions, 11 deletions
diff --git a/resolv/res_init.c b/resolv/res_init.c
index 640e087920..d1a5681a93 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -241,8 +241,8 @@ __res_vinit(res_state statp, int preinit) {
line[sizeof(name) - 1] == '\t'))
if ((fp = fopen(_PATH_RESCONF, "rc")) != NULL) {
- /* No threads use this stream. */
- __fsetlocking (fp, FSETLOCKING_BYCALLER);
+ /* No threads use this stream. */
+ __fsetlocking (fp, FSETLOCKING_BYCALLER);
/* read the config file */
while (fgets_unlocked(buf, sizeof(buf), fp) != NULL) {
/* skip comments */
@@ -397,8 +397,11 @@ __res_vinit(res_state statp, int preinit) {
if (nserv > 1)
statp->nscount = nserv;
#ifdef _LIBC
- if (nservall - nserv > 0)
+ if (nservall - nserv > 0) {
statp->_u._ext.nscount6 = nservall - nserv;
+ /* We try IPv6 servers again. */
+ statp->ipv6_unavail = false;
+ }
#endif
#ifdef RESOLVSORT
statp->nsort = nsort;
diff --git a/resolv/res_send.c b/resolv/res_send.c
index f38c399ffd..27dd1d4351 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -813,17 +813,20 @@ send_dg(res_state statp,
struct pollfd pfd[1];
int ptimeout;
struct sockaddr_in6 from;
- static int socket_pf = 0;
socklen_t fromlen;
int resplen, seconds, n;
if (EXT(statp).nssocks[ns] == -1) {
/* only try IPv6 if IPv6 NS and if not failed before */
- if ((EXT(statp).nscount6 > 0) && (socket_pf != PF_INET)) {
+ if ((EXT(statp).nscount6 > 0) && !statp->ipv6_unavail) {
EXT(statp).nssocks[ns] =
socket(PF_INET6, SOCK_DGRAM, 0);
- socket_pf = EXT(statp).nssocks[ns] < 0 ? PF_INET
- : PF_INET6;
+ if (EXT(statp).nssocks[ns] < 0)
+ statp->ipv6_unavail = errno == EAFNOSUPPORT;
+ /* If IPv6 socket and nsap is IPv4, make it
+ IPv4-mapped */
+ else if (nsap->sin6_family == AF_INET)
+ convaddr4to6(nsap);
}
if (EXT(statp).nssocks[ns] < 0)
EXT(statp).nssocks[ns] = socket(PF_INET, SOCK_DGRAM, 0);
@@ -832,9 +835,7 @@ send_dg(res_state statp,
Perror(statp, stderr, "socket(dg)", errno);
return (-1);
}
- /* If IPv6 socket and nsap is IPv4, make it IPv4-mapped */
- if ((socket_pf == PF_INET6) && (nsap->sin6_family == AF_INET))
- convaddr4to6(nsap);
+
/*
* On a 4.3BSD+ machine (client and server,
* actually), sending to a nameserver datagram
diff --git a/resolv/resolv.h b/resolv/resolv.h
index 9aa09b8701..105631ee7d 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -110,21 +110,25 @@ struct __res_state {
nsaddr_list[MAXNS]; /* address of name server */
# define nsaddr nsaddr_list[0] /* for backward compatibility */
u_short id; /* current message id */
+ /* 2 byte hole here. */
char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */
char defdname[256]; /* default domain (deprecated) */
u_long pfcode; /* RES_PRF_ flags - see below. */
unsigned ndots:4; /* threshold for initial abs. query */
unsigned nsort:4; /* number of elements in sort_list[] */
- char unused[3];
+ unsigned ipv6_unavail:1; /* connecting to IPv6 server failed */
+ unsigned unused:23;
struct {
struct in_addr addr;
u_int32_t mask;
} sort_list[MAXRESOLVSORT];
+ /* 4 byte hole here on 64-bit architectures. */
res_send_qhook qhook; /* query hook */
res_send_rhook rhook; /* response hook */
int res_h_errno; /* last one set for this context */
int _vcsock; /* PRIVATE: for res_send VC i/o */
u_int _flags; /* PRIVATE: see below */
+ /* 4 byte hole here on 64-bit architectures. */
union {
char pad[52]; /* On an i386 this means 512b total. */
struct {