aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndroid (Google) Code Review <android-gerrit@google.com>2009-08-08 09:46:30 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2009-08-08 09:46:30 -0700
commitac68b70ed95db959274106d268deca1d303fa15c (patch)
tree0daab9df124f916b51c0eeb14258a519fa83bd09
parent44ac5d5d9353b74a9782e6ee9e4cf432c03800e1 (diff)
parent3d8f4ada56cc4965c8d2cbaa16d1bc0f75492c07 (diff)
downloadandroid_bionic-ac68b70ed95db959274106d268deca1d303fa15c.tar.gz
android_bionic-ac68b70ed95db959274106d268deca1d303fa15c.tar.bz2
android_bionic-ac68b70ed95db959274106d268deca1d303fa15c.zip
Merge change 9642
* changes: Don't request IPv6 addresses if AI_ADDRCONFIG is specified and the system has no IPv6 connectivity.
-rw-r--r--libc/netbsd/net/getaddrinfo.c50
1 files changed, 42 insertions, 8 deletions
diff --git a/libc/netbsd/net/getaddrinfo.c b/libc/netbsd/net/getaddrinfo.c
index f2189fbfe..1233cb82f 100644
--- a/libc/netbsd/net/getaddrinfo.c
+++ b/libc/netbsd/net/getaddrinfo.c
@@ -335,6 +335,36 @@ str2number(const char *p)
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
getaddrinfo(const char *hostname, const char *servname,
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 *);
pai = va_arg(ap, const struct addrinfo *);
-
//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
memset(&q, 0, sizeof(q));
@@ -1299,15 +1328,20 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
/* prefer IPv6 */
q.name = name;
q.qclass = C_IN;
- q.qtype = T_AAAA;
q.answer = buf->buf;
q.anslen = sizeof(buf->buf);
- q.next = &q2;
- q2.name = name;
- q2.qclass = C_IN;
- q2.qtype = T_A;
- q2.answer = buf2->buf;
- q2.anslen = sizeof(buf2->buf);
+ /* If AI_ADDRCONFIG, lookup IPv6 only if we have connectivity */
+ if (!(pai->ai_flags & AI_ADDRCONFIG) || _have_ipv6()) {
+ q.qtype = T_AAAA;
+ q.next = &q2;
+ q2.name = name;
+ q2.qclass = C_IN;
+ q2.qtype = T_A;
+ q2.answer = buf2->buf;
+ q2.anslen = sizeof(buf2->buf);
+ } else {
+ q.qtype = T_A;
+ }
break;
case AF_INET:
q.name = name;