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) */