public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Update getaddrinfo to RFC 6724 (bug 29496)
@ 2022-09-06  9:28 Andreas Schwab
  2023-09-04 15:53 ` Florian Weimer
  0 siblings, 1 reply; 7+ messages in thread
From: Andreas Schwab @ 2022-09-06  9:28 UTC (permalink / raw)
  To: libc-alpha

RFC 6724 is the successor of RFC 3484 and updated the default policy table
and the address selection rules.  The policy table contains more entries
to depreference deprecated prefixes.  The longest prefix match rule has
been updated to only compare the prefix part of the addresses, so that
addresses on the same subnet are no longer reordered.
---
 posix/Makefile                             |   2 +-
 posix/gai.conf                             |  48 ++++-----
 posix/{tst-rfc3484-2.c => tst-rfc6724-2.c} |   6 +-
 posix/{tst-rfc3484-3.c => tst-rfc6724-3.c} |   4 +-
 posix/{tst-rfc3484.c => tst-rfc6724.c}     |   6 +-
 sysdeps/posix/getaddrinfo.c                | 107 +++++++++++++--------
 6 files changed, 98 insertions(+), 75 deletions(-)
 rename posix/{tst-rfc3484-2.c => tst-rfc6724-2.c} (95%)
 rename posix/{tst-rfc3484-3.c => tst-rfc6724-3.c} (96%)
 rename posix/{tst-rfc3484.c => tst-rfc6724.c} (95%)

diff --git a/posix/Makefile b/posix/Makefile
index cb36b506c9..aacb515e62 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -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
diff --git a/posix/gai.conf b/posix/gai.conf
index 4616ed005b..de76e2c26f 100644
--- a/posix/gai.conf
+++ b/posix/gai.conf
@@ -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
 
diff --git a/posix/tst-rfc3484-2.c b/posix/tst-rfc6724-2.c
similarity index 95%
rename from posix/tst-rfc3484-2.c
rename to posix/tst-rfc6724-2.c
index ce8ccd5f38..d882124513 100644
--- a/posix/tst-rfc3484-2.c
+++ b/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)
     {
diff --git a/posix/tst-rfc3484-3.c b/posix/tst-rfc6724-3.c
similarity index 96%
rename from posix/tst-rfc3484-3.c
rename to posix/tst-rfc6724-3.c
index ecb163963f..59244fd73f 100644
--- a/posix/tst-rfc3484-3.c
+++ b/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)
diff --git a/posix/tst-rfc3484.c b/posix/tst-rfc6724.c
similarity index 95%
rename from posix/tst-rfc3484.c
rename to posix/tst-rfc6724.c
index 3b2052eb54..a1485ba59a 100644
--- a/posix/tst-rfc3484.c
+++ b/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)
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index bcff909b2f..3da296816a 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -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;
-- 
2.37.3


-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Update getaddrinfo to RFC 6724 (bug 29496)
  2022-09-06  9:28 [PATCH] Update getaddrinfo to RFC 6724 (bug 29496) Andreas Schwab
@ 2023-09-04 15:53 ` Florian Weimer
  2023-09-04 16:16   ` Andreas Schwab
  0 siblings, 1 reply; 7+ messages in thread
From: Florian Weimer @ 2023-09-04 15:53 UTC (permalink / raw)
  To: Andreas Schwab via Libc-alpha; +Cc: Andreas Schwab

* Andreas Schwab via Libc-alpha:

> diff --git a/posix/gai.conf b/posix/gai.conf
> index 4616ed005b..de76e2c26f 100644
> --- a/posix/gai.conf
> +++ b/posix/gai.conf

> @@ -16,40 +16,34 @@
>  #    used.  There are possible runtime problems.  The default is no.
>  #
>  # label   <mask>   <value>
> +#    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 2001::/32     5
> +#label fec0::/10     11
> +#label 3ffe::/16     12
> +#label fc00::/7      13

Change matches new table in section 2.1.

> -#    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

Likewise.

> diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
> index bcff909b2f..3da296816a 100644
> --- a/sysdeps/posix/getaddrinfo.c
> +++ b/sysdeps/posix/getaddrinfo.c
> @@ -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 } }

> @@ -1354,23 +1350,39 @@ static const struct prefixentry *precedence;
>  /* The default precedences.  */
>  static const struct prefixentry default_precedence[] =

Table updates match the RFC.

> @@ -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;
>  	}

This is an undocumented change that I can't find in RFC 6724.  I have a
general distaste for Rule 9, so anything that treats more addresses as
equivalent is fine with me.  However, it is not clear to me why we would
prefer subnets with longer prefixes.  Setting bit1 and bit2 to 1 if the
source and destination address are on the same subnet should achieve the
same thing.

This does not conform to RFC 6724, so it needs a comment, and probably a
NEWS entry as well.

>        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)
>  	    {
> +	      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;
> +		}

Why use the common prefix length for IPv6 addresses?  RFC 6724 pretends
that IPv6 assignment is strictly hierarchical, but in reality, it's
not.  Shouldn't we do the same thing as for IPv4 addresses?

It's not clear to me why you changed the implementation.  Does it fix a
bug?  

Thanks,
Florian


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Update getaddrinfo to RFC 6724 (bug 29496)
  2023-09-04 15:53 ` Florian Weimer
