PSARC 2006/073 PF_ROUTE: Include interface name with RTM_NEWADDR/RTM_DELADDR
authorsommerfe
Thu, 22 Jun 2006 12:52:27 -0700
changeset 2263 fd48046384d0
parent 2262 819edd3019b3
child 2264 b2b9267d002d
PSARC 2006/073 PF_ROUTE: Include interface name with RTM_NEWADDR/RTM_DELADDR PSARC 2006/084 SO_ALLZONES 4963315 Should make IKE work for non-global zones 4984263 in.iked removes server entities when unnumbered interfaces go away 5024997 system daemons need a way to receive packets from all zones 6218993 PF_ROUTE: RTM_NEWADDR/RTM_DELADDR should include interface name via RTA_IFP 6422023 sctp doesn't need shadow copies of conn_t socket option bits 6426542 Comment about ipp_use_min_mtu got lost and wandered into conn_t 6430869 in.iked should ignore loopback addresses, not loopback interfaces 6438186 SCTP handling of getsockopt( .. SO_MAC_EXEMPT) is oddly inconsistent with TCP, UDP
usr/src/cmd/mdb/common/modules/sctp/sctp.c
usr/src/cmd/ptools/pfiles/pfiles.c
usr/src/cmd/truss/print.c
usr/src/uts/common/inet/ip/icmp.c
usr/src/uts/common/inet/ip/icmp_opt_data.c
usr/src/uts/common/inet/ip/ip.c
usr/src/uts/common/inet/ip/ip_multi.c
usr/src/uts/common/inet/ip/ip_opt_data.c
usr/src/uts/common/inet/ip/ip_rts.c
usr/src/uts/common/inet/ip/ipclassifier.c
usr/src/uts/common/inet/ipclassifier.h
usr/src/uts/common/inet/sctp/sctp.c
usr/src/uts/common/inet/sctp/sctp_addr.c
usr/src/uts/common/inet/sctp/sctp_hash.c
usr/src/uts/common/inet/sctp/sctp_impl.h
usr/src/uts/common/inet/sctp/sctp_opt_data.c
usr/src/uts/common/inet/tcp/tcp.c
usr/src/uts/common/inet/tcp/tcp_opt_data.c
usr/src/uts/common/inet/udp/udp.c
usr/src/uts/common/inet/udp/udp_opt_data.c
usr/src/uts/common/sys/socket.h
--- a/usr/src/cmd/mdb/common/modules/sctp/sctp.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/cmd/mdb/common/modules/sctp/sctp.c	Thu Jun 22 12:52:27 2006 -0700
@@ -540,13 +540,8 @@
 	mdb_printf("\tunderstands_asconf\t%d\n",
 	    sctp->sctp_understands_asconf);
 	mdb_printf("\tdebug\t\t\t%d\n", sctp->sctp_debug);
-	mdb_printf("\tdontroute\t\t%d\n", sctp->sctp_dontroute);
-	mdb_printf("\tbroadcast\t\t%d\n", sctp->sctp_broadcast);
-
-	mdb_printf("\tuseloopback\t\t%d\n", sctp->sctp_useloopback);
 	mdb_printf("\tcchunk_pend\t\t%d\n", sctp->sctp_cchunk_pend);
 	mdb_printf("\tdgram_errind\t\t%d\n", sctp->sctp_dgram_errind);
-	mdb_printf("\treuseaddr\t\t%d\n", sctp->sctp_reuseaddr);
 
 	mdb_printf("\tlinger\t\t\t%d\n", sctp->sctp_linger);
 	if (sctp->sctp_lingering)
@@ -572,8 +567,8 @@
 
 	mdb_printf("\tprsctp_aware\t\t%d\n", sctp->sctp_prsctp_aware);
 	mdb_printf("\tlinklocal\t\t%d\n", sctp->sctp_linklocal);
-	mdb_printf("\tmac_exempt\t\t%d\n", sctp->sctp_mac_exempt);
 	mdb_printf("\trexmitting\t\t%d\n", sctp->sctp_rexmitting);
+	mdb_printf("\tzero_win_probe\t\t%d\n", sctp->sctp_zero_win_probe);
 
 	mdb_printf("\trecvsndrcvinfo\t\t%d\n", sctp->sctp_recvsndrcvinfo);
 	mdb_printf("\trecvassocevnt\t\t%d\n", sctp->sctp_recvassocevnt);
--- a/usr/src/cmd/ptools/pfiles/pfiles.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/cmd/ptools/pfiles/pfiles.c	Thu Jun 22 12:52:27 2006 -0700
@@ -544,11 +544,12 @@
 	    { SO_DONTROUTE,	"SO_DONTROUTE,"	},
 	    { SO_BROADCAST,	"SO_BROADCAST,"	},
 	    { SO_OOBINLINE,	"SO_OOBINLINE,"	},
-	    { SO_DGRAM_ERRIND,	"SO_DGRAM_ERRIND,"}
+	    { SO_DGRAM_ERRIND,	"SO_DGRAM_ERRIND,"},
+	    { SO_ALLZONES,	"SO_ALLZONES,"	},
 	};
 	struct linger l;
 
-	buf[0] = ',';
+	buf[0] = '!';		/* sentinel value, never printed */
 	buf[1] = '\0';
 
 	for (i = 0; i < sizeof (boolopts) / sizeof (boolopts[0]); i++) {
@@ -588,7 +589,7 @@
 		}
 	}
 
-	buf[strlen(buf) - 1] = '\0';
+	buf[strlen(buf) - 1] = '\0'; /* overwrites sentinel if no options */
 	if (buf[1] != '\0')
 		(void) printf("\t%s\n", buf+1);
 }
