6401076 TX: mac-exempt UDP fails if local addr is shared IPv4 and a router added a CIPSO option
6627834 tsol_check_label fails to account for space released by label removal
6643901 TX mac-exempt connections with NET_MAC_AWARE flag fail
6667486 zoneid != (-1) assertion on TX system while forwarding IPv6 packet
6672916 Packets may be forwarded out non global zone interfaces
diff --git a/usr/src/uts/common/inet/ip/icmp.c b/usr/src/uts/common/inet/ip/icmp.c
index 658ba12..553a975 100644
--- a/usr/src/uts/common/inet/ip/icmp.c
+++ b/usr/src/uts/common/inet/ip/icmp.c
@@ -1558,7 +1558,7 @@
 	 * exempt mode.  This allows read-down to unlabeled hosts.
 	 */
 	if (getpflags(NET_MAC_AWARE, credp) != 0)
-		icmp->icmp_mac_exempt = B_TRUE;
+		connp->conn_mac_exempt = B_TRUE;
 
 	connp->conn_ulp_labeled = is_system_labeled();
 
@@ -1713,7 +1713,7 @@
 			*i1 = icmp->icmp_timestamp;
 			break;
 		case SO_MAC_EXEMPT:
-			*i1 = icmp->icmp_mac_exempt;
+			*i1 = connp->conn_mac_exempt;
 			break;
 		case SO_DOMAIN:
 			*i1 = icmp->icmp_family;
@@ -2227,12 +2227,12 @@
 			}
 			break;
 		case SO_MAC_EXEMPT:
-			if (secpolicy_net_mac_aware(cr) != 0 ||
-			    icmp->icmp_state != TS_UNBND)
-				return (EACCES);
-			if (!checkonly)
-				icmp->icmp_mac_exempt = onoff;
-			break;
+			/*
+			 * "soft" error (negative)
+			 * option not handled at this level
+			 * Note: Do not modify *outlenp
+			 */
+			return (-EINVAL);
 		/*
 		 * Following three not meaningful for icmp
 		 * Action is same as "default" so we keep them
@@ -4344,7 +4344,7 @@
 	conn_t	*connp = icmp->icmp_connp;
 
 	err = tsol_compute_label(DB_CREDDEF(mp, connp->conn_cred), dst,
-	    opt_storage, icmp->icmp_mac_exempt,
+	    opt_storage, connp->conn_mac_exempt,
 	    is->is_netstack->netstack_ip);
 	if (err == 0) {
 		err = tsol_update_options(&icmp->icmp_ip_snd_options,
@@ -4666,7 +4666,7 @@
 	conn_t	*connp = icmp->icmp_connp;
 
 	err = tsol_compute_label_v6(DB_CREDDEF(mp, connp->conn_cred), dst,
-	    opt_storage, icmp->icmp_mac_exempt,
+	    opt_storage, connp->conn_mac_exempt,
 	    is->is_netstack->netstack_ip);
 	if (err == 0) {
 		err = tsol_update_sticky(&icmp->icmp_sticky_ipp,
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c
index 69f409e..6c2681f 100644
--- a/usr/src/uts/common/inet/ip/ip.c
+++ b/usr/src/uts/common/inet/ip/ip.c
@@ -7090,6 +7090,7 @@
 	zoneid_t	last_zoneid;
 	boolean_t	reuseaddr;
 	boolean_t	shared_addr;
+	boolean_t	unlabeled;
 	ip_stack_t	*ipst;
 
 	ASSERT(recv_ill != NULL);
@@ -7112,6 +7113,11 @@
 	dst = ipha->ipha_dst;
 	src = ipha->ipha_src;
 
+	unlabeled = B_FALSE;
+	if (is_system_labeled())
+		/* Cred cannot be null on IPv4 */
+		unlabeled = (crgetlabel(DB_CRED(mp))->tsl_flags &
+		    TSLF_UNLABELED) != 0;
 	shared_addr = (zoneid == ALL_ZONES);
 	if (shared_addr) {
 		/*
@@ -7119,8 +7125,20 @@
 		 * only applies to the shared stack.
 		 */
 		zoneid = tsol_mlp_findzone(IPPROTO_UDP, dstport);
+		/*
+		 * If no shared MLP is found, tsol_mlp_findzone returns
+		 * ALL_ZONES.  In that case, we assume it's SLP, and
+		 * search for the zone based on the packet label.
+		 *
+		 * If there is such a zone, we prefer to find a
+		 * connection in it.  Otherwise, we look for a
+		 * MAC-exempt connection in any zone whose label
+		 * dominates the default label on the packet.
+		 */
 		if (zoneid == ALL_ZONES)
 			zoneid = tsol_packet_to_zoneid(mp);
+		else
+			unlabeled = B_FALSE;
 	}
 
 	connfp = &ipst->ips_ipcl_udp_fanout[IPCL_UDP_HASH(dstport, ipst)];
