tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: point2point network interfaces cannot receive ipv6 packets



On Fri, 2015-04-10 at 17:27 +0100, Robert Swindells wrote:
> Kengo NAKAHARA <k-nakahara%iij.ad.jp@localhost> 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 {


Home | Main Index | Thread Index | Old Index