--- a/usr/src/cmd/truss/print.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/cmd/truss/print.c	Thu Jun 22 12:52:27 2006 -0700
@@ -1758,6 +1758,7 @@
 		case SO_ERROR:		return ("SO_ERROR");
 		case SO_TYPE:		return ("SO_TYPE");
 		case SO_PROTOTYPE:	return ("SO_PROTOTYPE");
+		case SO_ALLZONES:	return ("SO_ALLZONES");
 
 		default:		(void) snprintf(pri->code_buf, CBSIZE,
 						    "0x%lx", val);
--- a/usr/src/uts/common/inet/ip/icmp.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/ip/icmp.c	Thu Jun 22 12:52:27 2006 -0700
@@ -1567,12 +1567,13 @@
 			*i1 = icmp->icmp_mac_exempt;
 			break;
 		/*
-		 * Following three not meaningful for icmp
+		 * Following four not meaningful for icmp
 		 * Action is same as "default" to which we fallthrough
 		 * so we keep them in comments.
 		 * case SO_LINGER:
 		 * case SO_KEEPALIVE:
 		 * case SO_OOBINLINE:
+		 * case SO_ALLZONES:
 		 */
 		default:
 			return (-1);
@@ -2024,6 +2025,13 @@
 			if (!checkonly)
 				icmp->icmp_dgram_errind = onoff;
 			break;
+		case SO_ALLZONES:
+			/*
+			 * "soft" error (negative)
+			 * option not handled at this level
+			 * Note: Do not modify *outlenp
+			 */
+			return (-EINVAL);
 		case SO_TIMESTAMP:
 			if (!checkonly) {
 				icmp->icmp_timestamp = onoff;
--- a/usr/src/uts/common/inet/ip/icmp_opt_data.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/ip/icmp_opt_data.c	Thu Jun 22 12:52:27 2006 -0700
@@ -88,7 +88,10 @@
 { SO_TIMESTAMP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0
 	},
 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int),
