Hello Aaron, On 24/06/16(Fri) 06:25, Aaron Riekenberg wrote: > I am running an OpenBSD 5.9 box as a firewall/router on a Comcast cable > connection. My box has 2 interfaces: em0 on external network (cable modem) > and em1 on internal network. I have applied all available patches for 5.9. > > For ipv6 I'm running wide-dhcpv6 package to get a non-temporary address on > em0 and prefix delegation (/64) on em1. > > I'm using slaac on em0 to get the default inet6 route from Comcast - I have > "rtsol" line in hostname.em0. > > Finally I'm running rtadvd on em1 to advertise inet6 route and prefix to > internal clients. I'm using default rtadvd config (no config file). > > This all works great, but one issue I'm noticing is netstat -rn output > seems to keep growing, particularly for ff02::1:ff routes on the internal > interface (em1). After 2 days of uptime I have this: > > $ netstat -rn | grep -c 'ff02::1:ff' > 124 > > These routes look like this - notice c flag so these are cloned routes: > > $ netstat -rn | grep 'ff02::1:ff' > ff02::1:ff02:e530%em1 link#3 UHLc > 0 3 - 4 em1 > ff02::1:ff04:8e23%em1 link#3 UHLc > 0 71 - 4 em1 > ff02::1:ff04:ee06%em1 link#3 UHLc > 0 2 - 4 em1 > > Wikipedia says these are solicited node multicast addresses: > https://en.wikipedia.org/wiki/Solicited-node_multicast_address > > Looking at the kernel code - I think these are all cloned child routes of a > route set up by this code in sys/netinet6/in6.c (interesting comment): > > 807 bzero(&info, sizeof(info)); > 808 info.rti_info[RTAX_DST] = sin6tosa(&mltaddr); > 809 info.rti_info[RTAX_GATEWAY] = > sin6tosa(&ia6->ia_addr); > 810 info.rti_info[RTAX_NETMASK] = > sin6tosa(&mltmask); > 811 info.rti_info[RTAX_IFA] = > sin6tosa(&ia6->ia_addr); > 812 /* XXX: we need RTF_CLONING to fake > nd6_rtrequest */ > 813 info.rti_flags = RTF_CLONING; > 814 error = rtrequest(RTM_ADD, &info, > RTP_CONNECTED, NULL, > 815 ifp->if_rdomain); > > mltaddr is set to in6addr_linklocal_allnodes, which > is IN6ADDR_LINKLOCAL_ALLNODES_INIT, which is ff02::1:ff > > > Questions - Are these child routes really leaking? Is there a max number > of cloned child routes or a timeout for these? I cannot find any evidence > of this.
Yes they are leaking. It believe very few people trigger this problem that's why it went unnoticed. This hack is here to prevent the following error: nd6_rtrequest: bad gateway value: em0 That's because the routing table hasn't been designed to handle multicast addresses and KAME people worked around that. Setting the RTF_CLONING flag was the worst thing to do to have a working route entry without triggering this error. I plan to start flagging multicast route entries as such. Here's what I have in my tree. The diff below should prevent your leak, I'd be interested to know if everything still work on your setup with it. Note that it is for -current but it might apply without problem on a 5.9 tree. Index: sys/net/route.h =================================================================== RCS file: /cvs/src/sys/net/route.h,v retrieving revision 1.138 diff -u -p -r1.138 route.h --- sys/net/route.h 14 Jun 2016 09:48:52 -0000 1.138 +++ sys/net/route.h 5 Jul 2016 14:28:22 -0000 @@ -131,7 +131,7 @@ struct rtentry { #define RTF_DONE 0x40 /* message confirmed */ #define RTF_MASK 0x80 /* subnet mask present */ #define RTF_CLONING 0x100 /* generate new routes on use */ -/* 0x200 unused */ +#define RTF_MULTICAST 0x200 /* route associated to a mcast addr. */ #define RTF_LLINFO 0x400 /* generated by ARP or ND */ #define RTF_STATIC 0x800 /* manually added */ #define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */ Index: sys/netinet/if_ether.c =================================================================== RCS file: /cvs/src/sys/netinet/if_ether.c,v retrieving revision 1.216 diff -u -p -r1.216 if_ether.c --- sys/netinet/if_ether.c 28 Jun 2016 17:18:24 -0000 1.216 +++ sys/netinet/if_ether.c 5 Jul 2016 14:34:10 -0000 @@ -139,7 +139,7 @@ arp_rtrequest(struct ifnet *ifp, int req timeout_add_sec(&arptimer_to, 1); } - if (rt->rt_flags & (RTF_GATEWAY|RTF_BROADCAST)) + if (ISSET(rt->rt_flags, RTF_GATEWAY|RTF_BROADCAST|RTF_MULTICAST)) return; switch (req) { Index: sys/netinet6/in6.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6.c,v retrieving revision 1.188 diff -u -p -r1.188 in6.c --- sys/netinet6/in6.c 5 Jul 2016 10:17:14 -0000 1.188 +++ sys/netinet6/in6.c 5 Jul 2016 14:19:36 -0000 @@ -757,8 +757,7 @@ in6_update_ifa(struct ifnet *ifp, struct info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia6->ia_addr); info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask); info.rti_info[RTAX_IFA] = sin6tosa(&ia6->ia_addr); - /* XXX: we need RTF_CLONING to fake nd6_rtrequest */ - info.rti_flags = RTF_CLONING; + info.rti_flags = RTF_MULTICAST; error = rtrequest(RTM_ADD, &info, RTP_CONNECTED, NULL, ifp->if_rdomain); if (error) @@ -814,7 +813,7 @@ in6_update_ifa(struct ifnet *ifp, struct info.rti_info[RTAX_GATEWAY] = sin6tosa(&ia6->ia_addr); info.rti_info[RTAX_NETMASK] = sin6tosa(&mltmask); info.rti_info[RTAX_IFA] = sin6tosa(&ia6->ia_addr); - info.rti_flags = RTF_CLONING; + info.rti_flags = RTF_MULTICAST; error = rtrequest(RTM_ADD, &info, RTP_CONNECTED, NULL, ifp->if_rdomain); if (error) Index: sys/netinet6/nd6.c =================================================================== RCS file: /cvs/src/sys/netinet6/nd6.c,v retrieving revision 1.186 diff -u -p -r1.186 nd6.c --- sys/netinet6/nd6.c 15 Jun 2016 11:49:34 -0000 1.186 +++ sys/netinet6/nd6.c 5 Jul 2016 14:34:55 -0000 @@ -882,7 +882,7 @@ nd6_rtrequest(struct ifnet *ifp, int req dr->installed = 0; } - if ((rt->rt_flags & RTF_GATEWAY) != 0) + if (ISSET(rt->rt_flags, RTF_GATEWAY|RTF_MULTICAST)) return; if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) { Index: sbin/route/show.c =================================================================== RCS file: /cvs/src/sbin/route/show.c,v retrieving revision 1.103 diff -u -p -r1.103 show.c --- sbin/route/show.c 27 Nov 2015 16:26:52 -0000 1.103 +++ sbin/route/show.c 5 Jul 2016 14:18:24 -0000 @@ -78,8 +78,8 @@ static const struct bits bits[] = { { RTF_DYNAMIC, 'D' }, { RTF_MODIFIED, 'M' }, { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ - { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */ { RTF_CLONING, 'C' }, + { RTF_MULTICAST,'m' }, { RTF_LLINFO, 'L' }, { RTF_STATIC, 'S' }, { RTF_PROTO1, '1' }, Index: usr.bin/netstat/show.c =================================================================== RCS file: /cvs/src/usr.bin/netstat/show.c,v retrieving revision 1.49 diff -u -p -r1.49 show.c --- usr.bin/netstat/show.c 11 Sep 2015 20:10:26 -0000 1.49 +++ usr.bin/netstat/show.c 5 Jul 2016 14:20:05 -0000 @@ -78,8 +78,8 @@ static const struct bits bits[] = { { RTF_DYNAMIC, 'D' }, { RTF_MODIFIED, 'M' }, { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ - { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */ { RTF_CLONING, 'C' }, + { RTF_MULTICAST,'m' }, { RTF_LLINFO, 'L' }, { RTF_STATIC, 'S' }, { RTF_PROTO1, '1' }, Index: usr.sbin/route6d/route6d.c =================================================================== RCS file: /cvs/src/usr.sbin/route6d/route6d.c,v retrieving revision 1.86 diff -u -p -r1.86 route6d.c --- usr.sbin/route6d/route6d.c 25 Jan 2016 05:15:43 -0000 1.86 +++ usr.sbin/route6d/route6d.c 5 Jul 2016 14:24:03 -0000 @@ -2319,45 +2319,16 @@ do { \ RTFLAG("D", RTF_DYNAMIC); RTFLAG("M", RTF_MODIFIED); RTFLAG("d", RTF_DONE); -#ifdef RTF_MASK - RTFLAG("m", RTF_MASK); -#endif + RTFLAG("m", RTF_MULTICAST); RTFLAG("C", RTF_CLONING); -#ifdef RTF_CLONED RTFLAG("c", RTF_CLONED); -#endif -#ifdef RTF_PRCLONING - RTFLAG("c", RTF_PRCLONING); -#endif -#ifdef RTF_WASCLONED - RTFLAG("W", RTF_WASCLONED); -#endif RTFLAG("L", RTF_LLINFO); RTFLAG("S", RTF_STATIC); RTFLAG("B", RTF_BLACKHOLE); -#ifdef RTF_PROTO3 RTFLAG("3", RTF_PROTO3); -#endif RTFLAG("2", RTF_PROTO2); RTFLAG("1", RTF_PROTO1); -#ifdef RTF_BROADCAST RTFLAG("b", RTF_BROADCAST); -#endif -#ifdef RTF_DEFAULT - RTFLAG("d", RTF_DEFAULT); -#endif -#ifdef RTF_ISAROUTER - RTFLAG("r", RTF_ISAROUTER); -#endif -#ifdef RTF_TUNNEL - RTFLAG("T", RTF_TUNNEL); -#endif -#ifdef RTF_AUTH - RTFLAG("A", RTF_AUTH); -#endif -#ifdef RTF_CRYPT - RTFLAG("E", RTF_CRYPT); -#endif #undef RTFLAG return buf; } Index: share/man/man4/route.4 =================================================================== RCS file: /cvs/src/share/man/man4/route.4,v retrieving revision 1.40 diff -u -p -r1.40 route.4 --- share/man/man4/route.4 23 Mar 2016 12:57:53 -0000 1.40 +++ share/man/man4/route.4 5 Jul 2016 14:22:27 -0000 @@ -358,6 +358,7 @@ Flags include the values: #define RTF_DONE 0x40 /* message confirmed */ #define RTF_MASK 0x80 /* subnet mask present */ #define RTF_CLONING 0x100 /* generate new routes on use */ +#define RTF_MULTICAST 0x200 /* route associated to a mcast addr. */ #define RTF_LLINFO 0x400 /* generated by ARP or NDP */ #define RTF_STATIC 0x800 /* manually added */ #define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */