Bug 24282

Summary: Remove Rule 9 sorting from getaddrinfo
Product: glibc Reporter: Florian Weimer <fweimer>
Component: networkAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: carlos
Priority: P2 Flags: fweimer: security-
Version: unspecified   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description Florian Weimer 2019-02-28 12:35:53 UTC
RFC 3484 Rule 9 sorting breaks user expectations in a pretty drastic way.  For example if we start out with this scenario:

Host wants to connect to a host with these addresses, on the same subnet and uses getaddrinfo to look up these three addresses:

The DNS server used round-robin mode, so the first address returns varies between all three.

With a source address of, the length of the shared prefix is 24 for all destination addresses, so Rule 9 has no preference, and the getaddrinfo result reflects the order returned by the DNS server (so round-robin in this example).

Now we renumber the host from to  At this point, the shared prefix lengths are: 30 25 25

As a result, getaddrinfo will always sort the address first, overriding the round-robin behavior requested by the DNS server.

This behavior is not useful, and RFC 3484 Rule 9 sorting should be removed from the getaddrinfo implementation.
Comment 1 Andreas Schwab 2019-02-28 14:08:44 UTC
I think CommonPrefixLen should never return more than the network prefix length for local destinations.
Comment 2 Carlos O'Donell 2019-02-28 14:10:34 UTC
What do other C libraries or OS libraries do in this case?
Comment 3 Andreas Schwab 2019-02-28 14:44:23 UTC
FreeBSD closely follows the RFC (see comp_dst in <https://svnweb.freebsd.org/base/head/lib/libc/net/getaddrinfo.c?view=markup>).
Comment 4 Florian Weimer 2019-03-04 08:29:53 UTC
(In reply to Andreas Schwab from comment #1)
> I think CommonPrefixLen should never return more than the network prefix
> length for local destinations.

We already ignore shared prefix length for non-local addresses:

	  /* Outside of subnets, as defined by the network masks,
	     common address prefixes for IPv4 addresses make no sense.
	     So, define a non-zero value only if source and
	     destination address are on the same subnet.  */

So with your proposal, Rule 9 is either gone completely, or we simply prefer directly connected addresses (which I still think will be very confusing to system administrators and generally do not have the expected performance benefits in case of tunnels etc.).

(In reply to Carlos O'Donell from comment #2)
> What do other C libraries or OS libraries do in this case?

I don't have test systems with multiple Ethernet interfaces.  (We don't look at the interface type in getaddrinfo, but other systems might.)

RFC 6724 obsoletes RFC 3484 and has this:

   Rule 8: Use longest matching prefix.
   If CommonPrefixLen(SA, D) > CommonPrefixLen(SB, D), then prefer SA.
   Similarly, if CommonPrefixLen(SB, D) > CommonPrefixLen(SA, D), then
   prefer SB.

   Rule 8 MAY be superseded if the implementation has other means of
   choosing among source addresses.  For example, if the implementation
   somehow knows which source address will result in the "best"
   communications performance.

Based on the bug reports and customer cases I've seen over the years, I think Rule 9 is still a mistake.  It is very confusing to system administrators, prevents you from renumbering systems without introducing drastic changes in network behavior, and there is no evidence that as a general rule, destinations with a longer common prefix shared with the source are actually closer on the network.