Merge "Only look up A records if the system has IPv4." into gingerbread
diff --git a/libc/include/netinet/in6.h b/libc/include/netinet/in6.h
index 2f5fee1..efd5c0a 100644
--- a/libc/include/netinet/in6.h
+++ b/libc/include/netinet/in6.h
@@ -60,6 +60,10 @@
 #define IN6_IS_ADDR_SITELOCAL(a)	\
 	(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
 
+/* RFC 4193. */
+#define IN6_IS_ADDR_ULA(a)	\
+	(((a)->s6_addr[0] & 0xfe) == 0xfc)
+
 #define IN6_IS_ADDR_MULTICAST(a)	\
 	(((__const uint8_t *) (a))[0] == 0xff)
 
diff --git a/libc/netbsd/net/getaddrinfo.c b/libc/netbsd/net/getaddrinfo.c
index 895662e..e4d8c56 100644
--- a/libc/netbsd/net/getaddrinfo.c
+++ b/libc/netbsd/net/getaddrinfo.c
@@ -1319,11 +1319,13 @@
 		if (IN_LOOPBACK(na) ||                          /* 127.0.0.0/8 */
 		    (na & 0xffff0000) == 0xa9fe0000) {          /* 169.254.0.0/16 */
 			return IPV6_ADDR_SCOPE_LINKLOCAL;
-		} else if ((na & 0xff000000) == 0x0a000000 ||   /* 10.0.0.0/8 */
-			   (na & 0xfff00000) == 0xac100000 ||   /* 172.16.0.0/12 */
-			   (na & 0xffff0000) == 0xc0a80000) {   /* 192.168.0.0/16 */
-			return IPV6_ADDR_SCOPE_SITELOCAL;
 		} else {
+			/*
+			 * According to draft-ietf-6man-rfc3484-revise-01 section 2.3,
+			 * it is best not to treat the private IPv4 ranges
+			 * (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) as being
+			 * in a special scope, so we don't.
+			 */
 			return IPV6_ADDR_SCOPE_GLOBAL;
 		}
 	} else {
@@ -1345,9 +1347,13 @@
 #define IN6_IS_ADDR_6TO4(a)	 \
 	(((a)->s6_addr[0] == 0x20) && ((a)->s6_addr[1] == 0x02))
 
+/* 6bone testing address area (3ffe::/16), deprecated in RFC 3701. */
+#define IN6_IS_ADDR_6BONE(a)      \
+	(((a)->s6_addr[0] == 0x3f) && ((a)->s6_addr[1] == 0xfe))
+
 /*
  * Get the label for a given IPv4/IPv6 address.
- * RFC 3484, section 2.1, plus Teredo added in with label 5.
+ * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01.
  */
 
 /*ARGSUSED*/
@@ -1355,19 +1361,27 @@
 _get_label(const struct sockaddr *addr)
 {
 	if (addr->sa_family == AF_INET) {
-		return 4;
+		return 3;
 	} else if (addr->sa_family == AF_INET6) {
 		const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
 		if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) {
 			return 0;
-		} else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) {
+		} else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) {
+			return 1;
+		} else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
 			return 3;
+		} else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
+			return 4;
 		} else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) {
 			return 5;
-		} else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
-			return 2;
+		} else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) {
+			return 10;
+		} else if (IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)) {
+			return 11;
+		} else if (IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) {
+			return 12;
 		} else {
-			return 1;
+			return 2;
 		}
 	} else {
 		/*
@@ -1380,7 +1394,7 @@
 
 /*
  * Get the precedence for a given IPv4/IPv6 address.
- * RFC 3484, section 2.1, plus Teredo added in with precedence 25.
+ * RFC 3484, section 2.1, plus changes from draft-ietf-6man-rfc3484-revise-01.
  */
 
 /*ARGSUSED*/
@@ -1388,22 +1402,28 @@
 _get_precedence(const struct sockaddr *addr)
 {
 	if (addr->sa_family == AF_INET) {
-		return 10;
+		return 30;
 	} else if (addr->sa_family == AF_INET6) {
 		const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
 		if (IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)) {
+			return 60;
+		} else if (IN6_IS_ADDR_ULA(&addr6->sin6_addr)) {
 			return 50;
-		} else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr)) {
+		} else if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
+			return 30;
+		} else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
 			return 20;
 		} else if (IN6_IS_ADDR_TEREDO(&addr6->sin6_addr)) {
-			return 25;
-		} else if (IN6_IS_ADDR_6TO4(&addr6->sin6_addr)) {
-			return 30;
+			return 10;
+		} else if (IN6_IS_ADDR_V4COMPAT(&addr6->sin6_addr) ||
+		           IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr) ||
+		           IN6_IS_ADDR_6BONE(&addr6->sin6_addr)) {
+			return 1;
 		} else {
 			return 40;
 		}
 	} else {
-		return 5;
+		return 1;
 	}
 }