@@ -7135,7 +7153,14 @@
 		 */
 		while ((connp != NULL) &&
 		    (!IPCL_UDP_MATCH(connp, dstport, dst, srcport, src) ||
-		    !IPCL_ZONE_MATCH(connp, zoneid))) {
+		    (!IPCL_ZONE_MATCH(connp, zoneid) &&
+		    !(unlabeled && connp->conn_mac_exempt)))) {
+			/*
+			 * We keep searching since the conn did not match,
+			 * or its zone did not match and it is not either
+			 * an allzones conn or a mac exempt conn (if the
+			 * sender is unlabeled.)
+			 */
 			connp = connp->conn_next;
 		}
 
@@ -13862,6 +13887,17 @@
 
 	ipha = (ipha_t *)mp->b_rptr;
 
+	if (ire != NULL &&
+	    ire->ire_zoneid != GLOBAL_ZONEID &&
+	    ire->ire_zoneid != ALL_ZONES) {
+		/*
+		 * Should only use IREs that are visible to the global
+		 * zone for forwarding.
+		 */
+		ire_refrele(ire);
+		ire = ire_cache_lookup(dst, GLOBAL_ZONEID, NULL, ipst);
+	}
+
 	/*
 	 * Martian Address Filtering [RFC 1812, Section 5.3.7]
 	 * The loopback address check for both src and dst has already
@@ -13881,7 +13917,6 @@
 		goto drop;
 	}
 
-
 	/* No ire cache of nexthop. So first create one  */
 	if (ire == NULL) {
 
@@ -15226,6 +15261,18 @@
 			    MBLK_GETLABEL(mp), ipst);
 		}
 
+		if (ire != NULL && ire->ire_stq != NULL &&
+		    ire->ire_zoneid != GLOBAL_ZONEID &&
+		    ire->ire_zoneid != ALL_ZONES) {
+			/*
+			 * Should only use IREs that are visible from the
+			 * global zone for forwarding.
+			 */
+			ire_refrele(ire);
+			ire = ire_cache_lookup(dst, GLOBAL_ZONEID,
+			    MBLK_GETLABEL(mp), ipst);
+		}
+
 		if (ire == NULL) {
 			/*
 			 * No IRE for this destination, so it can't be for us.
@@ -20116,8 +20163,6 @@
 	mblk_t		*copy_mp = NULL;
 	int		err;
 	zoneid_t	zoneid;
-	int	adjust;
-	uint16_t iplen;
 	boolean_t	need_decref = B_FALSE;
 	boolean_t	ignore_dontroute = B_FALSE;
 	boolean_t	ignore_nexthop = B_FALSE;
@@ -20199,7 +20244,7 @@
 	if (is_system_labeled() &&
 	    (ipha->ipha_version_and_hdr_length & 0xf0) == (IPV4_VERSION << 4) &&
 	    !connp->conn_ulp_labeled) {
-		err = tsol_check_label(BEST_CRED(mp, connp), &mp, &adjust,
+		err = tsol_check_label(BEST_CRED(mp, connp), &mp,
 		    connp->conn_mac_exempt, ipst);
 		ipha = (ipha_t *)mp->b_rptr;
 		if (err != 0) {
@@ -20209,8 +20254,6 @@
 			ip2dbg(("ip_wput: label check failed (%d)\n", err));
 			goto discard_pkt;
 		}
-		iplen = ntohs(ipha->ipha_length) + adjust;
-		ipha->ipha_length = htons(iplen);
 	}
 
 	ASSERT(infop != NULL);
@@ -20736,7 +20779,7 @@
 		    (*mp->b_rptr & 0xf0) == (IPV4_VERSION << 4) &&
 		    !connp->conn_ulp_labeled) {
 			err = tsol_check_label(BEST_CRED(mp, connp), &mp,
-			    &adjust, connp->conn_mac_exempt, ipst);
+			    connp->conn_mac_exempt, ipst);
 			ipha = (ipha_t *)mp->b_rptr;
 			if (first_mp != NULL)
 				first_mp->b_cont = mp;
@@ -20749,8 +20792,6 @@
 				    err));
 				goto discard_pkt;
 			}
-			iplen = ntohs(ipha->ipha_length) + adjust;
-			ipha->ipha_length = htons(iplen);
 		}
 
 		ipha = (ipha_t *)mp->b_rptr;
diff --git a/usr/src/uts/common/inet/ip/ip6.c b/usr/src/uts/common/inet/ip/ip6.c
index 0bd6e64..622b33d 100644
--- a/usr/src/uts/common/inet/ip/ip6.c
+++ b/usr/src/uts/common/inet/ip/ip6.c
@@ -4436,18 +4436,6 @@
 	ip3dbg(("ip_newroute_v6: ire_ftable_lookup_v6() "
 	    "returned ire %p, sire %p\n", (void *)ire, (void *)sire));
 
-	if (zoneid == ALL_ZONES && ire != NULL) {
-		/*
-		 * In the forwarding case, we can use a route from any zone
-		 * since we won't change the source address. We can easily
-		 * assert that the source address is already set when there's no
-		 * ip6_info header - otherwise we'd have to call pullupmsg().
-		 */
-		ASSERT(ip6i_present ||
-		    !IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src));
-		zoneid = ire->ire_zoneid;
-	}
-
 	/*
 	 * We enter a loop that will be run only once in most cases.
 	 * The loop is re-entered in the case where the destination
@@ -7342,7 +7330,20 @@
 	} else {
 		ire = ire_cache_lookup_v6(&ip6h->ip6_dst, ALL_ZONES,
 		    MBLK_GETLABEL(mp), ipst);
+
+		if (ire != NULL && ire->ire_stq != NULL &&
+		    ire->ire_zoneid != GLOBAL_ZONEID &&
+		    ire->ire_zoneid != ALL_ZONES) {
+			/*
+			 * Should only use IREs that are visible from the
+			 * global zone for forwarding.
+			 */
+			ire_refrele(ire);
+			ire = ire_cache_lookup_v6(&ip6h->ip6_dst,
+			    GLOBAL_ZONEID, MBLK_GETLABEL(mp), ipst);
+		}
 	}
