--- 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);
}
/*