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;