+
 	if (ire == NULL) {
 		/*
 		 * No matching IRE found.  Mark this packet as having
@@ -7381,7 +7382,7 @@
 		    ill->ill_phyint->phyint_ifindex;
 		ip_newroute_v6(q, mp, &ip6h->ip6_dst, &ip6h->ip6_src,
 		    IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_dst) ? ill : NULL,
-		    ALL_ZONES, ipst);
+		    GLOBAL_ZONEID, ipst);
 		return;
 	}
 	/* we have a matching IRE */
@@ -7534,7 +7535,7 @@
 
 			src_ire_v6 = ire_ftable_lookup_v6(&ip6h->ip6_src,
 			    NULL, NULL, IRE_INTERFACE, ire->ire_ipif, NULL,
-			    ALL_ZONES, 0, NULL,
+			    GLOBAL_ZONEID, 0, NULL,
 			    MATCH_IRE_IPIF | MATCH_IRE_TYPE,
 			    ipst);
 
@@ -7962,6 +7963,7 @@
 					    hdr_len, mctl_present, 0, zoneid,
 					    dl_mp);
 			}
+		}
 			/* FALLTHRU */
 		default: {
 			/*
@@ -8146,7 +8148,7 @@
 			used = 0;
 			break;
 		}
-		case IPPROTO_HOPOPTS:
+		case IPPROTO_HOPOPTS: {
 			if (hada_mp != NULL) {
 				ip0dbg(("hop hada drop\n"));
 				goto hada_drop;
@@ -9171,7 +9173,6 @@
 	boolean_t	conn_lock_held;
 	boolean_t	need_decref = B_FALSE;
 	ip_stack_t	*ipst;
-	int		adjust;
 
 	if (q->q_next != NULL) {
 		ill = (ill_t *)q->q_ptr;
@@ -9303,10 +9304,10 @@
 		if (connp != NULL) {
 			ASSERT(CONN_CRED(connp) != NULL);
 			err = tsol_check_label_v6(BEST_CRED(mp, connp),
-			    &mp, &adjust, connp->conn_mac_exempt, ipst);
+			    &mp, connp->conn_mac_exempt, ipst);
 		} else if (DB_CRED(mp) != NULL) {
 			err = tsol_check_label_v6(DB_CRED(mp),
-			    &mp, &adjust, 0, ipst);
+			    &mp, B_FALSE, ipst);
 		}
 		if (mctl_present)
 			first_mp->b_cont = mp;
diff --git a/usr/src/uts/common/inet/ip/tn_ipopt.c b/usr/src/uts/common/inet/ip/tn_ipopt.c
index aa49945..7c6f713 100644
--- a/usr/src/uts/common/inet/ip/tn_ipopt.c
+++ b/usr/src/uts/common/inet/ip/tn_ipopt.c
@@ -257,7 +257,7 @@
 		} else if (ire == NULL) {
 			ire = ire_ftable_lookup(dst, 0, 0, 0, NULL, &sire,
 			    ip_zoneid, 0, tsl, (MATCH_IRE_RECURSIVE |
-				MATCH_IRE_DEFAULT | MATCH_IRE_SECATTR), ipst);
+			    MATCH_IRE_DEFAULT | MATCH_IRE_SECATTR), ipst);
 		}
 
 		/* no route to destination */
@@ -606,7 +606,7 @@
  * zero, so the caller knows that the label is syncronized, and further calls
  * are not required.  If the label isn't right, then the right one is inserted.
  *
- * The packet's header is clear, before entering IPSec's engine.
+ * The packet's header is clear before entering IPsec's engine.
  *
  * Returns:
  *      0		Label on packet (was|is now) correct
@@ -615,8 +615,8 @@
  *	EINVAL		Label cannot be computed
  */
 int
-tsol_check_label(const cred_t *credp, mblk_t **mpp, int *addedp,
-    boolean_t isexempt, ip_stack_t *ipst)
+tsol_check_label(const cred_t *credp, mblk_t **mpp, boolean_t isexempt,
+    ip_stack_t *ipst)
 {
 	mblk_t *mp = *mpp;
 	ipha_t  *ipha;
@@ -624,12 +624,9 @@
 	uint_t hlen;
 	uint_t sec_opt_len;
 	uchar_t *optr;
-	int added;
+	int delta_remove = 0, delta_add, adjust;
 	int retv;
 
-	if (addedp != NULL)
-		*addedp = 0;
-
 	opt_storage[IPOPT_OPTVAL] = 0;
 
 	ipha = (ipha_t *)mp->b_rptr;
@@ -658,8 +655,10 @@
 	/*
 	 * If there is an option there, then it must be the wrong one; delete.
 	 */
-	if (hlen > 0)
-		mp->b_wptr += tsol_remove_secopt(ipha, MBLKL(mp));
+	if (hlen > 0) {
+		delta_remove = tsol_remove_secopt(ipha, MBLKL(mp));
+		mp->b_wptr += delta_remove;
+	}
 
 	/* Make sure we have room for the worst-case addition */
 	hlen = IPH_HDR_LENGTH(ipha) + opt_storage[IPOPT_OLEN];
@@ -693,15 +692,16 @@
 		ipha = (ipha_t *)mp->b_rptr;
 	}
 
-	added = tsol_prepend_option(opt_storage, ipha, MBLKL(mp));
-	if (added == -1)
+	delta_add = tsol_prepend_option(opt_storage, ipha, MBLKL(mp));
+	if (delta_add == -1)
 		goto param_prob;
 
-	if (addedp != NULL)
-		*addedp = added;
+	ASSERT((mp->b_wptr + delta_add) <= DB_LIM(mp));
+	mp->b_wptr += delta_add;
 
-	ASSERT((mp->b_wptr + added) <= DB_LIM(mp));
-	mp->b_wptr += added;
+	adjust = delta_remove + delta_add;
+	adjust += ntohs(ipha->ipha_length);
+	ipha->ipha_length = htons(adjust);
 
 	return (0);
 
@@ -1171,8 +1171,8 @@
  *      ENOMEM		Memory allocation failure.
  */
 int
-tsol_check_label_v6(const cred_t *credp, mblk_t **mpp, int *addedp,
-    boolean_t isexempt, ip_stack_t *ipst)
+tsol_check_label_v6(const cred_t *credp, mblk_t **mpp, boolean_t isexempt,
+    ip_stack_t *ipst)
 {
 	mblk_t *mp = *mpp;
 	ip6_t  *ip6h;
@@ -1183,7 +1183,7 @@
 	uchar_t opt_storage[TSOL_MAX_IPV6_OPTION];
 	uint_t hlen;
 	uint_t sec_opt_len; /* label option length not including type, len */
-	int added;
+	int delta_remove = 0, delta_add;
 	int retv;
 	uchar_t	*after_secopt;
 	uchar_t	*secopt = NULL;
@@ -1191,9 +1191,6 @@
 	uint_t	hbhlen;
 	boolean_t hbh_needed;
 
-	if (addedp != NULL)
-		*addedp = 0;
-
 	ip6h = (ip6_t *)mp->b_rptr;
 	retv = tsol_compute_label_v6(credp, &ip6h->ip6_dst, opt_storage,
 	    isexempt, ipst);
@@ -1225,8 +1222,10 @@
 	/*
 	 * If there is an option there, then it must be the wrong one; delete.
 	 */
-	if (secopt != NULL)
-		mp->b_wptr += tsol_remove_secopt_v6(ip6h, MBLKL(mp));
+	if (secopt != NULL) {
+		delta_remove = tsol_remove_secopt_v6(ip6h, MBLKL(mp));
+		mp->b_wptr += delta_remove;
+	}
 
 	/*
 	 * Make sure we have room for the worst-case addition. Add 2 bytes for
@@ -1268,15 +1267,12 @@
 		ip6h = (ip6_t *)mp->b_rptr;
 	}
 
-	added = tsol_prepend_option_v6(opt_storage, ip6h, MBLKL(mp));
-	if (added == -1)
+	delta_add = tsol_prepend_option_v6(opt_storage, ip6h, MBLKL(mp));
+	if (delta_add == -1)
 		goto param_prob;
 
-	if (addedp != NULL)
-		*addedp = added;
-
-	ASSERT(mp->b_wptr + added <= DB_LIM(mp));
-	mp->b_wptr += added;
+	ASSERT(mp->b_wptr + delta_add <= DB_LIM(mp));
+	mp->b_wptr += delta_add;
 
 	return (0);
 
diff --git a/usr/src/uts/common/inet/ip/tnet.c b/usr/src/uts/common/inet/ip/tnet.c
index 5ffda9f..84fce1b 100644
--- a/usr/src/uts/common/inet/ip/tnet.c
+++ b/usr/src/uts/common/inet/ip/tnet.c
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -849,8 +849,8 @@
 		if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL)
 			return (B_FALSE);
 		if (src_rhtp->tpc_tp.host_type == UNLABELED)
-		    crgetlabel(DB_CRED(mp))->tsl_flags |=
-		    TSLF_UNLABELED;
+			crgetlabel(DB_CRED(mp))->tsl_flags |=
+			    TSLF_UNLABELED;
 		TPC_RELE(src_rhtp);
 	}
 
@@ -1240,10 +1240,10 @@
 	 */
 	if (tsl == NULL || ire->ire_gw_secattr == NULL) {
 		if (tsl != NULL) {
-			DTRACE_PROBE3(
-			tx__ip__log__drop__irematch__nogwsec, char *,
-			"ire(1) lacks ire_gw_secattr when matching label(2)",
-			ire_t *, ire, ts_label_t *, tsl);
+			DTRACE_PROBE3(tx__ip__log__drop__irematch__nogwsec,
+			    char *,
+			    "ire(1) lacks ire_gw_secattr matching label(2)",
+			    ire_t *, ire, ts_label_t *, tsl);
 			error = EACCES;
 		}
 		goto done;
@@ -1400,11 +1400,9 @@
 		ASSERT(gw_rhc != NULL);
 		switch (gw_rhc->rhc_tpc->tpc_tp.host_type) {
 		case SUN_CIPSO:
-			if (tsl->tsl_doi !=
-			    gw_rhc->rhc_tpc->tpc_tp.tp_doi ||
+			if (tsl->tsl_doi != gw_rhc->rhc_tpc->tpc_tp.tp_doi ||
 			    (!_blinrange(&tsl->tsl_label,
-			    &gw_rhc->rhc_tpc->tpc_tp.
-			    tp_sl_range_cipso) &&
+			    &gw_rhc->rhc_tpc->tpc_tp.tp_sl_range_cipso) &&
 			    !blinlset(&tsl->tsl_label,
 			    gw_rhc->rhc_tpc->tpc_tp.tp_sl_set_cipso))) {
 				error = EACCES;
@@ -1418,8 +1416,7 @@
 			break;
 
 		case UNLABELED:
-			if (tsl->tsl_doi !=
-				gw_rhc->rhc_tpc->tpc_tp.tp_doi ||
+			if (tsl->tsl_doi != gw_rhc->rhc_tpc->tpc_tp.tp_doi ||
 			    (!_blinrange(&tsl->tsl_label,
 			    &gw_rhc->rhc_tpc->tpc_tp.tp_gw_sl_range) &&
 			    !blinlset(&tsl->tsl_label,
@@ -1673,27 +1670,17 @@
 		goto keep_label;
 
 	if ((af == AF_INET &&
-	    tsol_check_label(DB_CRED(mp), &mp, &adjust, B_FALSE, ipst) != 0) ||
+	    tsol_check_label(DB_CRED(mp), &mp, B_FALSE, ipst) != 0) ||
 	    (af == AF_INET6 &&
-	    tsol_check_label_v6(DB_CRED(mp), &mp, &adjust, B_FALSE,
-	    ipst) != 0)) {
+	    tsol_check_label_v6(DB_CRED(mp), &mp, B_FALSE, ipst) != 0)) {
 		mp = NULL;
 		goto keep_label;
 	}
 
-	ASSERT(adjust != -1);
-	if (adjust != 0) {
-		if (af == AF_INET) {
-			ipha = (ipha_t *)mp->b_rptr;
-			iplen = ntohs(ipha->ipha_length) + adjust;
-			ipha->ipha_length = htons(iplen);
-			ipha->ipha_hdr_checksum = 0;
-			ipha->ipha_hdr_checksum = ip_csum_hdr(ipha);
-		}
-
-		DTRACE_PROBE3(tx__ip__log__info__forward__adjust, char *,
-		    "mp(1) adjusted(2) for CIPSO option removal",
-		    mblk_t *, mp, int, adjust);
+	if (af == AF_INET) {
+		ipha = (ipha_t *)mp->b_rptr;
+		ipha->ipha_hdr_checksum = 0;
+		ipha->ipha_hdr_checksum = ip_csum_hdr(ipha);
 	}
 
 keep_label:
diff --git a/usr/src/uts/common/inet/rawip_impl.h b/usr/src/uts/common/inet/rawip_impl.h
index 20c3161..638cea6 100644
--- a/usr/src/uts/common/inet/rawip_impl.h
+++ b/usr/src/uts/common/inet/rawip_impl.h
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /* Copyright (c) 1990 Mentat Inc. */
@@ -128,9 +128,8 @@
 	    icmp_old_ipv6_recvdstopts : 1, /* Old ver of IPV6_RECVDSTOPTS */
 
 	    icmp_timestamp : 1,  	/* SO_TIMESTAMP "socket" option */
-	    icmp_mac_exempt : 1,	/* SO_MAC_EXEMPT option */
 
-	    icmp_pad_to_bit_31: 10;
+	    icmp_pad_to_bit_31: 11;
 
 	uint8_t		icmp_type_of_service;
 	uint8_t		icmp_ttl;		/* TTL or hoplimit */
diff --git a/usr/src/uts/common/inet/sctp/sctp_cookie.c b/usr/src/uts/common/inet/sctp/sctp_cookie.c
index 6d1d9c9..46dbb5d 100644
--- a/usr/src/uts/common/inet/sctp/sctp_cookie.c
+++ b/usr/src/uts/common/inet/sctp/sctp_cookie.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -156,8 +156,7 @@
 	/* First validate stream parameters */
 	if (init->sic_instr == 0 || init->sic_outstr == 0) {
 		serror = SCTP_ERR_BAD_MANDPARM;
-		dprint(1,
-		    ("validate_init_params: bad sid, is=%d os=%d\n",
+		dprint(1, ("validate_init_params: bad sid, is=%d os=%d\n",
 		    htons(init->sic_instr), htons(init->sic_outstr)));
 		goto abort;
 	}
@@ -731,14 +730,14 @@
 	if (is_system_labeled() && (cr = DB_CRED(iackmp)) != NULL &&
 	    crgetlabel(cr) != NULL) {
 		conn_t *connp = sctp->sctp_connp;
-		int err, adjust;
+		int err;
 
 		if (isv4)
-			err = tsol_check_label(cr, &iackmp, &adjust,
+			err = tsol_check_label(cr, &iackmp,
 			    connp->conn_mac_exempt,
 			    sctps->sctps_netstack->netstack_ip);
 		else
-			err = tsol_check_label_v6(cr, &iackmp, &adjust,
+			err = tsol_check_label_v6(cr, &iackmp,
 			    connp->conn_mac_exempt,
 			    sctps->sctps_netstack->netstack_ip);
 		if (err != 0) {
@@ -747,11 +746,6 @@
 			freemsg(iackmp);
 			return;
 		}
-		if (isv4) {
-			iackiph = (ipha_t *)iackmp->b_rptr;
-			adjust += ntohs(iackiph->ipha_length);
-			iackiph->ipha_length = htons(adjust);
-		}
 	}
 
 	/*
diff --git a/usr/src/uts/common/inet/sctp/sctp_error.c b/usr/src/uts/common/inet/sctp/sctp_error.c
index 049a17b..783b55a 100644
--- a/usr/src/uts/common/inet/sctp/sctp_error.c
+++ b/usr/src/uts/common/inet/sctp/sctp_error.c
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -254,28 +254,21 @@
 	BUMP_MIB(&sctps->sctps_mib, sctpAborted);
 	BUMP_LOCAL(sctp->sctp_obchunks);
 
+	ipst = sctps->sctps_netstack->netstack_ip;
 	connp = sctp->sctp_connp;
 	if (is_system_labeled() && (cr = DB_CRED(inmp)) != NULL &&
 	    crgetlabel(cr) != NULL) {
-		int err, adjust;
+		int err;
+		boolean_t exempt = connp->conn_mac_exempt;
 
 		if (isv4)
-			err = tsol_check_label(cr, &hmp, &adjust,
-			    connp->conn_mac_exempt,
-			    sctps->sctps_netstack->netstack_ip);
+			err = tsol_check_label(cr, &hmp, exempt, ipst);
 		else
-			err = tsol_check_label_v6(cr, &hmp, &adjust,
-			    connp->conn_mac_exempt,
-			    sctps->sctps_netstack->netstack_ip);
+			err = tsol_check_label_v6(cr, &hmp, exempt, ipst);
 		if (err != 0) {
 			freemsg(hmp);
 			return;
 		}
-		if (isv4) {
-			ahiph = (ipha_t *)hmp->b_rptr;
-			adjust += ntohs(ahiph->ipha_length);
-			ahiph->ipha_length = htons(adjust);
-		}
 	}
 
 	/* Stash the conn ptr info. for IP */
@@ -289,7 +282,6 @@
 	 * Let's just mark the IRE for this destination as temporary
 	 * to prevent any DoS attack.
 	 */
-	ipst = sctps->sctps_netstack->netstack_ip;
 	tsl = cr == NULL ? NULL : crgetlabel(cr);
 	if (isv4) {
 		ire = ire_cache_lookup(iniph->ipha_src, sctp->sctp_zoneid, tsl,
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index 9f44374..470f6ca 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -10452,25 +10452,14 @@
 			}
 			break;
 		case SO_ALLZONES:
-			/* Handled at the IP level */
+			/* Pass option along to IP level for handling */
 			return (-EINVAL);
 		case SO_ANON_MLP:
-			if (!checkonly) {
-				mutex_enter(&connp->conn_lock);
-				connp->conn_anon_mlp = onoff;
-				mutex_exit(&connp->conn_lock);
-			}
-			break;
+			/* Pass option along to IP level for handling */
+			return (-EINVAL);
 		case SO_MAC_EXEMPT:
-			if (secpolicy_net_mac_aware(cr) != 0 ||
-			    IPCL_IS_BOUND(connp))
-				return (EACCES);
-			if (!checkonly) {
-				mutex_enter(&connp->conn_lock);
-				connp->conn_mac_exempt = onoff;
-				mutex_exit(&connp->conn_lock);
-			}
-			break;
+			/* Pass option along to IP level for handling */
+			return (-EINVAL);
 		case SO_EXCLBIND:
 			if (!checkonly)
 				tcp->tcp_exclbind = onoff;
@@ -22734,14 +22723,14 @@
 	/* IP trusts us to set up labels when required. */
 	if (is_system_labeled() && (cr = DB_CRED(mp)) != NULL &&
 	    crgetlabel(cr) != NULL) {
-		int err, adjust;
+		int err;
 
 		if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION)
-			err = tsol_check_label(cr, &mp, &adjust,
+			err = tsol_check_label(cr, &mp,
 			    tcp->tcp_connp->conn_mac_exempt,
 			    tcps->tcps_netstack->netstack_ip);
 		else
-			err = tsol_check_label_v6(cr, &mp, &adjust,
+			err = tsol_check_label_v6(cr, &mp,
 			    tcp->tcp_connp->conn_mac_exempt,
 			    tcps->tcps_netstack->netstack_ip);
 		if (mctl_present)
@@ -22754,8 +22743,6 @@
 		}
 		if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
 			ipha = (ipha_t *)mp->b_rptr;
-			adjust += ntohs(ipha->ipha_length);
-			ipha->ipha_length = htons(adjust);
 		} else {
 			ip6h = (ip6_t *)mp->b_rptr;
 		}
diff --git a/usr/src/uts/common/inet/udp/udp.c b/usr/src/uts/common/inet/udp/udp.c
index 2282373..9514a61 100644
--- a/usr/src/uts/common/inet/udp/udp.c
+++ b/usr/src/uts/common/inet/udp/udp.c
@@ -827,7 +827,8 @@
 			if (!(IPCL_ZONE_MATCH(udp1->udp_connp, zoneid) ||
 			    IPCL_ZONE_MATCH(connp,
 			    udp1->udp_connp->conn_zoneid)) &&
-			    !udp->udp_mac_exempt && !udp1->udp_mac_exempt)
+			    !connp->conn_mac_exempt && \
+			    !udp1->udp_connp->conn_mac_exempt)
 				continue;
 
 			/*
@@ -850,7 +851,8 @@
 			 * as UDP_EXCLBIND, except that zoneid is ignored.
 			 */
 			if (udp1->udp_exclbind || udp->udp_exclbind ||
-			    udp1->udp_mac_exempt || udp->udp_mac_exempt) {
+			    udp1->udp_connp->conn_mac_exempt ||
+			    connp->conn_mac_exempt) {
 				if (V6_OR_V4_INADDR_ANY(
 				    udp1->udp_bound_v6src) ||
 				    is_inaddr_any ||
@@ -2482,7 +2484,7 @@
 	 * exempt mode.  This allows read-down to unlabeled hosts.
 	 */
 	if (getpflags(NET_MAC_AWARE, credp) != 0)
-		udp->udp_mac_exempt = B_TRUE;
+		connp->conn_mac_exempt = B_TRUE;
 
 	if (flag & SO_SOCKSTR) {
 		connp->conn_flags |= IPCL_SOCKET;
@@ -2639,10 +2641,10 @@
 			*i1 = udp->udp_timestamp;
 			break;	/* goto sizeof (int) option return */
 		case SO_ANON_MLP:
-			*i1 = udp->udp_anon_mlp;
+			*i1 = connp->conn_anon_mlp;
 			break;	/* goto sizeof (int) option return */
 		case SO_MAC_EXEMPT:
-			*i1 = udp->udp_mac_exempt;
+			*i1 = connp->conn_mac_exempt;
 			break;	/* goto sizeof (int) option return */
 		case SO_ALLZONES:
 			*i1 = connp->conn_allzones;
@@ -3064,16 +3066,11 @@
 				udp->udp_timestamp = onoff;
 			break;
 		case SO_ANON_MLP:
-			if (!checkonly)
-				udp->udp_anon_mlp = onoff;
-			break;
+			/* Pass option along to IP level for handling */
+			return (-EINVAL);
 		case SO_MAC_EXEMPT:
-			if (secpolicy_net_mac_aware(cr) != 0 ||
-			    udp->udp_state != TS_UNBND)
-				return (EACCES);
-			if (!checkonly)
-				udp->udp_mac_exempt = onoff;
-			break;
+			/* Pass option along to IP level for handling */
+			return (-EINVAL);
 		case SCM_UCRED: {
 			struct ucred_s *ucr;
 			cred_t *cr, *newcr;
@@ -5731,7 +5728,7 @@
 	udp_stack_t	*us = udp->udp_us;
 
 	err = tsol_compute_label(DB_CREDDEF(mp, udp->udp_connp->conn_cred), dst,
-	    opt_storage, udp->udp_mac_exempt,
+	    opt_storage, udp->udp_connp->conn_mac_exempt,
 	    us->us_netstack->netstack_ip);
 	if (err == 0) {
 		err = tsol_update_options(&udp->udp_ip_snd_options,
@@ -6371,7 +6368,7 @@
 	udp_stack_t		*us = udp->udp_us;
 
 	err = tsol_compute_label_v6(DB_CREDDEF(mp, udp->udp_connp->conn_cred),
-	    dst, opt_storage, udp->udp_mac_exempt,
+	    dst, opt_storage, udp->udp_connp->conn_mac_exempt,
 	    us->us_netstack->netstack_ip);
 	if (err == 0) {
 		err = tsol_update_sticky(&udp->udp_sticky_ipp,
diff --git a/usr/src/uts/common/inet/udp_impl.h b/usr/src/uts/common/inet/udp_impl.h
index 131bf3e..04b8dbc 100644
--- a/usr/src/uts/common/inet/udp_impl.h
+++ b/usr/src/uts/common/inet/udp_impl.h
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -92,10 +92,8 @@
 	udpb_direct_sockfs : 1,		/* direct calls to/from sockfs */
 	udpb_timestamp : 1,		/* SO_TIMESTAMP "socket" option */
 
-	udpb_anon_mlp : 1,		/* SO_ANON_MLP */
-	udpb_mac_exempt : 1,		/* SO_MAC_EXEMPT */
 	udpb_nat_t_endpoint : 1,	/* UDP_NAT_T_ENDPOINT option */
-	udpb_pad_to_bit_31 : 1;
+	udpb_pad_to_bit_31 : 3;
 } udp_bits_t;
 
 #define	udp_debug	udp_bits.udpb_debug
@@ -133,8 +131,6 @@
 #define	udp_direct_sockfs	udp_bits.udpb_direct_sockfs
 #define	udp_timestamp		udp_bits.udpb_timestamp
 
-#define	udp_anon_mlp		udp_bits.udpb_anon_mlp
-#define	udp_mac_exempt		udp_bits.udpb_mac_exempt
 #define	udp_nat_t_endpoint	udp_bits.udpb_nat_t_endpoint
 
 /*
diff --git a/usr/src/uts/common/sys/tsol/tnet.h b/usr/src/uts/common/sys/tsol/tnet.h
index 5a0acb1..30b633b 100644
--- a/usr/src/uts/common/sys/tsol/tnet.h
+++ b/usr/src/uts/common/sys/tsol/tnet.h
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  * from "tnet.h	7.44	02/10/09 SMI; TSOL 2.x"
@@ -52,9 +52,8 @@
     ip_stack_t *);
 extern int tsol_compute_label_v6(const cred_t *, const in6_addr_t *, uchar_t *,
     boolean_t, ip_stack_t *);
-extern int tsol_check_label(const cred_t *, mblk_t **, int *, boolean_t,
-    ip_stack_t *);
-extern int tsol_check_label_v6(const cred_t *, mblk_t **, int *, boolean_t,
+extern int tsol_check_label(const cred_t *, mblk_t **, boolean_t, ip_stack_t *);
+extern int tsol_check_label_v6(const cred_t *, mblk_t **, boolean_t,
     ip_stack_t *);
 extern int tsol_prepend_option(uchar_t *, ipha_t *, int);
 extern int tsol_prepend_option_v6(uchar_t *, ip6_t *, int);