On Fri, 2015-04-10 at 17:27 +0100, Robert Swindells wrote: > Kengo NAKAHARA <k-nakah...@iij.ad.jp> wrote: > >On 2015/04/03 16:14, Takahiro HAYASHI wrote: > >> It seems that IFF_POINTTOPOINT interfaces like tun and gif cannot > >> receive ipv6 packets. > >> This occurs on NetBSD/amd64 -current since Feb 27 2015. > >> > >> For example, establishing gif tunnnel between 2 hosts. > >> > >> [host1] <---> [host2] > >> 192.168.0.1 192.168.0.2 ipv4 address of real interface > >> fd00::1 fd00::2 gif address > >> > >> When I ping6, a host can send ICMPv6 ECHO(128), but the other host > >> returns ICMPv6 DST_UNREACH(1) code UNREACH_ADDR(3) to pinging host. > > > >I think the reason of this issue is below commit: > > > > http://www.nerv.org/netbsd/?q=id:20150226T095446Z.75354d997222ae09acc944ba1c6cf573c3ea724b > > The following patch helps for me. It results in the RTF_LLINFO flag getting > set for the route for the interface. > > The comment looks to be incorrect in any case. > > Robert Swindells > > Index: in6.c > =================================================================== > RCS file: /cvsroot/src/sys/netinet6/in6.c,v > retrieving revision 1.186 > diff -u -r1.186 in6.c > --- in6.c 7 Apr 2015 23:30:36 -0000 1.186 > +++ in6.c 10 Apr 2015 16:10:31 -0000 > @@ -1695,7 +1695,7 @@ > /* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */ > if (newhost) { > /* set the rtrequest function to create llinfo */ > - if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0) > + if ((ifp->if_flags & IFF_LOOPBACK) == 0) > ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; > in6_ifaddlocal(&ia->ia_ifa); > } else { >
We shouldn't really need the LLINFO flag on P2P interfaces. Here is a patch which introduces p2p_rtrequest() which installs a correct and working local route for P2P interfaces, based on an older patch for OpenBSD. I intend to commit this to fix the PR early next week when I can put more testing into it. Commentary welcome as I can't test many P2P interfaces. Roy
Index: sys/net/if.c =================================================================== RCS file: /cvsroot/src/sys/net/if.c,v retrieving revision 1.309 diff -u -r1.309 if.c --- sys/net/if.c 7 Apr 2015 23:30:36 -0000 1.309 +++ sys/net/if.c 12 Apr 2015 15:57:09 -0000 @@ -1482,6 +1482,58 @@ } /* + * Default action when installing a local route on a point-to-point + * interface. + */ +void +p2p_rtrequest(int req, struct rtentry *rt, + __unused const struct rt_addrinfo *info) +{ + struct ifnet *ifp = rt->rt_ifp; + struct ifaddr *ifa, *lo0ifa; + + switch (req) { + case RTM_ADD: + if ((rt->rt_flags & RTF_LOCAL) == 0) + break; + + IFADDR_FOREACH(ifa, ifp) { + if (equal(rt_getkey(rt), ifa->ifa_addr)) + break; + } + if (ifa == NULL) + break; + + /* + * Ensure lo0 has an address of the same family. + */ + IFADDR_FOREACH(lo0ifa, lo0ifp) { + if (lo0ifa->ifa_addr->sa_family == + ifa->ifa_addr->sa_family) + break; + } + if (lo0ifa == NULL) + break; + + rt->rt_ifp = lo0ifp; + rt->rt_flags &= ~RTF_LLINFO; + + /* + * Make sure to set rt->rt_ifa to the interface + * address we are using, otherwise we will have trouble + * with source address selection. + */ + if (ifa != rt->rt_ifa) + rt_replace_ifa(rt, ifa); + break; + case RTM_DELETE: + case RTM_RESOLVE: + default: + break; + } +} + +/* * Mark an interface down and notify protocols of * the transition. * NOTE: must be called at splsoftnet or equivalent. Index: sys/net/if.h =================================================================== RCS file: /cvsroot/src/sys/net/if.h,v retrieving revision 1.187 diff -u -r1.187 if.h --- sys/net/if.h 7 Apr 2015 23:30:36 -0000 1.187 +++ sys/net/if.h 12 Apr 2015 15:57:09 -0000 @@ -899,6 +899,7 @@ struct ifaddr *ifaof_ifpforaddr(const struct sockaddr *, struct ifnet *); void ifafree(struct ifaddr *); void link_rtrequest(int, struct rtentry *, const struct rt_addrinfo *); +void p2p_rtrequest(int, struct rtentry *, const struct rt_addrinfo *); void if_clone_attach(struct if_clone *); void if_clone_detach(struct if_clone *); Index: sys/net/if_gif.c =================================================================== RCS file: /cvsroot/src/sys/net/if_gif.c,v retrieving revision 1.83 diff -u -r1.83 if_gif.c --- sys/net/if_gif.c 5 Jun 2014 23:48:16 -0000 1.83 +++ sys/net/if_gif.c 12 Apr 2015 15:57:09 -0000 @@ -423,12 +423,14 @@ { struct gif_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq*)data; + struct ifaddr *ifa = (struct ifaddr*)data; int error = 0, size; struct sockaddr *dst, *src; switch (cmd) { case SIOCINITIFADDR: ifp->if_flags |= IFF_UP; + ifa->ifa_rtrequest = p2p_rtrequest; break; case SIOCADDMULTI: Index: sys/net/if_gre.c =================================================================== RCS file: /cvsroot/src/sys/net/if_gre.c,v retrieving revision 1.162 diff -u -r1.162 if_gre.c --- sys/net/if_gre.c 3 Apr 2015 20:01:07 -0000 1.162 +++ sys/net/if_gre.c 12 Apr 2015 15:57:09 -0000 @@ -1180,6 +1180,7 @@ gre_ioctl(struct ifnet *ifp, const u_long cmd, void *data) { struct ifreq *ifr; + struct ifaddr *ifa = (struct ifaddr *)data; struct if_laddrreq *lifr = (struct if_laddrreq *)data; struct gre_softc *sc = ifp->if_softc; struct gre_soparm *sp; @@ -1221,6 +1222,7 @@ break; gre_clearconf(sp, false); ifp->if_flags |= IFF_UP; + ifa->ifa_rtrequest = p2p_rtrequest; goto mksocket; case SIOCSIFFLAGS: if ((error = ifioctl_common(ifp, cmd, data)) != 0) Index: sys/net/if_ppp.c =================================================================== RCS file: /cvsroot/src/sys/net/if_ppp.c,v retrieving revision 1.146 diff -u -r1.146 if_ppp.c --- sys/net/if_ppp.c 1 Jul 2014 15:03:58 -0000 1.146 +++ sys/net/if_ppp.c 12 Apr 2015 15:57:09 -0000 @@ -767,6 +767,7 @@ error = EAFNOSUPPORT; break; } + ifa->ifa_rtrequest = p2p_rtrequest; break; case SIOCADDMULTI: Index: sys/net/if_spppsubr.c =================================================================== RCS file: /cvsroot/src/sys/net/if_spppsubr.c,v retrieving revision 1.131 diff -u -r1.131 if_spppsubr.c --- sys/net/if_spppsubr.c 28 Nov 2014 08:29:00 -0000 1.131 +++ sys/net/if_spppsubr.c 12 Apr 2015 15:57:10 -0000 @@ -1017,12 +1017,14 @@ { struct lwp *l = curlwp; /* XXX */ struct ifreq *ifr = (struct ifreq *) data; + struct ifaddr *ifa = (struct ifaddr *) data; struct sppp *sp = (struct sppp *) ifp; int s, error=0, going_up, going_down, newmode; s = splnet(); switch (cmd) { case SIOCINITIFADDR: + ifa->ifa_rtrequest = p2p_rtrequest; break; case SIOCSIFFLAGS: Index: sys/net/if_tun.c =================================================================== RCS file: /cvsroot/src/sys/net/if_tun.c,v retrieving revision 1.120 diff -u -r1.120 if_tun.c --- sys/net/if_tun.c 25 Jul 2014 08:10:40 -0000 1.120 +++ sys/net/if_tun.c 12 Apr 2015 15:57:10 -0000 @@ -435,13 +435,15 @@ { int error = 0, s; struct tun_softc *tp = (struct tun_softc *)(ifp->if_softc); - struct ifreq *ifr = data; + struct ifreq *ifr = (struct ifreq *)data; + struct ifaddr *ifa = (struct ifaddr *)data; s = splnet(); switch (cmd) { case SIOCINITIFADDR: tuninit(tp); + ifa->ifa_rtrequest = p2p_rtrequest; TUNDEBUG("%s: address set\n", ifp->if_xname); break; case SIOCSIFBRDADDR: Index: sys/netinet6/in6.c =================================================================== RCS file: /cvsroot/src/sys/netinet6/in6.c,v retrieving revision 1.186 diff -u -r1.186 in6.c --- sys/netinet6/in6.c 7 Apr 2015 23:30:36 -0000 1.186 +++ sys/netinet6/in6.c 12 Apr 2015 15:57:11 -0000 @@ -1695,7 +1695,9 @@ /* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */ if (newhost) { /* set the rtrequest function to create llinfo */ - if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0) + if (ifp->if_flags & IFF_POINTOPOINT) + ia->ia_ifa.ifa_rtrequest = p2p_rtrequest; + else if ((ifp->if_flags & (IFF_LOOPBACK)) == 0) ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; in6_ifaddlocal(&ia->ia_ifa); } else {