@ 2023-09-04 16:16   ` Andreas Schwab
  2023-09-05 12:19     ` Florian Weimer
  0 siblings, 1 reply; 7+ messages in thread
From: Andreas Schwab @ 2023-09-04 16:16 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Andreas Schwab via Libc-alpha

On Sep 04 2023, Florian Weimer wrote:

>> @@ -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;
>>  	}
>
> This is an undocumented change that I can't find in RFC 6724.

See Appendix B, changes to the rules, "Changed the definition of
CommonPrefixLen()".

>
>>        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)
>>  	    {
>> +	      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;
>> +		}
>
> Why use the common prefix length for IPv6 addresses?  RFC 6724 pretends
> that IPv6 assignment is strictly hierarchical, but in reality, it's
> not.  Shouldn't we do the same thing as for IPv4 addresses?

That's the same consequence as above due to the changes in
CommonPrefixLen.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Update getaddrinfo to RFC 6724 (bug 29496)
  2023-09-04 16:16   ` Andreas Schwab
@ 2023-09-05 12:19     ` Florian Weimer
  2023-09-05 12:31       ` Andreas Schwab
  0 siblings, 1 reply; 7+ messages in thread
From: Florian Weimer @ 2023-09-05 12:19 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Andreas Schwab via Libc-alpha

* Andreas Schwab:

> On Sep 04 2023, Florian Weimer wrote:
>
>>> @@ -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;
>>>  	}
>>
>> This is an undocumented change that I can't find in RFC 6724.
>
> See Appendix B, changes to the rules, "Changed the definition of
> CommonPrefixLen()".

So it's the “up to the length of S's prefix” part here:

| 2.2.  Common Prefix Length
| 
|    We define the common prefix length CommonPrefixLen(S, D) of a source
|    address S and a destination address D as the length of the longest
|    prefix (looking at the most significant, or leftmost, bits) that the
|    two addresses have in common, up to the length of S's prefix (i.e.,
|    the portion of the address not including the interface ID).  For
|    example, CommonPrefixLen(fe80::1, fe80::2) is 64.

There's an erratum for this because not all addresses have interface
IDs, so this is just confusing.

In any case, new code still does not implement the rule that prefers
longer common prefixes.  Our rule goes like this, if I understand the
code correctly:

* If one source/destination pair is on the same subnet and the other is
  not, prefer the first.

* If both source/destination pairs are on the same (but potentially
  distinct) subnets, prefer the smaller subnet, the one with the longer
  prefix.

I still think the second, length-based heuristic is dubious.  In any
case, it doesn't match what's in the RFC (and there's an old comment to
that effect).  To reiterate, I think that's fine, and we should go
further.

>>> @@ -1672,18 +1686,33 @@ rfc3484_sort (const void *p1, const void *p2, void *arg)
>>>  
>>>  	  int i;
>>>  	  for (i = 0; i < 4; ++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;
>>> +		}
>>
>> Why use the common prefix length for IPv6 addresses?  RFC 6724 pretends
>> that IPv6 assignment is strictly hierarchical, but in reality, it's
>> not.  Shouldn't we do the same thing as for IPv4 addresses?
>
> That's the same consequence as above due to the changes in
> CommonPrefixLen.

But it doesn't implement the same algorithm, as far as I can tell.  I
think we should use this in both cases:

* If one source/destination pair is on the same subnet and the other is
  not, prefer the first.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Update getaddrinfo to RFC 6724 (bug 29496)
  2023-09-05 12:19     ` Florian Weimer
@ 2023-09-05 12:31       ` Andreas Schwab
  2023-09-05 12:44         ` Florian Weimer
  0 siblings, 1 reply; 7+ messages in thread
From: Andreas Schwab @ 2023-09-05 12:31 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Andreas Schwab via Libc-alpha

On Sep 05 2023, Florian Weimer wrote:

> There's an erratum for this

What does that mean?

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] Update getaddrinfo to RFC 6724 (bug 29496)
  2023-09-05 12:31       ` Andreas Schwab
@ 2023-09-05 12:44         ` Florian Weimer
  0 siblings, 0 replies; 7+ messages in thread
From: Florian Weimer @ 2023-09-05 12:44 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Andreas Schwab via Libc-alpha

