6521326 6391685 limits the usability of neighbour discovery in non-global zones
authorja97890
Wed, 28 Mar 2007 07:55:32 -0700
changeset 3909 9f4024db0edf
parent 3908 211a66d0821f
child 3910 00586900e34c
6521326 6391685 limits the usability of neighbour discovery in non-global zones
usr/src/uts/common/inet/ip/ip_ndp.c
--- a/usr/src/uts/common/inet/ip/ip_ndp.c	Wed Mar 28 05:47:04 2007 -0700
+++ b/usr/src/uts/common/inet/ip/ip_ndp.c	Wed Mar 28 07:55:32 2007 -0700
@@ -2289,6 +2289,7 @@
 	ip6i_t		*ip6i;
 	ipif_t		*src_ipif = NULL;
 	uint8_t		*hw_addr;
+	zoneid_t	zoneid = GLOBAL_ZONEID;
 
 	/*
 	 * If we have a unspecified source(sender) address, select a
@@ -2298,6 +2299,12 @@
 	 * the whole group and the h/w address initialized from ill will
 	 * be wrong if the source address comes from a different ill.
 	 *
+	 * If the sender is specified then we use this address in order
+	 * to lookup the zoneid before calling ip_output_v6(). This is to
+	 * enable unicast ND_NEIGHBOR_ADVERT packets to be routed correctly
+	 * by IP (we cannot guarantee that the global zone has an interface
+	 * route to the destination).
+	 *
 	 * Note that the NA never comes here with the unspecified source
 	 * address. The following asserts that whenever the source
 	 * address is specified, the haddr also should be specified.
@@ -2315,7 +2322,7 @@
 		 * source address had better be a valid neighbor.
 		 */
 		src_ipif = ipif_select_source_v6(ill, target, RESTRICT_TO_ILL,
-		    IPV6_PREFER_SRC_DEFAULT, GLOBAL_ZONEID);
+		    IPV6_PREFER_SRC_DEFAULT, ALL_ZONES);
 		if (src_ipif == NULL) {
 			char buf[INET6_ADDRSTRLEN];
 
@@ -2326,6 +2333,16 @@
 		}
 		sender = &src_ipif->ipif_v6src_addr;
 		hwaddr_ill = src_ipif->ipif_ill;
+	} else if (!(IN6_IS_ADDR_UNSPECIFIED(sender))) {
+		zoneid = ipif_lookup_addr_zoneid_v6(sender, ill, ill->ill_ipst);
+		/*
+		 * It's possible for ipif_lookup_addr_zoneid_v6() to return
+		 * ALL_ZONES if it cannot find a matching ipif for the address
+		 * we are trying to use. In this case we err on the side of
+		 * trying to send the packet by defaulting to the GLOBAL_ZONEID.
+		 */
+		if (zoneid == ALL_ZONES)
+			zoneid = GLOBAL_ZONEID;
 	}
 
 	/*
@@ -2424,12 +2441,9 @@
 
 	if (src_ipif != NULL)
 		ipif_refrele(src_ipif);
-	if (canput(ill->ill_wq)) {
-		put(ill->ill_wq, mp);
-		return (B_FALSE);
-	}
-	freemsg(mp);
-	return (B_TRUE);
+
+	ip_output_v6((void *)(uintptr_t)zoneid, mp, ill->ill_wq, IP_WPUT);
+	return (B_FALSE);
 }
 
 /*