Bug 24282 - Remove Rule 9 sorting from getaddrinfo
Summary: Remove Rule 9 sorting from getaddrinfo
Status: NEW
Alias: None
Product: glibc
Classification: Unclassified
Component: network (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-02-28 12:35 UTC by Florian Weimer
Modified: 2019-03-04 08:29 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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 192.0.2.1 wants to connect to a host with these addresses, on the same subnet 192.0.2.0/24 and uses getaddrinfo to look up these three addresses:

  192.0.2.129
  192.0.2.192
  192.0.2.193

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

With a source address of 192.0.2.1, 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 192.0.2.1 to 192.0.2.130.  At this point, the shared prefix lengths are:

  192.0.2.129: 30
  192.0.2.192: 25
  192.0.2.193: 25

As a result, getaddrinfo will always sort the address 192.0.2.129 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.