-    0 },
+	0 },
+
+{ SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT, sizeof (int),
+	0 },
 
 { IP_OPTIONS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP,
 	(OP_PASSNEXT|OP_VARLEN|OP_NODEFAULT),
--- a/usr/src/uts/common/inet/ip/ip.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ip.c	Thu Jun 22 12:52:27 2006 -0700
@@ -4245,7 +4245,7 @@
 	src_ire = NULL;
 	ipif = NULL;
 
-	zoneid = connp->conn_zoneid;
+	zoneid = IPCL_ZONEID(connp);
 
 	if (src_addr) {
 		src_ire = ire_route_lookup(src_addr, 0, 0, 0,
@@ -4431,7 +4431,7 @@
 		policy_mp = mp->b_cont;
 	}
 
-	zoneid = connp->conn_zoneid;
+	zoneid = IPCL_ZONEID(connp);
 
 	if (CLASSD(dst_addr)) {
 		/* Pick up an IRE_BROADCAST */
@@ -6353,7 +6353,8 @@
 		 */
 		while ((connp != NULL) &&
 		    (!IPCL_UDP_MATCH(connp, dstport, dst,
-		    srcport, src) || connp->conn_zoneid != zoneid)) {
+		    srcport, src) ||
+		    (connp->conn_zoneid != zoneid && !connp->conn_allzones))) {
 			connp = connp->conn_next;
 		}
 
@@ -6499,7 +6500,7 @@
 	if (!broadcast && !CLASSD(dst)) {
 		while (connp != NULL) {
 			if (IPCL_UDP_MATCH_V6(connp, dstport, ipv6_all_zeros,
-			    srcport, v6src) && connp->conn_zoneid == zoneid &&
+			    srcport, v6src) && IPCL_ZONE_MATCH(connp, zoneid) &&
 			    conn_wantpacket(connp, ill, ipha, flags, zoneid) &&
 			    !connp->conn_ipv6_v6only)
 				break;
@@ -9666,16 +9667,17 @@
 	ipif_t *ipif = NULL;
 	int error;
 	ill_t *ill;
+	int zoneid;
 
 	ip2dbg(("ip_opt_set_ipif: ipaddr %X\n", addr));
 
 	if (addr != INADDR_ANY || checkonly) {
 		ASSERT(connp != NULL);
+		zoneid = IPCL_ZONEID(connp);
 		if (option == IP_NEXTHOP) {
-			ipif =
-			    ipif_lookup_onlink_addr(addr, connp->conn_zoneid);
-		} else {
-			ipif = ipif_lookup_addr(addr, NULL, connp->conn_zoneid,
+			ipif = ipif_lookup_onlink_addr(addr, zoneid);
+		} else {
+			ipif = ipif_lookup_addr(addr, NULL, zoneid,
 			    CONNP_TO_WQ(connp), first_mp, ip_restart_optmgmt,
 			    &error);
 		}
@@ -10057,6 +10059,17 @@
 				mutex_exit(&connp->conn_lock);
 			}
 			break;	/* goto sizeof (int) option return */
+		case SO_ALLZONES:
+			if (!checkonly) {
+				mutex_enter(&connp->conn_lock);
+				if (IPCL_IS_BOUND(connp)) {
+					mutex_exit(&connp->conn_lock);
+					return (EINVAL);
+				}
+				connp->conn_allzones = *i1 != 0 ? 1 : 0;
+				mutex_exit(&connp->conn_lock);
+			}
+			break;	/* goto sizeof (int) option return */
 		case SO_ANON_MLP:
 			if (!checkonly) {
 				mutex_enter(&connp->conn_lock);
@@ -26384,7 +26397,7 @@
 	}
 
 	if (!CLASSD(dst)) {
-		if (connp->conn_zoneid == zoneid)
+		if (IPCL_ZONE_MATCH(connp, zoneid))
 			return (B_TRUE);
 		/*
 		 * The conn is in a different zone; we need to check that this
--- a/usr/src/uts/common/inet/ip/ip_multi.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ip_multi.c	Thu Jun 22 12:52:27 2006 -0700
@@ -1858,13 +1858,15 @@
 {
 	ipif_t *ipif;
 	int err = 0;
-	zoneid_t zoneid = connp->conn_zoneid;
+	zoneid_t zoneid;
 
 	if (!CLASSD(group) || CLASSD(src)) {
 		return (EINVAL);
 	}
 	*ipifpp = NULL;
 
+	zoneid = IPCL_ZONEID(connp);
+
 	ASSERT(!(ifaddr != INADDR_ANY && ifindexp != NULL && *ifindexp != 0));
 	if (ifaddr != INADDR_ANY) {
 		ipif = ipif_lookup_addr(ifaddr, NULL, zoneid,
--- a/usr/src/uts/common/inet/ip/ip_opt_data.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ip_opt_data.c	Thu Jun 22 12:52:27 2006 -0700
@@ -66,6 +66,10 @@
 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0
 	},
 
+{ SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT, sizeof (int),
+	0 },
+
+
 { IP_OPTIONS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP,
 	(OP_PASSNEXT|OP_VARLEN|OP_NODEFAULT), 40, -1 /* not initialized */ },
 { T_IP_OPTIONS,	IPPROTO_IP, OA_RW, OA_RW, OP_NP,
--- a/usr/src/uts/common/inet/ip/ip_rts.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ip_rts.c	Thu Jun 22 12:52:27 2006 -0700
@@ -1805,7 +1805,7 @@
 		    (cmd == RTM_DELETE && pass == 2)) {
 			ncmd = ((cmd == RTM_ADD) ? RTM_NEWADDR : RTM_DELADDR);
 
-			rtm_addrs = (RTA_IFA | RTA_NETMASK | RTA_BRD);
+			rtm_addrs = (RTA_IFA | RTA_NETMASK | RTA_BRD | RTA_IFP);
 			mp = rts_alloc_msg(ncmd, rtm_addrs, af, 0);
 			if (mp == NULL)
 				continue;
@@ -1813,7 +1813,7 @@
 			case AF_INET:
 				rts_fill_msg(ncmd, rtm_addrs, 0,
 				    ipif->ipif_net_mask, 0, ipif->ipif_lcl_addr,
-				    ipif->ipif_pp_dst_addr, 0, NULL, mp,
+				    ipif->ipif_pp_dst_addr, 0, ipif, mp,
 				    0, NULL);
 				break;
 			case AF_INET6:
@@ -1821,7 +1821,7 @@
 				    &ipv6_all_zeros, &ipif->ipif_v6net_mask,
 				    &ipv6_all_zeros, &ipif->ipif_v6lcl_addr,
 				    &ipif->ipif_v6pp_dst_addr, &ipv6_all_zeros,
-				    NULL, mp, 0, NULL);
+				    ipif, mp, 0, NULL);
 				break;
 			}
 			ifam = (ifa_msghdr_t *)mp->b_rptr;
--- a/usr/src/uts/common/inet/ip/ipclassifier.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/ip/ipclassifier.c	Thu Jun 22 12:52:27 2006 -0700
@@ -1362,8 +1362,7 @@
 		for (connp = bind_connfp->connf_head; connp != NULL;
 		    connp = connp->conn_next) {
 			if (IPCL_BIND_MATCH(connp, protocol, ipha->ipha_dst,
-			    lport) &&
-			    (connp->conn_zoneid == zoneid ||
+			    lport) && (IPCL_ZONE_MATCH(connp, zoneid) ||
 			    (unlabeled && connp->conn_mac_exempt)))
 				break;
 		}
@@ -1432,7 +1431,7 @@
 		    connp = connp->conn_next) {
 			if (IPCL_UDP_MATCH(connp, lport, ipha->ipha_dst,
 			    fport, ipha->ipha_src) &&
-			    (connp->conn_zoneid == zoneid ||
+			    (IPCL_ZONE_MATCH(connp, zoneid) ||
 			    (unlabeled && connp->conn_mac_exempt)))
 				break;
 		}
@@ -1546,7 +1545,7 @@
 		    connp = connp->conn_next) {
 			if (IPCL_BIND_MATCH_V6(connp, protocol,
 			    ip6h->ip6_dst, lport) &&
-			    (connp->conn_zoneid == zoneid ||
+			    (IPCL_ZONE_MATCH(connp, zoneid) ||
 			    (unlabeled && connp->conn_mac_exempt)))
 				break;
 		}
@@ -1617,7 +1616,7 @@
 		    connp = connp->conn_next) {
 			if (IPCL_UDP_MATCH_V6(connp, lport, ip6h->ip6_dst,
 			    fport, ip6h->ip6_src) &&
-			    (connp->conn_zoneid == zoneid ||
+			    (IPCL_ZONE_MATCH(connp, zoneid) ||
 			    (unlabeled && connp->conn_mac_exempt)))
 				break;
 		}
@@ -1755,7 +1754,7 @@
 			}
 		}
 
-		if (connp->conn_zoneid == zoneid ||
+		if (IPCL_ZONE_MATCH(connp, zoneid) ||
 		    (unlabeled && connp->conn_mac_exempt))
 			break;
 	}