* Andreas Schwab:

> On Sep 05 2023, Florian Weimer wrote:
>
>> There's an erratum for this
>
> What does that mean?

There's an unverified entry on this page:

  <https://www.rfc-editor.org/errata/rfc6724>

It discusses section 2.2.  I do not agree with the proposed resolution.
It essentially recommends going back to the old behavior which assumes
strictly hierarchical IPv6 address assignment.


Thanks,
Florian


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH] Update getaddrinfo to RFC 6724 (bug 29496)
@ 2023-10-24 11:27 Andreas Schwab
  0 siblings, 0 replies; 7+ messages in thread
From: Andreas Schwab @ 2023-10-24 11:27 UTC (permalink / raw)
  To: libc-alpha

RFC 6724 is the successor of RFC 3484 and updated the default policy table
and the address selection rules.  The policy table contains more entries
to depreference deprecated prefixes.  The longest prefix match rule has
been updated to only compare the prefix part of the addresses, so that
addresses on the same subnet are no longer reordered.
---
 nss/Makefile                             |   6 +-
 nss/getaddrinfo.c                        | 107 ++++++++++++++---------
 nss/{tst-rfc3484-2.c => tst-rfc6724-2.c} |   6 +-
 nss/{tst-rfc3484-3.c => tst-rfc6724-3.c} |   4 +-
 nss/{tst-rfc3484.c => tst-rfc6724.c}     |   6 +-
 posix/gai.conf                           |  48 +++++-----
 6 files changed, 100 insertions(+), 77 deletions(-)
 rename nss/{tst-rfc3484-2.c => tst-rfc6724-2.c} (95%)
 rename nss/{tst-rfc3484-3.c => tst-rfc6724-3.c} (96%)
 rename nss/{tst-rfc3484.c => tst-rfc6724.c} (95%)

diff --git a/nss/Makefile b/nss/Makefile
index 213b68720b..9162912264 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -306,9 +306,9 @@ tests-static            = tst-field
 
 tests-internal := \
   tst-field \
-  tst-rfc3484 \
-  tst-rfc3484-2 \
-  tst-rfc3484-3 \
+  tst-rfc6724 \
+  tst-rfc6724-2 \
+  tst-rfc6724-3 \
   # tests-internal
 
 tests := \
diff --git a/nss/getaddrinfo.c b/nss/getaddrinfo.c
index 531124958d..6902a47224 100644
--- a/nss/getaddrinfo.c
+++ b/nss/getaddrinfo.c
@@ -1311,7 +1311,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 } }
@@ -1328,26 +1328,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 } }
@@ -1361,23 +1357,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 } }
@@ -1460,7 +1472,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;
@@ -1468,7 +1482,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;
@@ -1649,7 +1663,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;
@@ -1660,7 +1674,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)
 	{
@@ -1679,18 +1693,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;
+		}
 	    }
 	}
 
@@ -1719,7 +1748,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"
 
 
@@ -2405,7 +2434,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;
@@ -2577,11 +2606,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;
diff --git a/nss/tst-rfc3484-2.c b/nss/tst-rfc6724-2.c
similarity index 95%
rename from nss/tst-rfc3484-2.c
rename to nss/tst-rfc6724-2.c
index a5f8f82c04..f6442ca0ed 100644
--- a/nss/tst-rfc3484-2.c
+++ b/nss/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)
     {
diff --git a/nss/tst-rfc3484-3.c b/nss/tst-rfc6724-3.c
similarity index 96%
rename from nss/tst-rfc3484-3.c
rename to nss/tst-rfc6724-3.c
index edf0b7db2e..56223680bd 100644
--- a/nss/tst-rfc3484-3.c
+++ b/nss/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)
diff --git a/nss/tst-rfc3484.c b/nss/tst-rfc6724.c
similarity index 95%
rename from nss/tst-rfc3484.c
rename to nss/tst-rfc6724.c
index 5b4a0c5b82..7063ae4635 100644
--- a/nss/tst-rfc3484.c
+++ b/nss/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)
diff --git a/posix/gai.conf b/posix/gai.conf
index 4616ed005b..de76e2c26f 100644
--- a/posix/gai.conf
+++ b/posix/gai.conf
@@ -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
 
-- 
2.42.0


-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-10-24 11:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-06  9:28 [PATCH] Update getaddrinfo to RFC 6724 (bug 29496) Andreas Schwab
2023-09-04 15:53 ` Florian Weimer
2023-09-04 16:16   ` Andreas Schwab
2023-09-05 12:19     ` Florian Weimer
2023-09-05 12:31       ` Andreas Schwab
2023-09-05 12:44         ` Florian Weimer
2023-10-24 11:27 Andreas Schwab

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).