Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Sep 2009 16:43:17 +0000 (UTC)
From:      Qing Li <qingli@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r196864 - in head/sys: net netinet6
Message-ID:  <200909051643.n85GhHkJ058525@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: qingli
Date: Sat Sep  5 16:43:16 2009
New Revision: 196864
URL: http://svn.freebsd.org/changeset/base/196864

Log:
  This patch fixes the following issues:
  - Interface link-local address is not reachable within the
    node that owns the interface, this is due to the mismatch
    in address scope as the result of the installed interface
    address loopback route. Therefore for each interface
    address loopback route, the rt_gateway field (of AF_LINK
    type) will be used to track which interface a given
    address belongs to. This will aid the address source to
    use the proper interface for address scope/zone validation.
  - The loopback address is not reachable. The root cause is
    the same as the above.
  - Empty nd6 entries are created for the IPv6 loopback addresses
    only for validation reason. Doing so will eliminate as much
    of the special case (loopback addresses) handling code
    as possible, however, these empty nd6 entries should not
    be returned to the userland applications such as the
    "ndp" command.
  Since both of the above issues contain common files, these
  files are committed together.
  
  Reviewed by:	bz
  MFC after:	immediately

Modified:
  head/sys/net/if_llatbl.c
  head/sys/netinet6/in6.c
  head/sys/netinet6/in6_src.c
  head/sys/netinet6/ip6_output.c

Modified: head/sys/net/if_llatbl.c
==============================================================================
--- head/sys/net/if_llatbl.c	Sat Sep  5 15:08:58 2009	(r196863)
+++ head/sys/net/if_llatbl.c	Sat Sep  5 16:43:16 2009	(r196864)
@@ -263,6 +263,15 @@ lla_rt_output(struct rt_msghdr *rtm, str
 		    __func__, dl->sdl_index);
 		return EINVAL;
 	}
+	if (ifp->if_flags & IFF_LOOPBACK) {
+		struct ifaddr *ia;
+		ia = ifa_ifwithaddr(dst);
+		if (ia != NULL) {
+			ifp = ia->ifa_ifp;
+			ifa_free(ia);
+		} else 
+			return EINVAL;
+	}
 
 	switch (rtm->rtm_type) {
 	case RTM_ADD:

Modified: head/sys/netinet6/in6.c
==============================================================================
--- head/sys/netinet6/in6.c	Sat Sep  5 15:08:58 2009	(r196863)
+++ head/sys/netinet6/in6.c	Sat Sep  5 16:43:16 2009	(r196864)
@@ -1201,8 +1201,8 @@ in6_purgeaddr(struct ifaddr *ifa)
 		bzero(&null_sdl, sizeof(null_sdl));
 		null_sdl.sdl_len = sizeof(null_sdl);
 		null_sdl.sdl_family = AF_LINK;
-		null_sdl.sdl_type = V_loif->if_type;
-		null_sdl.sdl_index = V_loif->if_index;
+		null_sdl.sdl_type = ia->ia_ifp->if_type;
+		null_sdl.sdl_index = ia->ia_ifp->if_index;
 		bzero(&info, sizeof(info));
 		info.rti_flags = ia->ia_flags | RTF_HOST | RTF_STATIC;
 		info.rti_info[RTAX_DST] = (struct sockaddr *)&ia->ia_addr;
@@ -1782,9 +1782,9 @@ in6_ifinit(struct ifnet *ifp, struct in6
 		if (error == 0 && rt != NULL) {
 			RT_LOCK(rt);
 			((struct sockaddr_dl *)rt->rt_gateway)->sdl_type  =
-				rt->rt_ifp->if_type;
+				ifp->if_type;
 			((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
-				rt->rt_ifp->if_index;
+				ifp->if_index;
 			RT_REMREF(rt);
 			RT_UNLOCK(rt);
 		} else if (error != 0)
@@ -2495,6 +2495,9 @@ in6_lltable_dump(struct lltable *llt, st
 	} ndpc;
 	int i, error;
 
+	if (ifp->if_flags & IFF_LOOPBACK)
+		return 0;
+
 	LLTABLE_LOCK_ASSERT();
 
 	error = 0;

Modified: head/sys/netinet6/in6_src.c
==============================================================================
--- head/sys/netinet6/in6_src.c	Sat Sep  5 15:08:58 2009	(r196863)
+++ head/sys/netinet6/in6_src.c	Sat Sep  5 16:43:16 2009	(r196864)
@@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/sx.h>
 
 #include <net/if.h>
+#include <net/if_dl.h>
 #include <net/route.h>
 #include <net/if_llatbl.h>
 #ifdef RADIX_MPATH
@@ -697,8 +698,25 @@ selectroute(struct sockaddr_in6 *dstsock
 	if (error == EHOSTUNREACH)
 		V_ip6stat.ip6s_noroute++;
 
-	if (retifp != NULL)
+	if (retifp != NULL) {
 		*retifp = ifp;
+
+		/*
+		 * Adjust the "outgoing" interface.  If we're going to loop 
+		 * the packet back to ourselves, the ifp would be the loopback 
+		 * interface. However, we'd rather know the interface associated 
+		 * to the destination address (which should probably be one of 
+		 * our own addresses.)
+		 */
+		if (rt) {
+			if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) &&
+			    (rt->rt_gateway->sa_family == AF_LINK))
+				*retifp = 
+					ifnet_byindex(((struct sockaddr_dl *)
+						       rt->rt_gateway)->sdl_index);
+		}
+	}
+
 	if (retrt != NULL)
 		*retrt = rt;	/* rt may be NULL */
 
@@ -750,16 +768,6 @@ in6_selectif(struct sockaddr_in6 *dstsoc
 		return (flags);
 	}
 
-	/*
-	 * Adjust the "outgoing" interface.  If we're going to loop the packet
-	 * back to ourselves, the ifp would be the loopback interface.
-	 * However, we'd rather know the interface associated to the
-	 * destination address (which should probably be one of our own
-	 * addresses.)
-	 */
-	if (rt && rt->rt_ifa && rt->rt_ifa->ifa_ifp)
-		*retifp = rt->rt_ifa->ifa_ifp;
-
 	if (ro == &sro && rt && rt == sro.ro_rt)
 		RTFREE(rt);
 	return (0);

Modified: head/sys/netinet6/ip6_output.c
==============================================================================
--- head/sys/netinet6/ip6_output.c	Sat Sep  5 15:08:58 2009	(r196863)
+++ head/sys/netinet6/ip6_output.c	Sat Sep  5 16:43:16 2009	(r196864)
@@ -602,15 +602,12 @@ again:
 		rt->rt_use++;
 	}
 
+
 	/*
 	 * The outgoing interface must be in the zone of source and
-	 * destination addresses.  We should use ia_ifp to support the
-	 * case of sending packets to an address of our own.
+	 * destination addresses.  
 	 */
-	if (ia != NULL && ia->ia_ifp)
-		origifp = ia->ia_ifp;
-	else
-		origifp = ifp;
+	origifp = ifp;
 
 	src0 = ip6->ip6_src;
 	if (in6_setscope(&src0, origifp, &zone))
@@ -634,6 +631,12 @@ again:
 		goto badscope;
 	}
 
+	/* We should use ia_ifp to support the case of 
+	 * sending packets to an address of our own.
+	 */
+	if (ia != NULL && ia->ia_ifp)
+		ifp = ia->ia_ifp;
+
 	/* scope check is done. */
 	goto routefound;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200909051643.n85GhHkJ058525>