@@ -1784,7 +1783,7 @@
 	    connp = connp->conn_next) {
 		/* We don't allow v4 fallback for v6 raw socket. */
 		if ((af == (connp->conn_af_isv6 ? IPV4_VERSION :
-		    IPV6_VERSION)) || (connp->conn_zoneid != zoneid)) {
+		    IPV6_VERSION)) || !IPCL_ZONE_MATCH(connp, zoneid)) {
 			continue;
 		}
 		if (af == IPV4_VERSION) {
@@ -2163,7 +2162,7 @@
 	    connp = connp->conn_next) {
 		tcp = connp->conn_tcp;
 		if (IPCL_BIND_MATCH(connp, IPPROTO_TCP, laddr, lport) &&
-		    connp->conn_zoneid == zoneid &&
+		    IPCL_ZONE_MATCH(connp, zoneid) &&
 		    (tcp->tcp_listener == NULL)) {
 			CONN_INC_REF(connp);
 			mutex_exit(&bind_connfp->connf_lock);
@@ -2201,7 +2200,7 @@
 	    connp = connp->conn_next) {
 		tcp = connp->conn_tcp;
 		if (IPCL_BIND_MATCH_V6(connp, IPPROTO_TCP, *laddr, lport) &&
-		    connp->conn_zoneid == zoneid &&
+		    IPCL_ZONE_MATCH(connp, zoneid) &&
 		    (tcp->tcp_bound_if == 0 ||
 		    tcp->tcp_bound_if == ifindex) &&
 		    tcp->tcp_listener == NULL) {
--- a/usr/src/uts/common/inet/ipclassifier.h	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/ipclassifier.h	Thu Jun 22 12:52:27 2006 -0700
@@ -165,18 +165,13 @@
 
 		conn_pathmtu_valid : 1,		/* The cached mtu is valid. */
 		conn_ipv6_dontfrag : 1,		/* IPV6_DONTFRAG */
-		/*
-		 * This option can take on values in [-1, 1] so we store it
-		 * +1.  Manifest constants IPV6_USE_MIN_MTU_* describe these
-		 * values.
-		 */
 		conn_fully_bound : 1,		/* Fully bound connection */
 		conn_recvif : 1,		/* IP_RECVIF option */
 
 		conn_recvslla : 1,		/* IP_RECVSLLA option */
 		conn_mdt_ok : 1,		/* MDT is permitted */
 		conn_nexthop_set : 1,
-		pad_to_bit_31 : 1;
+		conn_allzones : 1;		/* SO_ALLZONES */
 
 	tcp_t		*conn_tcp;		/* Pointer to the tcp struct */
 	struct udp_s	*conn_udp;		/* Pointer to the udp struct */
@@ -332,12 +327,28 @@
 	}								\
 }
 
+/*
+ * For use with subsystems within ip which use ALL_ZONES as a wildcard
+ */
+#define	IPCL_ZONEID(connp)						\
+	((connp)->conn_allzones ? ALL_ZONES : (connp)->conn_zoneid)
+
+/*
+ * For matching between a conn_t and a zoneid.
+ */
+#define	IPCL_ZONE_MATCH(connp, zoneid) 					\
+	(((connp)->conn_allzones) ||					\
+	    ((zoneid) == ALL_ZONES) ||					\
+	    (connp)->conn_zoneid == (zoneid))
+
+
 #define	_IPCL_V4_MATCH(v6addr, v4addr)	\
 	(V4_PART_OF_V6((v6addr)) == (v4addr) && IN6_IS_ADDR_V4MAPPED(&(v6addr)))
 
 #define	_IPCL_V4_MATCH_ANY(addr)	\
 	(IN6_IS_ADDR_V4MAPPED_ANY(&(addr)) || IN6_IS_ADDR_UNSPECIFIED(&(addr)))
 
+
 /*
  * IPCL_PROTO_MATCH() only matches conns with the specified zoneid, while
  * IPCL_PROTO_MATCH_V6() can match other conns in the multicast case, see
@@ -347,12 +358,12 @@
     fanout_flags, zoneid)						\
 	((((connp)->conn_src == INADDR_ANY) ||				\
 	(((connp)->conn_src == ((ipha)->ipha_dst)) &&			\
-	(((connp)->conn_rem == INADDR_ANY) ||				\
+	    (((connp)->conn_rem == INADDR_ANY) ||			\
 	((connp)->conn_rem == ((ipha)->ipha_src))))) &&			\
-	((zoneid) == ALL_ZONES || (connp)->conn_zoneid == (zoneid)) &&	\
-	(conn_wantpacket((connp), (ill), (ipha),			\
-	(fanout_flags), (zoneid)) || ((protocol) == IPPROTO_PIM) ||	\
-	((protocol) == IPPROTO_RSVP)))
+	IPCL_ZONE_MATCH(connp, zoneid) &&				\
+	(conn_wantpacket((connp), (ill), (ipha), (fanout_flags), 	\
+	    (zoneid)) || ((protocol) == IPPROTO_PIM) ||			\
+	    ((protocol) == IPPROTO_RSVP)))
 
 #define	IPCL_PROTO_MATCH_V6(connp, protocol, ip6h, ill,			   \
     fanout_flags, zoneid)						   \
--- a/usr/src/uts/common/inet/sctp/sctp.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/sctp/sctp.c	Thu Jun 22 12:52:27 2006 -0700
@@ -239,7 +239,10 @@
 		if (getpflags(NET_MAC_AWARE, credp) != 0)
 			connp->conn_mac_exempt = B_TRUE;
 	}
-	connp->conn_zoneid = psctp->sctp_zoneid;
+
+	connp->conn_allzones = pconnp->conn_allzones;
+	connp->conn_zoneid = pconnp->conn_zoneid;
+
 	sctp->sctp_mss = psctp->sctp_mss;
 	sctp->sctp_detached = B_TRUE;
 	/*
@@ -853,6 +856,7 @@
 {
 	int	err;
 	int	cnt;
+	conn_t 	*connp, *pconnp;
 
 	ASSERT((sctp->sctp_family == AF_INET &&
 	    sctp->sctp_ipversion == IPV4_VERSION) ||
@@ -954,16 +958,22 @@
 
 		/* xxx should be a better way to copy these flags xxx */
 		sctp->sctp_debug = psctp->sctp_debug;
-		sctp->sctp_dontroute = psctp->sctp_dontroute;
-		sctp->sctp_useloopback = psctp->sctp_useloopback;
-		sctp->sctp_broadcast = psctp->sctp_broadcast;
-		sctp->sctp_reuseaddr = psctp->sctp_reuseaddr;
 		sctp->sctp_bound_to_all = psctp->sctp_bound_to_all;
 		sctp->sctp_cansleep = psctp->sctp_cansleep;
 		sctp->sctp_send_adaption = psctp->sctp_send_adaption;
 		sctp->sctp_ndelay = psctp->sctp_ndelay;
 		sctp->sctp_events = psctp->sctp_events;
 		sctp->sctp_ipv6_recvancillary = psctp->sctp_ipv6_recvancillary;
+
+		/* Copy IP-layer options */
+		connp = sctp->sctp_connp;
+		pconnp = psctp->sctp_connp;
+
+		connp->conn_broadcast = pconnp->conn_broadcast;
+		connp->conn_loopback = pconnp->conn_loopback;
+		connp->conn_dontroute = pconnp->conn_dontroute;
+		connp->conn_reuseaddr = pconnp->conn_reuseaddr;
+
 	} else {
 		/*
 		 * Initialize the header template
@@ -1369,6 +1379,7 @@
 		 */
 		sctp->sctp_lport = psctp->sctp_lport;
 		sctp->sctp_state = SCTPS_BOUND;
+		sctp->sctp_allzones = psctp->sctp_allzones;
 		sctp->sctp_zoneid = psctp->sctp_zoneid;
 		WAKE_SCTP(psctp);
 	} else {
--- a/usr/src/uts/common/inet/sctp/sctp_addr.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/sctp/sctp_addr.c	Thu Jun 22 12:52:27 2006 -0700
@@ -50,7 +50,7 @@
 
 static void		sctp_ipif_inactive(sctp_ipif_t *);
 static sctp_ipif_t	*sctp_lookup_ipif_addr(in6_addr_t *, boolean_t,
-			    zoneid_t zoneid, uint_t);
+			    sctp_t *, uint_t);
 static int		sctp_get_all_ipifs(sctp_t *, int);
 int			sctp_valid_addr_list(sctp_t *, const void *, uint32_t,
 			    uchar_t *, size_t);
