@@ -123,7 +123,7 @@ tests += tst-spawn4-compat
endif
tests-internal := bug-regex5 bug-regex20 bug-regex33 \
- tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3
+ tst-rfc6724 tst-rfc6724-2 tst-rfc6724-3
tests-container := bug-ga2 tst-vfork3
tests-time64 := tst-wait4-time64 tst-wait3-time64 tst-gnuglob64-time64
xtests := tst-getaddrinfo4 tst-getaddrinfo5 tst-sched_rr_get_interval
@@ -1,7 +1,7 @@
# Configuration for getaddrinfo(3).
#
# So far only configuration for the destination address sorting is needed.
-# RFC 3484 governs the sorting. But the RFC also says that system
+# RFC 6724 governs the sorting. But the RFC also says that system
# administrators should be able to overwrite the defaults. This can be
# achieved here.
#
@@ -16,40 +16,34 @@
# used. There are possible runtime problems. The default is no.
#
# label <mask> <value>
-# Add another rule to the RFC 3484 label table. See section 2.1 in
-# RFC 3484. The default is:
+# Add another rule to the RFC 6724 label table. See section 2.1 in
+# RFC 6724. The default is:
#
#label ::1/128 0
#label ::/0 1
#label 2002::/16 2
#label ::/96 3
#label ::ffff:0:0/96 4
-#label fec0::/10 5
-#label fc00::/7 6
-#label 2001:0::/32 7
-#
-# This default differs from the tables given in RFC 3484 by handling
-# (now obsolete) site-local IPv6 addresses and Unique Local Addresses.
-# The reason for this difference is that these addresses are never
-# NATed while IPv4 site-local addresses most probably are. Given
-# the precedence of IPv6 over IPv4 (see below) on machines having only
-# site-local IPv4 and IPv6 addresses a lookup for a global address would
-# see the IPv6 be preferred. The result is a long delay because the
-# site-local IPv6 addresses cannot be used while the IPv4 address is
-# (at least for the foreseeable future) NATed. We also treat Teredo
-# tunnels special.
+#label 2001::/32 5
+#label fec0::/10 11
+#label 3ffe::/16 12
+#label fc00::/7 13
#
# precedence <mask> <value>
-# Add another rule to the RFC 3484 precedence table. See section 2.1
-# and 10.3 in RFC 3484. The default is:
-#
-#precedence ::1/128 50
-#precedence ::/0 40
-#precedence 2002::/16 30
-#precedence ::/96 20
-#precedence ::ffff:0:0/96 10
-#
-# For sites which prefer IPv4 connections change the last line to
+# Add another rule to the RFC 6724 precedence table. See section 2.1
+# and 10.3 in RFC 6724. The default is:
+#
+#precedence ::1/128 50
+#precedence ::/0 40
+#precedence ::ffff:0:0/96 35
+#precedence 2002::/16 30
+#precedence 2001::/32 5
+#precedence fc00::/7 3
+#precedence ::/96 1
+#precedence fec0::/10 1
+#precedence 3ffe::/16 1
+#
+# For sites which prefer IPv4 connections change the coresponding line to
#
#precedence ::ffff:0:0/96 100
similarity index 95%
rename from posix/tst-rfc3484-2.c
rename to posix/tst-rfc6724-2.c
@@ -62,7 +62,7 @@ _res_hconf_init (void)
nss_action_list __nss_hosts_database attribute_hidden;
/* This is the beginning of the real test code. The above defines
- (among other things) the function rfc3484_sort. */
+ (among other things) the function rfc6724_sort. */
#if __BYTE_ORDER == __BIG_ENDIAN
@@ -144,7 +144,7 @@ do_test (void)
struct sort_result_combo combo = { .results = results, .nresults = 2 };
- qsort_r (order, 2, sizeof (order[0]), rfc3484_sort, &combo);
+ qsort_r (order, 2, sizeof (order[0]), rfc6724_sort, &combo);
int result = 0;
if (results[order[0]].dest_addr->ai_family == AF_INET6)
@@ -174,7 +174,7 @@ do_test (void)
order[0] = 0;
- qsort_r (order, 2, sizeof (order[0]), rfc3484_sort, &combo);
+ qsort_r (order, 2, sizeof (order[0]), rfc6724_sort, &combo);
if (results[order[0]].dest_addr->ai_family == AF_INET6)
{
similarity index 96%
rename from posix/tst-rfc3484-3.c
rename to posix/tst-rfc6724-3.c
@@ -62,7 +62,7 @@ _res_hconf_init (void)
nss_action_list __nss_hosts_database attribute_hidden;
/* This is the beginning of the real test code. The above defines
- (among other things) the function rfc3484_sort. */
+ (among other things) the function rfc6724_sort. */
#if __BYTE_ORDER == __BIG_ENDIAN
@@ -141,7 +141,7 @@ do_test (void)
}
struct sort_result_combo combo = { .results = results, .nresults = naddrs };
- qsort_r (order, naddrs, sizeof (order[0]), rfc3484_sort, &combo);
+ qsort_r (order, naddrs, sizeof (order[0]), rfc6724_sort, &combo);
int result = 0;
for (int i = 0; i < naddrs; ++i)
similarity index 95%
rename from posix/tst-rfc3484.c
rename to posix/tst-rfc6724.c
@@ -62,7 +62,7 @@ _res_hconf_init (void)
nss_action_list __nss_hosts_database attribute_hidden;
/* This is the beginning of the real test code. The above defines
- (among other things) the function rfc3484_sort. */
+ (among other things) the function rfc6724_sort. */
#if __BYTE_ORDER == __BIG_ENDIAN
@@ -91,7 +91,7 @@ static size_t order[naddrs];
static int expected[naddrs] =
{
- 9, 4, 3, 6, 5, 7, 8, 2, 0, 1
+ 2, 3, 4, 5, 6, 7, 8, 9, 0, 1
};
@@ -133,7 +133,7 @@ do_test (void)
}
struct sort_result_combo combo = { .results = results, .nresults = naddrs };
- qsort_r (order, naddrs, sizeof (order[0]), rfc3484_sort, &combo);
+ qsort_r (order, naddrs, sizeof (order[0]), rfc6724_sort, &combo);
int result = 0;
for (int i = 0; i < naddrs; ++i)
@@ -1304,7 +1304,7 @@ static const struct prefixentry *labels;
/* Default labels. */
static const struct prefixentry default_labels[] =
{
- /* See RFC 3484 for the details. */
+ /* See RFC 6724 for the details. */
{ { .__in6_u
= { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
@@ -1321,26 +1321,22 @@ static const struct prefixentry default_labels[] =
= { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
}, 96, 4 },
- /* The next two entries differ from RFC 3484. We need to treat
- IPv6 site-local addresses special because they are never NATed,
- unlike site-locale IPv4 addresses. If this would not happen, on
- machines which have only IPv4 and IPv6 site-local addresses, the
- sorting would prefer the IPv6 site-local addresses, causing
- unnecessary delays when trying to connect to a global IPv6 address
- through a site-local IPv6 address. */
+ { { .__in6_u
+ = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+ }, 32, 5 },
{ { .__in6_u
= { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
- }, 10, 5 },
+ }, 10, 11 },
{ { .__in6_u
- = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ = { .__u6_addr8 = { 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
- }, 7, 6 },
- /* Additional rule for Teredo tunnels. */
+ }, 16, 12 },
{ { .__in6_u
- = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
- }, 32, 7 },
+ }, 7, 13 },
{ { .__in6_u
= { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
@@ -1354,23 +1350,39 @@ static const struct prefixentry *precedence;
/* The default precedences. */
static const struct prefixentry default_precedence[] =
{
- /* See RFC 3484 for the details. */
+ /* See RFC 6724 for the details. */
{ { .__in6_u
= { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
}, 128, 50 },
+ { { .__in6_u
+ = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
+ }, 96, 35 },
{ { .__in6_u
= { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
}, 16, 30 },
{ { .__in6_u
- = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
- }, 96, 20 },
+ = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+ }, 32, 5 },
+ { { .__in6_u
+ = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+ }, 7, 3 },
{ { .__in6_u
= { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
- }, 96, 10 },
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+ }, 96, 1 },
+ { { .__in6_u
+ = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+ }, 10, 1 },
+ { { .__in6_u
+ = { .__u6_addr8 = { 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+ }, 16, 1 },
{ { .__in6_u
= { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
@@ -1453,7 +1465,9 @@ fls (uint32_t a)
{
uint32_t mask;
int n;
- for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
+ if (a == 0)
+ return 0;
+ for (n = 0, mask = 1u << 31; n < 32; mask >>= 1, ++n)
if ((a & mask) != 0)
break;
return n;
@@ -1461,7 +1475,7 @@ fls (uint32_t a)
static int
-rfc3484_sort (const void *p1, const void *p2, void *arg)
+rfc6724_sort (const void *p1, const void *p2, void *arg)
{
const size_t idx1 = *(const size_t *) p1;
const size_t idx2 = *(const size_t *) p2;
@@ -1642,7 +1656,7 @@ rfc3484_sort (const void *p1, const void *p2, void *arg)
in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
- bit1 = fls (in1_dst_addr ^ in1_src_addr);
+ bit1 = a1->prefixlen;
struct sockaddr_in *in2_dst
= (struct sockaddr_in *) a2->dest_addr->ai_addr;
@@ -1653,7 +1667,7 @@ rfc3484_sort (const void *p1, const void *p2, void *arg)
in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
- bit2 = fls (in2_dst_addr ^ in2_src_addr);
+ bit2 = a2->prefixlen;
}
else if (a1->dest_addr->ai_family == PF_INET6)
{
@@ -1672,18 +1686,33 @@ rfc3484_sort (const void *p1, const void *p2, void *arg)
int i;
for (i = 0; i < 4; ++i)
- if (in1_dst->sin6_addr.s6_addr32[i]
- != in1_src->sin6_addr.s6_addr32[i]
- || (in2_dst->sin6_addr.s6_addr32[i]
- != in2_src->sin6_addr.s6_addr32[i]))
- break;
-
- if (i < 4)
{
- bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
- ^ in1_src->sin6_addr.s6_addr32[i]));
- bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
- ^ in2_src->sin6_addr.s6_addr32[i]));
+ uint32_t mask1, mask2;
+ if (i * 32 >= a1->prefixlen)
+ mask1 = 0;
+ else if ((i + 1) * 32 > a1->prefixlen)
+ mask1 = 0xffffffffu << (32 - (a1->prefixlen & 31));
+ else
+ mask1 = 0xffffffffu;
+ if (i * 32 >= a2->prefixlen)
+ mask2 = 0;
+ else if ((i + 1) * 32 > a2->prefixlen)
+ mask2 = 0xffffffffu << (32 - (a2->prefixlen & 31));
+ else
+ mask2 = 0xffffffffu;
+ if (((in1_dst->sin6_addr.s6_addr32[i]
+ ^ in1_src->sin6_addr.s6_addr32[i]) & htonl (mask1)) != 0
+ || ((in2_dst->sin6_addr.s6_addr32[i]
+ ^ in2_src->sin6_addr.s6_addr32[i]) & htonl (mask2)) != 0)
+ {
+ bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
+ ^ in1_src->sin6_addr.s6_addr32[i])
+ & mask1);
+ bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
+ ^ in2_src->sin6_addr.s6_addr32[i])
+ & mask2);
+ break;
+ }
}
}
@@ -1712,7 +1741,7 @@ in6aicmp (const void *p1, const void *p2)
}
-/* Name of the config file for RFC 3484 sorting (for now). */
+/* Name of the config file for RFC 6724 sorting (for now). */
#define GAICONF_FNAME "/etc/gai.conf"
@@ -2397,7 +2426,7 @@ getaddrinfo (const char *name, const char *service,
__libc_once_define (static, once);
__typeof (once) old_once = once;
__libc_once (once, gaiconf_init);
- /* Sort results according to RFC 3484. */
+ /* Sort results according to RFC 6724. */
struct sort_result *results;
size_t *order;
struct addrinfo *q;
@@ -2574,11 +2603,11 @@ getaddrinfo (const char *name, const char *service,
__libc_lock_lock (lock);
if (__libc_once_get (old_once) && gaiconf_reload_flag)
gaiconf_reload ();
- __qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
+ __qsort_r (order, nresults, sizeof (order[0]), rfc6724_sort, &src);
__libc_lock_unlock (lock);
}
else
- __qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
+ __qsort_r (order, nresults, sizeof (order[0]), rfc6724_sort, &src);
/* Queue the results up as they come out of sorting. */
q = p = results[order[0]].dest_addr;