Maksim Yevmenkin <e...@freebsd.org> wrote in <CAFPOs6pM8qrR72kOtZzO90wYembNrtzw7=ig-nsfudjza7b...@mail.gmail.com>:
em> of course :) we have ipv4 systems in production that make use of em> getaddrinfo(3) api. when a particular dns name is resolved, and, em> multiple A records are returned, the results get sorted according to em> the "default" address selection policy. rfc3484 has a set of rules em> according to which results should be sorted. all of the rules do not em> apply in our case, except one - the rule #9. the idea is that ipv4 em> addresses are "converted" to ipv6 addresses and then longest prefix em> match sorting is applied. in other words, if your system ip address em> happens to share high bits with the ip address from the A record, the em> IP address from the A record will always be preferred. of course, em> longest prefix match is performed without any extra information such em> as netmask and/or cidr. it really is just matching high bits of the em> address. em> em> so, what we found out, is that some systems tend to favor a particular em> ip address (from a bunch of ip addresses returned by name resolution) em> because 4 high bits were the same. basically, round-robin dns was em> completely shot. Is that issue solved by applying the attached patch and setting net.inet6.ip6.longestmatch_mapped=0? I do not think it is a good idea to use the empty rule to solve it because if the system has to support IPv6 as well the empty rule has negative effect. Adding flag to the IPv4 address line in the policy or adding a sysctl sounds a reasonable solution to me. -- Hiroki
Index: sys/netinet6/in6_proto.c =================================================================== --- sys/netinet6/in6_proto.c (revision 238998) +++ sys/netinet6/in6_proto.c (working copy) @@ -587,6 +587,9 @@ SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_STEALTH, stealth, CTLFLAG_RW, &VNET_NAME(ip6stealth), 0, ""); #endif +SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_LONGESTMATCH_MAPPED, + longestmatch_mapped, CTLFLAG_RW, &VNET_NAME(ip6_longestmatch_mapped), 0, + "Use longest match prefix rule for IPv4-mapped address in addrsel."); #ifdef FLOWTABLE VNET_DEFINE(int, ip6_output_flowtable_size) = 2048; Index: sys/netinet6/in6.h =================================================================== --- sys/netinet6/in6.h (revision 238998) +++ sys/netinet6/in6.h (working copy) @@ -618,7 +618,8 @@ * receiving IF. */ #define IPV6CTL_RFC6204W3 50 /* Accept defroute even when forwarding enabled */ -#define IPV6CTL_MAXID 51 +#define IPV6CTL_LONGESTMATCH_MAPPED 51 +#define IPV6CTL_MAXID 52 #endif /* __BSD_VISIBLE */ /* Index: sys/netinet6/in6_src.c =================================================================== --- sys/netinet6/in6_src.c (revision 238998) +++ sys/netinet6/in6_src.c (working copy) @@ -126,6 +126,7 @@ #define V_defaultaddrpolicy VNET(defaultaddrpolicy) VNET_DEFINE(int, ip6_prefer_tempaddr) = 0; +VNET_DEFINE(int, ip6_longestmatch_mapped) = 1; static int selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *, struct ip6_moptions *, struct route_in6 *, struct ifnet **, @@ -452,11 +453,13 @@ * a large number so that it is easy to assign smaller numbers * to more preferred rules. */ + if (!IN6_IS_ADDR_V4MAPPED(&dst) || ip6_longestmatch_mapped) { new_matchlen = in6_matchlen(&ia->ia_addr.sin6_addr, &dst); if (best_matchlen < new_matchlen) REPLACE(14); if (new_matchlen < best_matchlen) NEXT(14); + } /* Rule 15 is reserved. */ Index: sys/netinet6/ip6_var.h =================================================================== --- sys/netinet6/ip6_var.h (revision 238998) +++ sys/netinet6/ip6_var.h (working copy) @@ -357,6 +357,9 @@ * zone when unspecified */ #define V_ip6_use_defzone VNET(ip6_use_defzone) +VNET_DECLARE(int, ip6_longestmatch_mapped); /* Use longest match for addrsel */ +#define V_ip6_longestmatch_mapped VNET(ip6_longestmatch_mapped) + VNET_DECLARE (struct pfil_head, inet6_pfil_hook); /* packet filter hooks */ #define V_inet6_pfil_hook VNET(inet6_pfil_hook) #ifdef IPSTEALTH
pgpyY6nweGltr.pgp
Description: PGP signature