@@ -94,6 +94,9 @@
 	((!(ipif)->sctp_ipif_isv6 && !((supp_af) & PARM_SUPP_V4)) ||	\
 	((ipif)->sctp_ipif_isv6 && !((supp_af) & PARM_SUPP_V6)))
 
+#define	SCTP_IPIF_ZONE_MATCH(sctp, ipif) 				\
+	IPCL_ZONE_MATCH((sctp)->sctp_connp, (ipif)->sctp_ipif_zoneid)
+
 #define	SCTP_ILL_HASH_FN(index)		((index) % SCTP_ILL_HASH)
 #define	SCTP_IPIF_HASH_FN(seqid)	((seqid) % SCTP_IPIF_HASH)
 #define	SCTP_ILL_TO_PHYINDEX(ill)	((ill)->ill_phyint->phyint_ifindex)
@@ -167,14 +170,14 @@
  * Called with no locks held.
  */
 static sctp_ipif_t *
-sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, zoneid_t zoneid,
+sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, sctp_t *sctp,
     uint_t ifindex)
 {
 	int		i;
 	int		j;
 	sctp_ipif_t	*sctp_ipif;
 
-	ASSERT(zoneid != ALL_ZONES);
+	ASSERT(sctp->sctp_zoneid != ALL_ZONES);
 	rw_enter(&sctp_g_ipifs_lock, RW_READER);
 	for (i = 0; i < SCTP_IPIF_HASH; i++) {
 		if (sctp_g_ipifs[i].ipif_count == 0)
@@ -182,8 +185,7 @@
 		sctp_ipif = list_head(&sctp_g_ipifs[i].sctp_ipif_list);
 		for (j = 0; j < sctp_g_ipifs[i].ipif_count; j++) {
 			rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
-			if ((zoneid == sctp_ipif->sctp_ipif_zoneid ||
-			    sctp_ipif->sctp_ipif_zoneid == ALL_ZONES) &&
+			if (SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) &&
 			    SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) &&
 			    (ifindex == 0 || ifindex ==
 			    sctp_ipif->sctp_ipif_ill->sctp_ill_index) &&
@@ -226,8 +228,7 @@
 			rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER);
 			if (SCTP_IPIF_DISCARD(sctp_ipif->sctp_ipif_flags) ||
 			    !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) ||
-			    (sctp_ipif->sctp_ipif_zoneid != ALL_ZONES &&
-			    sctp_ipif->sctp_ipif_zoneid != sctp->sctp_zoneid) ||
+			    !SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) ||
 			    (sctp->sctp_ipversion == IPV4_VERSION &&
 			    sctp_ipif->sctp_ipif_isv6) ||
 			    (sctp->sctp_connp->conn_ipv6_v6only &&
@@ -359,8 +360,8 @@
 			goto free_ret;
 		}
 		if (lookup_saddr) {
-			ipif = sctp_lookup_ipif_addr(&addr, B_TRUE,
-			    sctp->sctp_zoneid, ifindex);
+			ipif = sctp_lookup_ipif_addr(&addr, B_TRUE, sctp,
+			    ifindex);
 			if (ipif == NULL) {
 				/* Address not in the list */
 				err = EINVAL;
@@ -974,8 +975,8 @@
 			ifindex = sin6->sin6_scope_id;
 			break;
 		}
-		sctp_ipif = sctp_lookup_ipif_addr(&addr, B_FALSE,
-		    sctp->sctp_zoneid, ifindex);
+		sctp_ipif = sctp_lookup_ipif_addr(&addr, B_FALSE, sctp,
+		    ifindex);
 		ASSERT(sctp_ipif != NULL);
 		sctp_ipif_hash_remove(sctp, sctp_ipif);
 	}
@@ -1000,8 +1001,7 @@
 	sctp_saddr_ipif_t	*saddr_ipifs;
 	sctp_ipif_t		*sctp_ipif;
 
-	sctp_ipif = sctp_lookup_ipif_addr(addr, B_FALSE, sctp->sctp_zoneid,
-	    ifindex);
+	sctp_ipif = sctp_lookup_ipif_addr(addr, B_FALSE, sctp, ifindex);
 	if (sctp_ipif == NULL)
 		return (NULL);
 
@@ -1015,8 +1015,7 @@
 {
 	sctp_ipif_t		*sctp_ipif;
 
-	sctp_ipif = sctp_lookup_ipif_addr(addr, B_TRUE, sctp->sctp_zoneid,
-	    ifindex);
+	sctp_ipif = sctp_lookup_ipif_addr(addr, B_TRUE, sctp, ifindex);
 	if (sctp_ipif == NULL)
 		return (EINVAL);
 
@@ -1447,7 +1446,7 @@
 			    !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) ||
 			    SCTP_IS_IPIF_LOOPBACK(sctp_ipif) ||
 			    SCTP_IS_IPIF_LINKLOCAL(sctp_ipif) ||
-			    sctp_ipif->sctp_ipif_zoneid != sctp->sctp_zoneid ||
+			    !SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) ||
 			    (sctp->sctp_ipversion == IPV4_VERSION &&
 			    sctp_ipif->sctp_ipif_isv6) ||
 			    (sctp->sctp_connp->conn_ipv6_v6only &&
--- a/usr/src/uts/common/inet/sctp/sctp_hash.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/sctp/sctp_hash.c	Thu Jun 22 12:52:27 2006 -0700
@@ -286,8 +286,8 @@
 	mutex_enter(&tf->tf_lock);
 
 	for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_conn_hash_next) {
-		if (ports != sctp->sctp_ports || (zoneid != ALL_ZONES &&
-		    zoneid != sctp->sctp_zoneid)) {
+		if (ports != sctp->sctp_ports ||
+		    !IPCL_ZONE_MATCH(sctp->sctp_connp, zoneid)) {
 			continue;
 		}
 
@@ -337,8 +337,8 @@
 	mutex_enter(&tf->tf_lock);
 
 	for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_listen_hash_next) {
-		if (lport != sctp->sctp_lport || (zoneid != ALL_ZONES &&
-		    zoneid != sctp->sctp_zoneid)) {
+		if (lport != sctp->sctp_lport ||
+		    !IPCL_ZONE_MATCH(sctp->sctp_connp, zoneid)) {
 			continue;
 		}
 
--- a/usr/src/uts/common/inet/sctp/sctp_impl.h	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/sctp/sctp_impl.h	Thu Jun 22 12:52:27 2006 -0700
@@ -633,7 +633,10 @@
 
 	conn_t		*sctp_connp;		/* conn_t stuff */
 #define	sctp_zoneid	sctp_connp->conn_zoneid
+#define	sctp_allzones	sctp_connp->conn_allzones
+#define	sctp_mac_exempt	sctp_connp->conn_mac_exempt
 #define	sctp_credp	sctp_connp->conn_cred
+#define	sctp_reuseaddr	sctp_connp->conn_reuseaddr
 
 	/* Peer address tracking */
 	sctp_faddr_t	*sctp_lastfaddr;	/* last faddr in list */
@@ -743,13 +746,8 @@
 
 		sctp_understands_asconf : 1, /* Peer handles ASCONF chunks */
 		sctp_debug : 1,		/* SO_DEBUG "socket" option. */
-		sctp_dontroute : 1,	/* SO_DONTROUTE "socket" option. */
-		sctp_broadcast : 1,	/* SO_BROADCAST "socket" option. */
-
-		sctp_useloopback : 1,	/* SO_USELOOPBACK "socket" option. */
 		sctp_cchunk_pend : 1,	/* Control chunk in flight. */
 		sctp_dgram_errind : 1,	/* SO_DGRAM_ERRIND option */
-		sctp_reuseaddr	: 1,	/* SO_REUSEADDR "socket" option. */
 
 		sctp_linger : 1,	/* SO_LINGER turned on */
 		sctp_lingering : 1,	/* Lingering in close */
@@ -773,11 +771,10 @@
 
 		sctp_prsctp_aware : 1,	/* is peer PR-SCTP aware? */
 		sctp_linklocal : 1,	/* is linklocal assoc. */
-		sctp_mac_exempt : 1,	/* SO_MAC_EXEMPT */
 		sctp_rexmitting : 1,	/* SCTP is retransmitting */
 		sctp_zero_win_probe : 1,	/* doing zero win probe */
 
-		sctp_dummy : 3;
+		sctp_dummy : 8;
 	} sctp_bits;
 	struct {
 		uint32_t
@@ -795,12 +792,8 @@
 #define	sctp_priv_stream sctp_bits.sctp_priv_stream
 #define	sctp_understands_asconf sctp_bits.sctp_understands_asconf
 #define	sctp_debug sctp_bits.sctp_debug
-#define	sctp_dontroute sctp_bits.sctp_dontroute
-#define	sctp_broadcast sctp_bits.sctp_broadcast
-#define	sctp_useloopback sctp_bits.sctp_useloopback
 #define	sctp_cchunk_pend sctp_bits.sctp_cchunk_pend
 #define	sctp_dgram_errind sctp_bits.sctp_dgram_errind
-#define	sctp_reuseaddr sctp_bits.sctp_reuseaddr
 #define	sctp_linger sctp_bits.sctp_linger
 #define	sctp_lingering sctp_bits.sctp_lingering
 #define	sctp_loopback sctp_bits.sctp_loopback
@@ -819,7 +812,6 @@
 #define	sctp_chk_fast_rexmit sctp_bits.sctp_chk_fast_rexmit
 #define	sctp_prsctp_aware sctp_bits.sctp_prsctp_aware
 #define	sctp_linklocal sctp_bits.sctp_linklocal
-#define	sctp_mac_exempt sctp_bits.sctp_mac_exempt
 #define	sctp_rexmitting sctp_bits.sctp_rexmitting
 #define	sctp_zero_win_probe sctp_bits.sctp_zero_win_probe
 
--- a/usr/src/uts/common/inet/sctp/sctp_opt_data.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/sctp/sctp_opt_data.c	Thu Jun 22 12:52:27 2006 -0700
@@ -701,16 +701,16 @@
 			*i1 = sctp->sctp_debug ? SO_DEBUG : 0;
 			break;
 		case SO_DONTROUTE:
-			*i1 = sctp->sctp_dontroute ? SO_DONTROUTE : 0;
+			*i1 = connp->conn_dontroute ? SO_DONTROUTE : 0;
 			break;
 		case SO_USELOOPBACK:
-			*i1 = sctp->sctp_useloopback ? SO_USELOOPBACK : 0;
+			*i1 = connp->conn_loopback ? SO_USELOOPBACK : 0;
 			break;
 		case SO_BROADCAST:
-			*i1 = sctp->sctp_broadcast ? SO_BROADCAST : 0;
+			*i1 = connp->conn_broadcast ? SO_BROADCAST : 0;
 			break;
 		case SO_REUSEADDR:
-			*i1 = sctp->sctp_reuseaddr ? SO_REUSEADDR : 0;
+			*i1 = connp->conn_reuseaddr ? SO_REUSEADDR : 0;
 			break;
 		case SO_DGRAM_ERRIND:
 			*i1 = sctp->sctp_dgram_errind ? SO_DGRAM_ERRIND : 0;
@@ -721,8 +721,11 @@
 		case SO_RCVBUF:
 			*i1 = sctp->sctp_rwnd;
 			break;
+		case SO_ALLZONES:
+			*i1 = connp->conn_allzones;
+			break;
 		case SO_MAC_EXEMPT:
-			*i1 = sctp->sctp_mac_exempt ? SO_MAC_EXEMPT : 0;
+			*i1 = connp->conn_mac_exempt;
 			break;
 		default:
 			retval = EINVAL;
@@ -1160,22 +1163,17 @@
 		case SO_DONTROUTE:
 			/*
 			 * SO_DONTROUTE, SO_USELOOPBACK and SO_BROADCAST are
-			 * only of interest to IP.  We track them here only so
-			 * that we can report their current value.
+			 * only of interest to IP.
 			 */
-			sctp->sctp_dontroute = onoff;
 			connp->conn_dontroute = onoff;
 			break;
 		case SO_USELOOPBACK:
-			sctp->sctp_useloopback = onoff;
 			connp->conn_loopback = onoff;
 			break;
 		case SO_BROADCAST:
-			sctp->sctp_broadcast = onoff;
 			connp->conn_broadcast = onoff;
 			break;
 		case SO_REUSEADDR:
-			sctp->sctp_reuseaddr = onoff;
 			connp->conn_reuseaddr = onoff;
 			break;
 		case SO_DGRAM_ERRIND:
@@ -1220,14 +1218,28 @@
 			 * and sctp_opt_get ?
 			 */
 			break;
-		case SO_MAC_EXEMPT:
-			if (secpolicy_net_mac_aware(sctp->sctp_credp) != 0 ||
-			    sctp->sctp_state >= SCTPS_BOUND) {
+		case SO_ALLZONES:
+			if (secpolicy_net(sctp->sctp_credp, OP_CONFIG,
+			    B_TRUE)) {
 				retval = EACCES;
-			} else {
-				sctp->sctp_mac_exempt = onoff;
-				connp->conn_mac_exempt = onoff;
+				break;
+			}
+			if (sctp->sctp_state >= SCTPS_BOUND) {
+				retval = EINVAL;
+				break;
 			}
+			sctp->sctp_allzones = onoff;
+			break;
+		case SO_MAC_EXEMPT:
+			if (secpolicy_net_mac_aware(sctp->sctp_credp) != 0) {
+				retval = EACCES;
+				break;
+			}
+			if (sctp->sctp_state >= SCTPS_BOUND) {
+				retval = EINVAL;
+				break;
+			}
+			connp->conn_mac_exempt = onoff;
 			break;
 		default:
 			retval = EINVAL;
--- a/usr/src/uts/common/inet/tcp/tcp.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/tcp/tcp.c	Thu Jun 22 12:52:27 2006 -0700
@@ -3511,7 +3511,7 @@
 			 * privilege as being in all zones, as there's
 			 * otherwise no way to identify the right receiver.
 			 */
-			if (lconnp->conn_zoneid != zoneid &&
+			if (!IPCL_ZONE_MATCH(ltcp->tcp_connp, zoneid) &&
 			    !lconnp->conn_mac_exempt &&
 			    !connp->conn_mac_exempt)
 				continue;
@@ -5341,7 +5341,7 @@
  * reference is dropped by the squeue framework.
  *
  * 3) The ref on listener placed in 1 above is dropped in tcp_accept_finish
- * 
+ *
  * The reference must be released by the same entity that added the reference
  * In the above scheme, the eager is the entity that adds and releases the
  * references. Note that tcp_accept_finish executes in the squeue of the eager
@@ -5373,10 +5373,10 @@
  * based on the ref placed on eager before sending T_conn_ind.
  * The only entity that can negate this refhold is a listener close
  * which is mutually exclusive with an active acceptor stream.
- * 
+ *
  * Eager's reference on the listener
  * ===================================
- * 
+ *
  * If the accept happens (even on a closed eager) the eager drops its
  * reference on the listener at the start of tcp_accept_finish. If the
  * eager is killed due to an incoming RST before the T_conn_ind is sent up,
@@ -9587,6 +9587,9 @@
 			*i1 = tcp->tcp_snd_zcopy_on ?
 			    SO_SND_COPYAVOID : 0;
 			break;
+		case SO_ALLZONES:
+			*i1 = connp->conn_allzones ? 1 : 0;
+			break;
 		case SO_ANON_MLP:
 			*i1 = connp->conn_anon_mlp;
 			break;
@@ -10072,6 +10075,9 @@
 				tcp->tcp_snd_zcopy_aware = 1;
 			}
 			break;
+		case SO_ALLZONES:
+			/* Handled at the IP level */
+			return (-EINVAL);
 		case SO_ANON_MLP:
 			if (!checkonly) {
 				mutex_enter(&connp->conn_lock);
@@ -22613,7 +22619,7 @@
 		mutex_enter(&tbf->tf_lock);
 		for (tcp = tbf->tf_tcp; tcp != NULL;
 		    tcp = tcp->tcp_bind_hash) {
-			if (zoneid == tcp->tcp_connp->conn_zoneid &&
+			if (IPCL_ZONE_MATCH(tcp->tcp_connp, zoneid) &&
 			    net_port == tcp->tcp_lport) {
 				/*
 				 * A port is already bound.  Search again
--- a/usr/src/uts/common/inet/tcp/tcp_opt_data.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/tcp/tcp_opt_data.c	Thu Jun 22 12:52:27 2006 -0700
@@ -75,9 +75,11 @@
 	},
 { SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int),
-    0 },
+	0 },
 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int),
-    0 },
+	0 },
+{ SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT, sizeof (int),
+	0 },
 { TCP_NODELAY,	IPPROTO_TCP, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0
 	},
 { TCP_MAXSEG,	IPPROTO_TCP, OA_R, OA_R, OP_NP, OP_PASSNEXT, sizeof (uint_t),
--- a/usr/src/uts/common/inet/udp/udp.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/udp/udp.c	Thu Jun 22 12:52:27 2006 -0700
@@ -3104,13 +3104,16 @@
 			break;	/* goto sizeof (int) option return */
 		case SO_TIMESTAMP:
 			*i1 = udp->udp_timestamp;
-			break;
+			break;	/* goto sizeof (int) option return */
 		case SO_ANON_MLP:
 			*i1 = udp->udp_anon_mlp;
 			break;	/* goto sizeof (int) option return */
 		case SO_MAC_EXEMPT:
 			*i1 = udp->udp_mac_exempt;
 			break;	/* goto sizeof (int) option return */
+		case SO_ALLZONES:
+			*i1 = connp->conn_allzones;
+			break;	/* goto sizeof (int) option return */
 		default:
 			return (-1);
 		}
@@ -3477,6 +3480,13 @@
 			if (!checkonly)
 				udp->udp_recvucred = onoff;
 			break;
+		case SO_ALLZONES:
+			/*
+			 * "soft" error (negative)
+			 * option not handled at this level
+			 * Do not modify *outlenp.
+			 */
+			return (-EINVAL);
 		case SO_TIMESTAMP:
 			if (!checkonly)
 				udp->udp_timestamp = onoff;
--- a/usr/src/uts/common/inet/udp/udp_opt_data.c	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/inet/udp/udp_opt_data.c	Thu Jun 22 12:52:27 2006 -0700
@@ -71,6 +71,8 @@
 	0 },
 { SO_RECVUCRED, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0
 	},
+{ SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT, sizeof (int),
+	0 },
 { SO_TIMESTAMP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int), 0
 	},
 { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int),
--- a/usr/src/uts/common/sys/socket.h	Thu Jun 22 11:29:01 2006 -0700
+++ b/usr/src/uts/common/sys/socket.h	Thu Jun 22 12:52:27 2006 -0700
@@ -153,6 +153,8 @@
 #define	SO_TIMESTAMP	0x1013		/* socket-level timestamp option */
 #define	SCM_TIMESTAMP	SO_TIMESTAMP	/* socket control message timestamp */
 
+#define	SO_ALLZONES	0x1014		/* bind in all zones */
+
 #ifdef	_KERNEL
 #define	SO_SRCADDR	0x2001		/* Internal: AF_UNIX source address */
 #define	SO_FILEP	0x2002		/* Internal: AF_UNIX file pointer */