svn commit: r286195 - head/sys/netinet6

Andrey V. Elsukov ae at FreeBSD.org
Sun Aug 2 12:40:58 UTC 2015


Author: ae
Date: Sun Aug  2 12:40:56 2015
New Revision: 286195
URL: https://svnweb.freebsd.org/changeset/base/286195

Log:
  Properly handle IPV6_NEXTHOP socket option in selectroute().
  
   o remove disabled code;
   o if nexthop address is link-local, use embedded scope zone id to
     determine outgoing interface;
   o properly fill ro_dst before doing route lookup;
   o remove LLE lookup, instead check rt_flags for RTF_GATEWAY bit.
  
  Sponsored by:	Yandex LLC

Modified:
  head/sys/netinet6/in6_src.c

Modified: head/sys/netinet6/in6_src.c
==============================================================================
--- head/sys/netinet6/in6_src.c	Sun Aug  2 11:58:24 2015	(r286194)
+++ head/sys/netinet6/in6_src.c	Sun Aug  2 12:40:56 2015	(r286195)
@@ -616,77 +616,38 @@ selectroute(struct sockaddr_in6 *dstsock
 	 */
 	if (opts && opts->ip6po_nexthop) {
 		struct route_in6 *ron;
-		struct llentry *la;
-	    
-		sin6_next = satosin6(opts->ip6po_nexthop);
-		
-		/* at this moment, we only support AF_INET6 next hops */
-		if (sin6_next->sin6_family != AF_INET6) {
-			error = EAFNOSUPPORT; /* or should we proceed? */
-			goto done;
-		}
-
-		/*
-		 * If the next hop is an IPv6 address, then the node identified
-		 * by that address must be a neighbor of the sending host.
-		 */
-		ron = &opts->ip6po_nextroute;
-		/*
-		 * XXX what do we do here?
-		 * PLZ to be fixing
-		 */
 
-
-		if (ron->ro_rt == NULL) {
-			in6_rtalloc(ron, fibnum); /* multi path case? */
-			if (ron->ro_rt == NULL) {
-				error = EHOSTUNREACH;
+		sin6_next = satosin6(opts->ip6po_nexthop);
+		if (IN6_IS_ADDR_LINKLOCAL(&sin6_next->sin6_addr)) {
+			/*
+			 * Next hop is LLA, thus it should be neighbor.
+			 * Determine outgoing interface by zone index.
+			 */
+			zoneid = ntohs(in6_getscope(&sin6_next->sin6_addr));
+			if (zoneid > 0) {
+				ifp = in6_getlinkifnet(zoneid);
 				goto done;
 			}
 		}
-
-		rt = ron->ro_rt;
-		ifp = rt->rt_ifp;
-		IF_AFDATA_RLOCK(ifp);
-		la = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)sin6_next);
-		IF_AFDATA_RUNLOCK(ifp);
-		if (la != NULL) 
-			LLE_RUNLOCK(la);
-		else {
-			error = EHOSTUNREACH;
-			goto done;
-		}
-#if 0
-		if ((ron->ro_rt &&
-		     (ron->ro_rt->rt_flags & (RTF_UP | RTF_LLINFO)) !=
-		     (RTF_UP | RTF_LLINFO)) ||
-		    !IN6_ARE_ADDR_EQUAL(&satosin6(&ron->ro_dst)->sin6_addr,
-		    &sin6_next->sin6_addr)) {
-			if (ron->ro_rt) {
-				RTFREE(ron->ro_rt);
-				ron->ro_rt = NULL;
-			}
-			*satosin6(&ron->ro_dst) = *sin6_next;
-		}
+		ron = &opts->ip6po_nextroute;
+		/* Use a cached route if it exists and is valid. */
+		if (ron->ro_rt != NULL && (
+		    (ron->ro_rt->rt_flags & RTF_UP) == 0 ||
+		    ron->ro_dst.sin6_family != AF_INET6 ||
+		    !IN6_ARE_ADDR_EQUAL(&ron->ro_dst.sin6_addr,
+			&sin6_next->sin6_addr)))
+			RO_RTFREE(ron);
 		if (ron->ro_rt == NULL) {
+			ron->ro_dst = *sin6_next;
 			in6_rtalloc(ron, fibnum); /* multi path case? */
-			if (ron->ro_rt == NULL ||
-			    !(ron->ro_rt->rt_flags & RTF_LLINFO)) {
-				if (ron->ro_rt) {
-					RTFREE(ron->ro_rt);
-					ron->ro_rt = NULL;
-				}
-				error = EHOSTUNREACH;
-				goto done;
-			}
 		}
-#endif
-
 		/*
-		 * When cloning is required, try to allocate a route to the
-		 * destination so that the caller can store path MTU
-		 * information.
+		 * The node identified by that address must be a
+		 * neighbor of the sending host.
 		 */
+		if (ron->ro_rt == NULL ||
+		    (ron->ro_rt->rt_flags & RTF_GATEWAY) != 0)
+			error = EHOSTUNREACH;
 		goto done;
 	}
 


More information about the svn-src-head mailing list