--- old/usr/src/uts/common/io/mac/mac_flow.c	Tue Feb  5 11:49:59 2019
+++ new/usr/src/uts/common/io/mac/mac_flow.c	Tue Feb  5 11:49:59 2019
@@ -22,6 +22,8 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2019, Joyent, Inc.
  */
 
 #include <sys/strsun.h>
@@ -113,7 +115,7 @@
 
 	for (i = 0; i < fep->fe_rx_srs_cnt; i++) {
 		mac_srs = (mac_soft_ring_set_t *)fep->fe_rx_srs[i];
-		if (mac_srs == NULL) 		/* Multicast flow */
+		if (mac_srs == NULL)		/* Multicast flow */
 			break;
 		mac_rx_stat = &mac_srs->srs_rx.sr_stat;
 
@@ -127,7 +129,7 @@
 	}
 
 	mac_srs = (mac_soft_ring_set_t *)fep->fe_tx_srs;
-	if (mac_srs == NULL) 		/* Multicast flow */
+	if (mac_srs == NULL)		/* Multicast flow */
 		goto done;
 	mac_tx_stat = &mac_srs->srs_tx.st_stat;
 
@@ -1186,7 +1188,7 @@
 int
 mac_link_flow_init(mac_client_handle_t mch, flow_entry_t *sub_flow)
 {
-	mac_client_impl_t 	*mcip = (mac_client_impl_t *)mch;
+	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
 	mac_impl_t		*mip = mcip->mci_mip;
 	int			err;
 
@@ -1320,7 +1322,7 @@
 void
 mac_link_flow_clean(mac_client_handle_t mch, flow_entry_t *sub_flow)
 {
-	mac_client_impl_t 	*mcip = (mac_client_impl_t *)mch;
+	mac_client_impl_t	*mcip = (mac_client_impl_t *)mch;
 	mac_impl_t		*mip = mcip->mci_mip;
 	boolean_t		last_subflow;
 
@@ -1438,7 +1440,7 @@
 mac_link_flow_modify(char *flow_name, mac_resource_props_t *mrp)
 {
 	flow_entry_t		*flent;
-	mac_client_impl_t 	*mcip;
+	mac_client_impl_t	*mcip;
 	int			err = 0;
 	mac_perim_handle_t	mph;
 	datalink_id_t		linkid;
@@ -1954,6 +1956,8 @@
 	case ETHERTYPE_IP: {
 		ipha_t	*ipha = (ipha_t *)l3_start;
 
+		if (IPH_HDR_VERSION(ipha) != IPV4_VERSION)
+			return (EINVAL);
 		if (PKT_TOO_SMALL(s, l3_start + IP_SIMPLE_HDR_LENGTH))
 			return (ENOBUFS);
 
@@ -1969,11 +1973,16 @@
 		ip6_frag_t	*frag = NULL;
 		uint16_t	ip6_hdrlen;
 		uint8_t		nexthdr;
+		int		errno;
 
-		if (!mac_ip_hdr_length_v6(ip6h, s->fs_mp->b_wptr, &ip6_hdrlen,
-		    &nexthdr, &frag)) {
-			return (ENOBUFS);
-		}
+		errno = mac_ip_hdr_length_v6(ip6h, s->fs_mp->b_wptr,
+		    &ip6_hdrlen, &nexthdr, &frag);
+		/*
+		 * ENOBUFS is not ENOSPC, but the semantics are the
+		 * same for this caller.
+		 */
+		if (errno != 0)
+			return (errno == ENOSPC ? ENOBUFS : errno);
 		l3info->l3_hdrsize = ip6_hdrlen;
 		l3info->l3_protocol = nexthdr;
 		l3info->l3_version = IPV6_VERSION;
--- old/usr/src/uts/common/io/mac/mac_protect.c	Tue Feb  5 11:49:59 2019
+++ new/usr/src/uts/common/io/mac/mac_protect.c	Tue Feb  5 11:49:59 2019
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015, Joyent, Inc.  All rights reserved.
+ * Copyright (c) 2019, Joyent, Inc.  All rights reserved.
  */
 /*
  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
@@ -812,9 +812,11 @@
 	uint8_t		proto;
 	struct udphdr	*udph;
 	uchar_t		*dh;
+	int		errno;
 
-	if (!mac_ip_hdr_length_v6(ip6h, end, &hdrlen, &proto, &frag))
-		return (ENOSPC);
+	errno = mac_ip_hdr_length_v6(ip6h, end, &hdrlen, &proto, &frag);
+	if (errno != 0)
+		return (errno);
 
 	if (proto != IPPROTO_UDP)
 		return (EINVAL);
@@ -861,9 +863,11 @@
 	uint8_t			proto;
 	uchar_t			*hdrp;
 	struct icmp6_hdr	*icmp;
+	int			errno;
 
-	if (!mac_ip_hdr_length_v6(ip6h, end, &hdrlen, &proto, &frag))
-		return (ENOSPC);
+	errno = mac_ip_hdr_length_v6(ip6h, end, &hdrlen, &proto, &frag);
+	if (errno != 0)
+		return (errno);
 
 	if (proto != IPPROTO_ICMPV6)
 		return (EINVAL);
--- old/usr/src/uts/common/io/mac/mac_sched.c	Tue Feb  5 11:49:59 2019
+++ new/usr/src/uts/common/io/mac/mac_sched.c	Tue Feb  5 11:49:59 2019
@@ -21,8 +21,8 @@
 /*
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
- * Copyright 2017 Joyent, Inc.
  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2019 Joyent, Inc.
  */
 
 /*
@@ -42,157 +42,157 @@
  *
  * MAC
  *
- * 	This driver. It interfaces with device drivers and provides abstractions
- * 	that the rest of the system consumes. All data links -- things managed
- * 	with dladm(1M), are accessed through MAC.
+ *	This driver. It interfaces with device drivers and provides abstractions
+ *	that the rest of the system consumes. All data links -- things managed
+ *	with dladm(1M), are accessed through MAC.
  *
  * GLDv3 DEVICE DRIVER
  *
- * 	A GLDv3 device driver refers to a driver, both for pseudo-devices and
- * 	real devices, which implement the GLDv3 driver API. Common examples of
- * 	these are igb and ixgbe, which are drivers for various Intel networking
- * 	cards. These devices may or may not have various features, such as
- * 	hardware rings and checksum offloading. For MAC, a GLDv3 device is the
- * 	final point for the transmission of a packet and the starting point for
- * 	the receipt of a packet.
+ *	A GLDv3 device driver refers to a driver, both for pseudo-devices and
+ *	real devices, which implement the GLDv3 driver API. Common examples of
+ *	these are igb and ixgbe, which are drivers for various Intel networking
+ *	cards. These devices may or may not have various features, such as
+ *	hardware rings and checksum offloading. For MAC, a GLDv3 device is the
+ *	final point for the transmission of a packet and the starting point for
+ *	the receipt of a packet.
  *
  * FLOWS
  *
- * 	At a high level, a flow refers to a series of packets that are related.
- * 	Often times the term is used in the context of TCP to indicate a unique
- * 	TCP connection and the traffic over it. However, a flow can exist at
- * 	other levels of the system as well. MAC has a notion of a default flow
- * 	which is used for all unicast traffic addressed to the address of a MAC
- * 	device. For example, when a VNIC is created, a default flow is created
- * 	for the VNIC's MAC address. In addition, flows are created for broadcast
- * 	groups and a user may create a flow with flowadm(1M).
+ *	At a high level, a flow refers to a series of packets that are related.
+ *	Often times the term is used in the context of TCP to indicate a unique
+ *	TCP connection and the traffic over it. However, a flow can exist at
+ *	other levels of the system as well. MAC has a notion of a default flow
+ *	which is used for all unicast traffic addressed to the address of a MAC
+ *	device. For example, when a VNIC is created, a default flow is created
+ *	for the VNIC's MAC address. In addition, flows are created for broadcast
+ *	groups and a user may create a flow with flowadm(1M).
  *
  * CLASSIFICATION
  *
- * 	Classification refers to the notion of identifying an incoming frame
- * 	based on its destination address and optionally its source addresses and
- * 	doing different processing based on that information. Classification can
- * 	be done in both hardware and software. In general, we usually only
- * 	classify based on the layer two destination, eg. for Ethernet, the
- * 	destination MAC address.
+ *	Classification refers to the notion of identifying an incoming frame
+ *	based on its destination address and optionally its source addresses and
+ *	doing different processing based on that information. Classification can
+ *	be done in both hardware and software. In general, we usually only
+ *	classify based on the layer two destination, eg. for Ethernet, the
+ *	destination MAC address.
  *
- * 	The system also will do classification based on layer three and layer
- * 	four properties. This is used to support things like flowadm(1M), which
- * 	allows setting QoS and other properties on a per-flow basis.
+ *	The system also will do classification based on layer three and layer
+ *	four properties. This is used to support things like flowadm(1M), which
+ *	allows setting QoS and other properties on a per-flow basis.
  *
  * RING
  *
- * 	Conceptually, a ring represents a series of framed messages, often in a
- * 	contiguous chunk of memory that acts as a circular buffer. Rings come in
- * 	a couple of forms. Generally they are either a hardware construct (hw
- * 	ring) or they are a software construct (sw ring) maintained by MAC.
+ *	Conceptually, a ring represents a series of framed messages, often in a
+ *	contiguous chunk of memory that acts as a circular buffer. Rings come in
+ *	a couple of forms. Generally they are either a hardware construct (hw
+ *	ring) or they are a software construct (sw ring) maintained by MAC.
  *
  * HW RING
  *
- * 	A hardware ring is a set of resources provided by a GLDv3 device driver
- * 	(even if it is a pseudo-device). A hardware ring comes in two different
- * 	forms: receive (rx) rings and transmit (tx) rings. An rx hw ring is
- * 	something that has a unique DMA (direct memory access) region and
- * 	generally supports some form of classification (though it isn't always
- * 	used), as well as a means of generating an interrupt specific to that
- * 	ring. For example, the device may generate a specific MSI-X for a PCI
- * 	express device. A tx ring is similar, except that it is dedicated to
- * 	transmission. It may also be a vector for enabling features such as VLAN
- * 	tagging and large transmit offloading. It usually has its own dedicated
- * 	interrupts for transmit being completed.
+ *	A hardware ring is a set of resources provided by a GLDv3 device driver
+ *	(even if it is a pseudo-device). A hardware ring comes in two different
+ *	forms: receive (rx) rings and transmit (tx) rings. An rx hw ring is
+ *	something that has a unique DMA (direct memory access) region and
+ *	generally supports some form of classification (though it isn't always
+ *	used), as well as a means of generating an interrupt specific to that
+ *	ring. For example, the device may generate a specific MSI-X for a PCI
+ *	express device. A tx ring is similar, except that it is dedicated to
+ *	transmission. It may also be a vector for enabling features such as VLAN
+ *	tagging and large transmit offloading. It usually has its own dedicated
+ *	interrupts for transmit being completed.
  *
  * SW RING
  *
- * 	A software ring is a construction of MAC. It represents the same thing
- * 	that a hardware ring generally does, a collection of frames. However,
- * 	instead of being in a contiguous ring of memory, they're instead linked
- * 	by using the mblk_t's b_next pointer. Each frame may itself be multiple
- * 	mblk_t's linked together by the b_cont pointer. A software ring always
- * 	represents a collection of classified packets; however, it varies as to
- * 	whether it uses only layer two information, or a combination of that and
- * 	additional layer three and layer four data.
+ *	A software ring is a construction of MAC. It represents the same thing
+ *	that a hardware ring generally does, a collection of frames. However,
+ *	instead of being in a contiguous ring of memory, they're instead linked
+ *	by using the mblk_t's b_next pointer. Each frame may itself be multiple
+ *	mblk_t's linked together by the b_cont pointer. A software ring always
+ *	represents a collection of classified packets; however, it varies as to
+ *	whether it uses only layer two information, or a combination of that and
+ *	additional layer three and layer four data.
  *
  * FANOUT
  *
- * 	Fanout is the idea of spreading out the load of processing frames based
- * 	on the source and destination information contained in the layer two,
- * 	three, and four headers, such that the data can then be processed in
- * 	parallel using multiple hardware threads.
+ *	Fanout is the idea of spreading out the load of processing frames based
+ *	on the source and destination information contained in the layer two,
+ *	three, and four headers, such that the data can then be processed in
+ *	parallel using multiple hardware threads.
  *
- * 	A fanout algorithm hashes the headers and uses that to place different
- * 	flows into a bucket. The most important thing is that packets that are
- * 	in the same flow end up in the same bucket. If they do not, performance
- * 	can be adversely affected. Consider the case of TCP.  TCP severely
- * 	penalizes a connection if the data arrives out of order. If a given flow
- * 	is processed on different CPUs, then the data will appear out of order,
- * 	hence the invariant that fanout always hash a given flow to the same
- * 	bucket and thus get processed on the same CPU.
+ *	A fanout algorithm hashes the headers and uses that to place different
+ *	flows into a bucket. The most important thing is that packets that are
+ *	in the same flow end up in the same bucket. If they do not, performance
+ *	can be adversely affected. Consider the case of TCP.  TCP severely
+ *	penalizes a connection if the data arrives out of order. If a given flow
+ *	is processed on different CPUs, then the data will appear out of order,
+ *	hence the invariant that fanout always hash a given flow to the same
+ *	bucket and thus get processed on the same CPU.
  *
  * RECEIVE SIDE SCALING (RSS)
  *
  *
- * 	Receive side scaling is a term that isn't common in illumos, but is used
- * 	by vendors and was popularized by Microsoft. It refers to the idea of
- * 	spreading the incoming receive load out across multiple interrupts which
- * 	can be directed to different CPUs. This allows a device to leverage
- * 	hardware rings even when it doesn't support hardware classification. The
- * 	hardware uses an algorithm to perform fanout that ensures the flow
- * 	invariant is maintained.
+ *	Receive side scaling is a term that isn't common in illumos, but is used
+ *	by vendors and was popularized by Microsoft. It refers to the idea of
+ *	spreading the incoming receive load out across multiple interrupts which
+ *	can be directed to different CPUs. This allows a device to leverage
+ *	hardware rings even when it doesn't support hardware classification. The
+ *	hardware uses an algorithm to perform fanout that ensures the flow
+ *	invariant is maintained.
  *
  * SOFT RING SET
  *
- * 	A soft ring set, commonly abbreviated SRS, is a collection of rings and
- * 	is used for both transmitting and receiving. It is maintained in the
- * 	structure mac_soft_ring_set_t. A soft ring set is usually associated
- * 	with flows, and coordinates both the use of hardware and software rings.
- * 	Because the use of hardware rings can change as devices such as VNICs
- * 	come and go, we always ensure that the set has software classification
- * 	rules that correspond to the hardware classification rules from rings.
+ *	A soft ring set, commonly abbreviated SRS, is a collection of rings and
+ *	is used for both transmitting and receiving. It is maintained in the
+ *	structure mac_soft_ring_set_t. A soft ring set is usually associated
+ *	with flows, and coordinates both the use of hardware and software rings.
+ *	Because the use of hardware rings can change as devices such as VNICs
+ *	come and go, we always ensure that the set has software classification
+ *	rules that correspond to the hardware classification rules from rings.
  *
- * 	Soft ring sets are also used for the enforcement of various QoS
- * 	properties. For example, if a bandwidth limit has been placed on a
- * 	specific flow or device, then that will be enforced by the soft ring
- * 	set.
+ *	Soft ring sets are also used for the enforcement of various QoS
+ *	properties. For example, if a bandwidth limit has been placed on a
+ *	specific flow or device, then that will be enforced by the soft ring
+ *	set.
  *
  * SERVICE ATTACHMENT POINT (SAP)
  *
- * 	The service attachment point is a DLPI (Data Link Provider Interface)
- * 	concept; however, it comes up quite often in MAC. Most MAC devices speak
- * 	a protocol that has some notion of different channels or message type
- * 	identifiers. For example, Ethernet defines an EtherType which is a part
- * 	of the Ethernet header and defines the particular protocol of the data
- * 	payload. If the EtherType is set to 0x0800, then it defines that the
- * 	contents of that Ethernet frame is IPv4 traffic. For Ethernet, the
- * 	EtherType is the SAP.
+ *	The service attachment point is a DLPI (Data Link Provider Interface)
+ *	concept; however, it comes up quite often in MAC. Most MAC devices speak
+ *	a protocol that has some notion of different channels or message type
+ *	identifiers. For example, Ethernet defines an EtherType which is a part
+ *	of the Ethernet header and defines the particular protocol of the data
+ *	payload. If the EtherType is set to 0x0800, then it defines that the
+ *	contents of that Ethernet frame is IPv4 traffic. For Ethernet, the
+ *	EtherType is the SAP.
  *
- * 	In DLPI, a given consumer attaches to a specific SAP. In illumos, the ip
- * 	and arp drivers attach to the EtherTypes for IPv4, IPv6, and ARP. Using
- * 	libdlpi(3LIB) user software can attach to arbitrary SAPs. With the
- * 	exception of 802.1Q VLAN tagged traffic, MAC itself does not directly
- * 	consume the SAP; however, it uses that information as part of hashing
- * 	and it may be used as part of the construction of flows.
+ *	In DLPI, a given consumer attaches to a specific SAP. In illumos, the ip
+ *	and arp drivers attach to the EtherTypes for IPv4, IPv6, and ARP. Using
+ *	libdlpi(3LIB) user software can attach to arbitrary SAPs. With the
+ *	exception of 802.1Q VLAN tagged traffic, MAC itself does not directly
+ *	consume the SAP; however, it uses that information as part of hashing
+ *	and it may be used as part of the construction of flows.
  *
  * PRIMARY MAC CLIENT
  *
- * 	The primary mac client refers to a mac client whose unicast address
- * 	matches the address of the device itself. For example, if the system has
- * 	instance of the e1000g driver such as e1000g0, e1000g1, etc., the
- * 	primary mac client is the one named after the device itself. VNICs that
- * 	are created on top of such devices are not the primary client.
+ *	The primary mac client refers to a mac client whose unicast address
+ *	matches the address of the device itself. For example, if the system has
+ *	instance of the e1000g driver such as e1000g0, e1000g1, etc., the
+ *	primary mac client is the one named after the device itself. VNICs that
+ *	are created on top of such devices are not the primary client.
  *
  * TRANSMIT DESCRIPTORS
  *
- * 	Transmit descriptors are a resource that most GLDv3 device drivers have.
- * 	Generally, a GLDv3 device driver takes a frame that's meant to be output
- * 	and puts a copy of it into a region of memory. Each region of memory
- * 	usually has an associated descriptor that the device uses to manage
- * 	properties of the frames. Devices have a limited number of such
- * 	descriptors. They get reclaimed once the device finishes putting the
- * 	frame on the wire.
+ *	Transmit descriptors are a resource that most GLDv3 device drivers have.
+ *	Generally, a GLDv3 device driver takes a frame that's meant to be output
+ *	and puts a copy of it into a region of memory. Each region of memory
+ *	usually has an associated descriptor that the device uses to manage
+ *	properties of the frames. Devices have a limited number of such
+ *	descriptors. They get reclaimed once the device finishes putting the
+ *	frame on the wire.
  *
- * 	If the driver runs out of transmit descriptors, for example, the OS is
- * 	generating more frames than it can put on the wire, then it will return
- * 	them back to the MAC layer.
+ *	If the driver runs out of transmit descriptors, for example, the OS is
+ *	generating more frames than it can put on the wire, then it will return
+ *	them back to the MAC layer.
  *
  * ---------------------------------
  * Rings, Classification, and Fanout
@@ -1194,7 +1194,7 @@
 #define	MAC_SRS_WORKER_POLLING_ON(mac_srs) {				\
 	ASSERT(MUTEX_HELD(&(mac_srs)->srs_lock));			\
 	if (((mac_srs)->srs_state &					\
-	    (SRS_POLLING_CAPAB|SRS_WORKER|SRS_POLLING)) == 		\
+	    (SRS_POLLING_CAPAB|SRS_WORKER|SRS_POLLING)) ==		\
 	    (SRS_POLLING_CAPAB|SRS_WORKER)) {				\
 		(mac_srs)->srs_state |= SRS_POLLING;			\
 		(void) mac_hwring_disable_intr((mac_ring_handle_t)	\
@@ -1217,11 +1217,11 @@
 									\
 	ASSERT(MUTEX_HELD(&(mac_srs)->srs_lock));			\
 	srs_rx->sr_poll_thr_sig++;					\
-	if (((mac_srs)->srs_state & 					\
+	if (((mac_srs)->srs_state &					\
 	    (SRS_POLLING_CAPAB|SRS_WORKER|SRS_GET_PKTS)) ==		\
 		(SRS_WORKER|SRS_POLLING_CAPAB)) {			\
 		(mac_srs)->srs_state |= SRS_GET_PKTS;			\
-		cv_signal(&(mac_srs)->srs_cv);   			\
+		cv_signal(&(mac_srs)->srs_cv);				\
 	} else {							\
 		srs_rx->sr_poll_thr_busy++;				\
 	}								\
@@ -1241,7 +1241,7 @@
 	clock_t now = ddi_get_lbolt();					\
 	if ((mac_srs)->srs_bw->mac_bw_curr_time != now) {		\
 		(mac_srs)->srs_bw->mac_bw_curr_time = now;		\
-		(mac_srs)->srs_bw->mac_bw_used = 0;	       		\
+		(mac_srs)->srs_bw->mac_bw_used = 0;			\
 		if ((mac_srs)->srs_bw->mac_bw_state & SRS_BW_ENFORCED)	\
 			(mac_srs)->srs_bw->mac_bw_state &= ~SRS_BW_ENFORCED; \
 	}								\
@@ -1715,6 +1715,7 @@
 	uint32_t	src_val, dst_val;
 	boolean_t	modifiable = B_TRUE;
 	boolean_t	v6;
+	int		errno;
 
 	ASSERT(MBLKL(mp) >= hdrsize);
 
@@ -1789,15 +1790,27 @@
 		 * when mac_ip_hdr_length_v6() fails because of malformed
 		 * packets or because mblks need to be concatenated using
 		 * pullupmsg().
-		 *
-		 * Perform a version check to prevent parsing weirdness...
 		 */
-		if (IPH_HDR_VERSION(ip6h) != IPV6_VERSION ||
-		    !mac_ip_hdr_length_v6(ip6h, mp->b_wptr, &hdr_len, &nexthdr,
-		    NULL)) {
+		errno = mac_ip_hdr_length_v6(ip6h, mp->b_wptr, &hdr_len,
+		    &nexthdr, NULL);
+		switch (errno) {
+		case EINVAL:
+			/* Bad version. */
+			*indx = 0;
+			*type = OTH;
+			return (0);
+		case 0:
+			break;
+		default:
 			goto src_dst_based_fanout;
 		}
 	} else {
+		if (IPH_HDR_VERSION(ipha) != IPV4_VERSION) {
+			/* Bad version. */
+			*indx = 0;
+			*type = OTH;
+			return (0);
+		}
 		hdr_len = IPH_HDR_LENGTH(ipha);
 		remlen = ntohs(ipha->ipha_length) - hdr_len;
 		nexthdr = ipha->ipha_protocol;
@@ -2207,13 +2220,13 @@
 void
 mac_rx_srs_poll_ring(mac_soft_ring_set_t *mac_srs)
 {
-	kmutex_t 		*lock = &mac_srs->srs_lock;
-	kcondvar_t 		*async = &mac_srs->srs_cv;
+	kmutex_t		*lock = &mac_srs->srs_lock;
+	kcondvar_t		*async = &mac_srs->srs_cv;
 	mac_srs_rx_t		*srs_rx = &mac_srs->srs_rx;
-	mblk_t 			*head, *tail, *mp;
-	callb_cpr_t 		cprinfo;
-	ssize_t 		bytes_to_pickup;
-	size_t 			sz;
+	mblk_t			*head, *tail, *mp;
+	callb_cpr_t		cprinfo;
+	ssize_t			bytes_to_pickup;
+	size_t			sz;
 	int			count;
 	mac_client_impl_t	*smcip;
 
@@ -2480,12 +2493,12 @@
 mac_srs_pick_chain(mac_soft_ring_set_t *mac_srs, mblk_t **chain_tail,
     size_t *chain_sz, int *chain_cnt)
 {
-	mblk_t 			*head = NULL;
-	mblk_t 			*tail = NULL;
+	mblk_t			*head = NULL;
+	mblk_t			*tail = NULL;
 	size_t			sz;
-	size_t 			tsz = 0;
+	size_t			tsz = 0;
 	int			cnt = 0;
-	mblk_t 			*mp;
+	mblk_t			*mp;
 
 	ASSERT(MUTEX_HELD(&mac_srs->srs_lock));
 	mutex_enter(&mac_srs->srs_bw->mac_bw_lock);
@@ -2566,9 +2579,9 @@
 void
 mac_rx_srs_drain(mac_soft_ring_set_t *mac_srs, uint_t proc_type)
 {
-	mblk_t 			*head;
+	mblk_t			*head;
 	mblk_t			*tail;
-	timeout_id_t 		tid;
+	timeout_id_t		tid;
 	int			cnt = 0;
 	mac_client_impl_t	*mcip = mac_srs->srs_mcip;
 	mac_srs_rx_t		*srs_rx = &mac_srs->srs_rx;
@@ -2806,9 +2819,9 @@
 void
 mac_rx_srs_drain_bw(mac_soft_ring_set_t *mac_srs, uint_t proc_type)
 {
-	mblk_t 			*head;
+	mblk_t			*head;
 	mblk_t			*tail;
-	timeout_id_t 		tid;
+	timeout_id_t		tid;
 	size_t			sz = 0;
 	int			cnt = 0;
 	mac_client_impl_t	*mcip = mac_srs->srs_mcip;
@@ -3073,8 +3086,8 @@
 void
 mac_srs_worker(mac_soft_ring_set_t *mac_srs)
 {
-	kmutex_t 		*lock = &mac_srs->srs_lock;
-	kcondvar_t 		*async = &mac_srs->srs_async;
+	kmutex_t		*lock = &mac_srs->srs_lock;
+	kcondvar_t		*async = &mac_srs->srs_async;
 	callb_cpr_t		cprinfo;
 	boolean_t		bw_ctl_flag;
 
@@ -3774,7 +3787,7 @@
  * queue any packets.
  */
 
-#define	MAC_TX_SOFT_RING_PROCESS(chain) {		       		\
+#define	MAC_TX_SOFT_RING_PROCESS(chain) {				\
 	index = COMPUTE_INDEX(hash, mac_srs->srs_tx_ring_count),	\
 	softring = mac_srs->srs_tx_soft_rings[index];			\
 	cookie = mac_tx_soft_ring_process(softring, chain, flag, ret_mp); \
@@ -4615,7 +4628,7 @@
  * a short period.
  */
 
-#define	SOFT_RING_ENQUEUE_CHAIN(ringp, mp, tail, cnt, sz) {	       	\
+#define	SOFT_RING_ENQUEUE_CHAIN(ringp, mp, tail, cnt, sz) {		\
 	/*								\
 	 * Enqueue our mblk chain.					\
 	 */								\
@@ -4792,7 +4805,7 @@
  * a short period.
  */
 
-#define	TX_SOFT_RING_ENQUEUE_CHAIN(ringp, mp, tail, cnt, sz) {	       	\
+#define	TX_SOFT_RING_ENQUEUE_CHAIN(ringp, mp, tail, cnt, sz) {		\
 	ASSERT(MUTEX_HELD(&ringp->s_ring_lock));			\
 	ringp->s_ring_state |= S_RING_ENQUEUED;				\
 	SOFT_RING_ENQUEUE_CHAIN(ringp, mp_chain, tail, cnt, sz);	\
--- old/usr/src/uts/common/io/mac/mac_util.c	Tue Feb  5 11:49:59 2019
+++ new/usr/src/uts/common/io/mac/mac_util.c	Tue Feb  5 11:49:59 2019
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2019 Joyent, Inc.
  */
 
 /*
@@ -477,7 +478,7 @@
  * Returns B_FALSE if all the IP headers are not in the same mblk otherwise
  * returns B_TRUE.
  */
-boolean_t
+int
 mac_ip_hdr_length_v6(ip6_t *ip6h, uint8_t *endptr, uint16_t *hdr_length,
     uint8_t *next_hdr, ip6_frag_t **fragp)
 {
@@ -490,8 +491,14 @@
 	ip6_frag_t *fraghdr;
 
 	if (((uchar_t *)ip6h + IPV6_HDR_LEN) > endptr)
-		return (B_FALSE);
-	ASSERT(IPH_HDR_VERSION(ip6h) == IPV6_VERSION);
+		return (ENOSPC);
+	/*
+	 * Return EINVAL, which mac_protect callers treat explicitly as "let
+	 * pass", flow callers treat as "not in a flow", and the rest treat
+	 * as "don't do special processing".
+	 */
+	if (IPH_HDR_VERSION(ip6h) != IPV6_VERSION)
+		return (EINVAL);
 	length = IPV6_HDR_LEN;
 	whereptr = ((uint8_t *)&ip6h[1]); /* point to next hdr */
 
@@ -511,7 +518,7 @@
 			desthdr = (ip6_dest_t *)whereptr;
 			ehdrlen = 8 * (desthdr->ip6d_len + 1);
 			if ((uchar_t *)desthdr +  ehdrlen > endptr)
-				return (B_FALSE);
+				return (ENOSPC);
 			nexthdrp = &desthdr->ip6d_nxt;
 			break;
 		case IPPROTO_ROUTING:
@@ -518,7 +525,7 @@
 			rthdr = (ip6_rthdr_t *)whereptr;
 			ehdrlen =  8 * (rthdr->ip6r_len + 1);
 			if ((uchar_t *)rthdr +  ehdrlen > endptr)
-				return (B_FALSE);
+				return (ENOSPC);
 			nexthdrp = &rthdr->ip6r_nxt;
 			break;
 		case IPPROTO_FRAGMENT:
@@ -525,7 +532,7 @@
 			fraghdr = (ip6_frag_t *)whereptr;
 			ehdrlen = sizeof (ip6_frag_t);
 			if ((uchar_t *)&fraghdr[1] > endptr)
-				return (B_FALSE);
+				return (ENOSPC);
 			nexthdrp = &fraghdr->ip6f_nxt;
 			if (fragp != NULL)
 				*fragp = fraghdr;
@@ -535,7 +542,7 @@
 		default:
 			*hdr_length = length;
 			*next_hdr = *nexthdrp;
-			return (B_TRUE);
+			return (0);
 		}
 		length += ehdrlen;
 		whereptr += ehdrlen;
@@ -551,8 +558,11 @@
 		 * If any know extension headers are still to be processed,
 		 * the packet's malformed (or at least all the IP header(s) are
 		 * not in the same mblk - and that should never happen.
+		 *
+		 * Return ENOSPC because it MAY be spread across mblks, and
+		 * and the rest of MAC or IPv6 itself can cope.
 		 */
-		return (B_FALSE);
+		return (ENOSPC);
 
 	default:
 		/*
@@ -561,7 +571,7 @@
 		 */
 		*hdr_length = length;
 		*next_hdr = *nexthdrp;
-		return (B_TRUE);
+		return (0);
 	}
 }
 
@@ -968,13 +978,14 @@
 		ipha_t *iphp;
 
 		/*
-		 * If the header is not aligned or the header doesn't fit
-		 * in the mblk, bail now. Note that this may cause packets
-		 * reordering.
+		 * If the header is not aligned, the header doesn't fit in the
+		 * mblk, OR we have a bad IP version, bail now. Note that this
+		 * may cause packets reordering.
 		 */
 		iphp = (ipha_t *)(mp->b_rptr + skip_len);
 		if (((unsigned char *)iphp + sizeof (ipha_t) > mp->b_wptr) ||
-		    !OK_32PTR((char *)iphp))
+		    !OK_32PTR((char *)iphp) ||
+		    IPH_HDR_VERSION(iphp) != IPV4_VERSION)
 			goto done;
 
 		proto = iphp->ipha_protocol;
@@ -1021,8 +1032,9 @@
 		    !OK_32PTR((char *)ip6hp))
 			goto done;
 
-		if (!mac_ip_hdr_length_v6(ip6hp, mp->b_wptr, &hdr_length,
-		    &proto, &frag))
+		/* Also bail, regardless of why, if the function below fails. */
+		if (mac_ip_hdr_length_v6(ip6hp, mp->b_wptr, &hdr_length,
+		    &proto, &frag) != 0)
 			goto done;
 		skip_len += hdr_length;
 
--- old/usr/src/uts/common/sys/mac_impl.h	Tue Feb  5 11:50:00 2019
+++ new/usr/src/uts/common/sys/mac_impl.h	Tue Feb  5 11:50:00 2019
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, Joyent, Inc.
+ * Copyright (c) 2019, Joyent, Inc.
  */
 
 #ifndef	_SYS_MAC_IMPL_H
@@ -244,7 +244,7 @@
 	(mr)->mr_refcnt++;				\
 }
 
-#define	MR_REFRELE(mr)		{	 		\
+#define	MR_REFRELE(mr)		{			\
 	mutex_enter(&(mr)->mr_lock);			\
 	ASSERT((mr)->mr_refcnt != 0);			\
 	(mr)->mr_refcnt--;				\
@@ -300,7 +300,7 @@
 	mac_ring_handle_t mrh = rh;					\
 	mac_impl_t *mimpl = (mac_impl_t *)mhp;				\
 	/*								\
-	 * Send packets through a selected tx ring, or through the 	\
+	 * Send packets through a selected tx ring, or through the	\
 	 * default handler if there is no selected ring.		\
 	 */								\
 	if (mrh == NULL)						\
@@ -322,9 +322,9 @@
 #define	MAC_TX(mip, rh, mp, src_mcip) {					\
 	mac_ring_handle_t	rhandle = (rh);				\
 	/*								\
-	 * If there is a bound Hybrid I/O share, send packets through 	\
+	 * If there is a bound Hybrid I/O share, send packets through	\
 	 * the default tx ring. (When there's a bound Hybrid I/O share,	\
-	 * the tx rings of this client are mapped in the guest domain 	\
+	 * the tx rings of this client are mapped in the guest domain	\
 	 * and not accessible from here.)				\
 	 */								\
 	_NOTE(CONSTANTCONDITION)					\
@@ -333,7 +333,7 @@
 	if (mip->mi_promisc_list != NULL)				\
 		mac_promisc_dispatch(mip, mp, src_mcip);		\
 	/*								\
-	 * Grab the proper transmit pointer and handle. Special 	\
+	 * Grab the proper transmit pointer and handle. Special		\
 	 * optimization: we can test mi_bridge_link itself atomically,	\
 	 * and if that indicates no bridge send packets through tx ring.\
 	 */								\
@@ -723,7 +723,7 @@
 extern int	mac_fini(void);
 
 extern void	mac_ndd_ioctl(mac_impl_t *, queue_t *, mblk_t *);
-extern boolean_t mac_ip_hdr_length_v6(ip6_t *, uint8_t *, uint16_t *,
+extern int mac_ip_hdr_length_v6(ip6_t *, uint8_t *, uint16_t *,
     uint8_t *, ip6_frag_t **);
 
 extern mblk_t *mac_copymsgchain_cksum(mblk_t *);
