in6_selectsrc() uses two different rtalloc calls depending on whether or not the destination address is multicast or not, but there is nothing to explain why. I dug a bit and found this commit from itojun@ :
diff -u -r1.6 -r1.7 --- src/sys/netinet6/in6_src.c 2000/06/18 04:49:32 1.6 +++ src/sys/netinet6/in6_src.c 2000/06/18 17:02:59 1.7 @@ -244,7 +244,11 @@ ro->ro_dst.sin6_family = AF_INET6; ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6); ro->ro_dst.sin6_addr = *dst; - if (!IN6_IS_ADDR_MULTICAST(dst)) { + ro->ro_dst.sin6_scope_id = dstsock->sin6_scope_id; + if (IN6_IS_ADDR_MULTICAST(dst)) { + ro->ro_rt = rtalloc1(&((struct route *)ro) + ->ro_dst, 0); + } else { rtalloc((struct route *)ro); } } Below are rtalloc() and rtalloc1() from sys/net/route.c r1.19 commited on 05/21/2000 : > void > rtalloc(ro) > register struct route *ro; > { > if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP)) > return; /* XXX */ > ro->ro_rt = rtalloc1(&ro->ro_dst, 1); > } > > struct rtentry * > rtalloc1(dst, report) > register struct sockaddr *dst; > int report; > { [...] > /* > * IP encapsulation does lots of lookups where we don't need nor want > * the RTM_MISSes that would be generated. It causes RTM_MISS storms > * sent upward breaking user-level routing queries. > */ > miss: if (report && dst->sa_family != PF_KEY) { > bzero((caddr_t)&info, sizeof(info)); > info.rti_info[RTAX_DST] = dst; > rt_missmsg(msgtype, &info, 0, err); > } > } > splx(s); > return (newrt); > } So this if(MULTICAST) has been introduced to prevent RTM_MISS storms when looking up routes to multicast addresses ; multicast and unicast route lookups are the same. Also, rtalloc(foo, RT_RESOLVE, bar) and rtalloc_mpath(foo, NULL, bar) are both equivalent to _rtalloc(foo, NULL, RT_RESOLVE, bar). Let's remove this if(MULTICAST), it's just confusing. ok ? Index: sys/netinet6/in6_src.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6_src.c,v retrieving revision 1.71 diff -u -p -r1.71 in6_src.c --- sys/netinet6/in6_src.c 2 Dec 2015 13:29:26 -0000 1.71 +++ sys/netinet6/in6_src.c 5 Dec 2015 12:03:48 -0000 @@ -240,13 +240,8 @@ in6_selectsrc(struct in6_addr **in6src, sa6->sin6_len = sizeof(struct sockaddr_in6); sa6->sin6_addr = *dst; sa6->sin6_scope_id = dstsock->sin6_scope_id; - if (IN6_IS_ADDR_MULTICAST(dst)) { - ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst), - RT_RESOLVE, ro->ro_tableid); - } else { - ro->ro_rt = rtalloc_mpath(sin6tosa(&ro->ro_dst), - NULL, ro->ro_tableid); - } + ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst), + RT_RESOLVE, ro->ro_tableid); } /*