Merge change 9642
* changes: Don't request IPv6 addresses if AI_ADDRCONFIG is specified and the system has no IPv6 connectivity.
This commit is contained in:
commit
ac68b70ed9
@ -335,6 +335,36 @@ str2number(const char *p)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine whether IPv6 connectivity is available. */
|
||||||
|
static int
|
||||||
|
_have_ipv6() {
|
||||||
|
/*
|
||||||
|
* Connect a UDP socket to an global unicast IPv6 address. This will
|
||||||
|
* cause no network traffic, but will fail fast if the system has no or
|
||||||
|
* limited IPv6 connectivity (e.g., only a link-local address).
|
||||||
|
*/
|
||||||
|
static const struct sockaddr_in6 sin6_test = {
|
||||||
|
/* family, port, flow label */
|
||||||
|
AF_INET6, 0, 0,
|
||||||
|
/* 2000:: */
|
||||||
|
{{{ 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}},
|
||||||
|
/* scope ID */
|
||||||
|
0};
|
||||||
|
static const struct sockaddr *sa_test = (struct sockaddr *) &sin6_test;
|
||||||
|
int s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (s < 0)
|
||||||
|
return 0;
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = connect(s, sa_test, sizeof(sin6_test));
|
||||||
|
} while (ret < 0 && errno == EINTR);
|
||||||
|
int have_ipv6 = (ret == 0);
|
||||||
|
do {
|
||||||
|
ret = close(s);
|
||||||
|
} while (ret < 0 && errno == EINTR);
|
||||||
|
return have_ipv6;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
getaddrinfo(const char *hostname, const char *servname,
|
getaddrinfo(const char *hostname, const char *servname,
|
||||||
const struct addrinfo *hints, struct addrinfo **res)
|
const struct addrinfo *hints, struct addrinfo **res)
|
||||||
@ -1274,7 +1304,6 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
|
|||||||
|
|
||||||
name = va_arg(ap, char *);
|
name = va_arg(ap, char *);
|
||||||
pai = va_arg(ap, const struct addrinfo *);
|
pai = va_arg(ap, const struct addrinfo *);
|
||||||
|
|
||||||
//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
|
//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
|
||||||
|
|
||||||
memset(&q, 0, sizeof(q));
|
memset(&q, 0, sizeof(q));
|
||||||
@ -1299,15 +1328,20 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
|
|||||||
/* prefer IPv6 */
|
/* prefer IPv6 */
|
||||||
q.name = name;
|
q.name = name;
|
||||||
q.qclass = C_IN;
|
q.qclass = C_IN;
|
||||||
q.qtype = T_AAAA;
|
|
||||||
q.answer = buf->buf;
|
q.answer = buf->buf;
|
||||||
q.anslen = sizeof(buf->buf);
|
q.anslen = sizeof(buf->buf);
|
||||||
q.next = &q2;
|
/* If AI_ADDRCONFIG, lookup IPv6 only if we have connectivity */
|
||||||
q2.name = name;
|
if (!(pai->ai_flags & AI_ADDRCONFIG) || _have_ipv6()) {
|
||||||
q2.qclass = C_IN;
|
q.qtype = T_AAAA;
|
||||||
q2.qtype = T_A;
|
q.next = &q2;
|
||||||
q2.answer = buf2->buf;
|
q2.name = name;
|
||||||
q2.anslen = sizeof(buf2->buf);
|
q2.qclass = C_IN;
|
||||||
|
q2.qtype = T_A;
|
||||||
|
q2.answer = buf2->buf;
|
||||||
|
q2.anslen = sizeof(buf2->buf);
|
||||||
|
} else {
|
||||||
|
q.qtype = T_A;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
q.name = name;
|
q.name = name;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user