--- old/usr/src/uts/common/inet/ip.h	Fri Feb 14 17:16:41 2014
+++ new/usr/src/uts/common/inet/ip.h	Fri Feb 14 17:16:41 2014
@@ -24,6 +24,7 @@
  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  */
 
 #ifndef	_INET_IP_H
@@ -3453,7 +3454,8 @@
 
 extern int	ip_srcid_insert(const in6_addr_t *, zoneid_t, ip_stack_t *);
 extern int	ip_srcid_remove(const in6_addr_t *, zoneid_t, ip_stack_t *);
-extern void	ip_srcid_find_id(uint_t, in6_addr_t *, zoneid_t, netstack_t *);
+extern boolean_t ip_srcid_find_id(uint_t, in6_addr_t *, zoneid_t, boolean_t,
+    netstack_t *);
 extern uint_t	ip_srcid_find_addr(const in6_addr_t *, zoneid_t, netstack_t *);
 
 extern uint8_t	ipoptp_next(ipoptp_t *);
--- old/usr/src/uts/common/inet/ip/icmp.c	Fri Feb 14 17:16:42 2014
+++ new/usr/src/uts/common/inet/ip/icmp.c	Fri Feb 14 17:16:42 2014
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  */
 /* Copyright (c) 1990 Mentat Inc. */
 
@@ -768,8 +769,12 @@
 			scopeid = sin6->sin6_scope_id;
 		srcid = sin6->__sin6_src_id;
 		if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
-			ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
-			    connp->conn_netstack);
+			/* Due to check above, we know sin6_addr is v6-only. */
+			if (!ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+			    B_FALSE, connp->conn_netstack)) {
+				/* Mismatch - v6src would be v4mapped. */
+				return (EADDRNOTAVAIL);
+			}
 		}
 		break;
 	}
@@ -3337,7 +3342,6 @@
 	in6_addr_t	v6nexthop;
 	in_port_t	dstport;
 	uint32_t	flowinfo;
-	uint_t		srcid;
 	int		is_absreq_failure = 0;
 	conn_opt_arg_t	coas, *coa;
 
@@ -3440,6 +3444,9 @@
 		ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
 		ixa->ixa_flags |= IXAF_IS_IPV4;
 	} else if (sin6 != NULL) {
+		boolean_t v4mapped;
+		uint_t srcid;
+
 		v6dst = sin6->sin6_addr;
 		dstport = sin6->sin6_port;
 		flowinfo = sin6->sin6_flowinfo;
@@ -3450,14 +3457,20 @@
 		} else {
 			ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
 		}
-		if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
-			ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
-			    connp->conn_netstack);
-		}
-		if (IN6_IS_ADDR_V4MAPPED(&v6dst))
+		v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
+		if (v4mapped)
 			ixa->ixa_flags |= IXAF_IS_IPV4;
 		else
 			ixa->ixa_flags &= ~IXAF_IS_IPV4;
+		if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
+			if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+			    v4mapped, connp->conn_netstack)) {
+				/* Mismatched v4mapped/v6 specified by srcid. */
+				mutex_exit(&connp->conn_lock);
+				error = EADDRNOTAVAIL;
+				goto failed;	/* Does freemsg() and mib. */
+			}
+		}
 	} else {
 		/* Connected case */
 		v6dst = connp->conn_faddr_v6;
@@ -4419,14 +4432,13 @@
 		IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &v6dst);
 		dstport = sin->sin_port;
 		flowinfo = 0;
+		/* Don't bother with ip_srcid_find_id(), but indicate anyway. */
 		srcid = 0;
 		ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
-		if (srcid != 0 && V4_PART_OF_V6(&v6src) == INADDR_ANY) {
-			ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
-			    connp->conn_netstack);
-		}
 		ixa->ixa_flags |= IXAF_IS_IPV4;
 	} else {
+		boolean_t v4mapped;
+
 		v6dst = sin6->sin6_addr;
 		dstport = sin6->sin6_port;
 		flowinfo = sin6->sin6_flowinfo;
@@ -4437,14 +4449,20 @@
 		} else {
 			ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
 		}
-		if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
-			ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
-			    connp->conn_netstack);
-		}
-		if (IN6_IS_ADDR_V4MAPPED(&v6dst))
+		v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
+		if (v4mapped)
 			ixa->ixa_flags |= IXAF_IS_IPV4;
 		else
 			ixa->ixa_flags &= ~IXAF_IS_IPV4;
+		if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
+			if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+			    v4mapped, connp->conn_netstack)) {
+				/* Mismatched v4mapped/v6 specified by srcid. */
+				mutex_exit(&connp->conn_lock);
+				error = EADDRNOTAVAIL;
+				goto ud_error;
+			}
+		}
 	}
 	/* Handle IP_PKTINFO/IPV6_PKTINFO setting source address. */
 	if (connp->conn_xmit_ipp.ipp_fields & IPPF_ADDR) {
--- old/usr/src/uts/common/inet/ip/ip_srcid.c	Fri Feb 14 17:16:42 2014
+++ new/usr/src/uts/common/inet/ip/ip_srcid.c	Fri Feb 14 17:16:42 2014
@@ -21,6 +21,8 @@
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ *
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  */
 
 /*
@@ -223,14 +225,22 @@
 /*
  * Map from a source id to an address.
  * If the id is unknown return the unspecified address.
+ *
+ * For known IDs, check if the returned address is v4mapped or not, and
+ * return B_TRUE if it matches the desired v4mapped state or not.  This
+ * prevents a broken app from requesting (via __sin6_src_id) a v4mapped
+ * address for a v6 destination, or vice versa.
+ *
+ * "addr" will not be set if we return B_FALSE.
  */
-void
+boolean_t
 ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid,
-    netstack_t *ns)
+    boolean_t v4mapped, netstack_t *ns)
 {
 	srcid_map_t	**smpp;
 	srcid_map_t	*smp;
 	ip_stack_t	*ipst = ns->netstack_ip;
+	boolean_t	rc;
 
 	rw_enter(&ipst->ips_srcid_lock, RW_READER);
 	smpp = srcid_lookup_id(id, ipst);
@@ -239,11 +249,24 @@
 		/* Not preset */
 		ip1dbg(("ip_srcid_find_id: unknown %u or in wrong zone\n", id));
 		*addr = ipv6_all_zeros;
+		rc = B_TRUE;
 	} else {
 		ASSERT(smp->sm_refcnt != 0);
-		*addr = smp->sm_addr;
+		/*
+		 * The caller tells us if it expects a v4mapped address.
+		 * Use it, along with the property of "addr" to set the rc.
+		 */
+		if (IN6_IS_ADDR_V4MAPPED(&smp->sm_addr))
+			rc = v4mapped;	/* We want a v4mapped address. */
+		else
+			rc = !v4mapped; /* We don't want a v4mapped address. */
+
+		if (rc)
+			*addr = smp->sm_addr;
+
 	}
 	rw_exit(&ipst->ips_srcid_lock);
+	return (rc);
 }
 
 /* Assign the next available ID */
--- old/usr/src/uts/common/inet/tcp/tcp.c	Fri Feb 14 17:16:43 2014
+++ new/usr/src/uts/common/inet/tcp/tcp.c	Fri Feb 14 17:16:43 2014
@@ -24,6 +24,7 @@
  * Copyright (c) 2011, Joyent Inc. All rights reserved.
  * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  */
 /* Copyright (c) 1990 Mentat Inc. */
 
@@ -1583,8 +1584,11 @@
 
 	/* Handle __sin6_src_id if socket not bound to an IP address */
 	if (srcid != 0 && connp->conn_laddr_v4 == INADDR_ANY) {
-		ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
-		    IPCL_ZONEID(connp), tcps->tcps_netstack);
+		if (!ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
+		    IPCL_ZONEID(connp), B_TRUE, tcps->tcps_netstack)) {
+			/* Mismatch - conn_laddr_v6 would be v6 address. */
+			return (EADDRNOTAVAIL);
+		}
 		connp->conn_saddr_v6 = connp->conn_laddr_v6;
 	}
 
@@ -1665,8 +1669,11 @@
 
 	/* Handle __sin6_src_id if socket not bound to an IP address */
 	if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) {
-		ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
-		    IPCL_ZONEID(connp), tcps->tcps_netstack);
+		if (!ip_srcid_find_id(srcid, &connp->conn_laddr_v6,
+		    IPCL_ZONEID(connp), B_FALSE, tcps->tcps_netstack)) {
+			/* Mismatch - conn_laddr_v6 would be v4-mapped. */
+			return (EADDRNOTAVAIL);
+		}
 		connp->conn_saddr_v6 = connp->conn_laddr_v6;
 	}
 
--- old/usr/src/uts/common/inet/udp/udp.c	Fri Feb 14 17:16:43 2014
+++ new/usr/src/uts/common/inet/udp/udp.c	Fri Feb 14 17:16:43 2014
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  */
 /* Copyright (c) 1990 Mentat Inc. */
 
@@ -2714,6 +2715,8 @@
 		ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
 		ixa->ixa_flags |= IXAF_IS_IPV4;
 	} else if (sin6 != NULL) {
+		boolean_t v4mapped;
+
 		v6dst = sin6->sin6_addr;
 		dstport = sin6->sin6_port;
 		flowinfo = sin6->sin6_flowinfo;
@@ -2724,14 +2727,20 @@
 		} else {
 			ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
 		}
-		if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
-			ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
-			    connp->conn_netstack);
-		}
-		if (IN6_IS_ADDR_V4MAPPED(&v6dst))
+		v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
+		if (v4mapped)
 			ixa->ixa_flags |= IXAF_IS_IPV4;
 		else
 			ixa->ixa_flags &= ~IXAF_IS_IPV4;
+		if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
+			if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+			    v4mapped, connp->conn_netstack)) {
+				/* Mismatch - v4mapped/v6 specified by srcid. */
+				mutex_exit(&connp->conn_lock);
+				error = EADDRNOTAVAIL;
+				goto failed;	/* Does freemsg() and mib. */
+			}
+		}
 	} else {
 		/* Connected case */
 		v6dst = connp->conn_faddr_v6;
@@ -3722,14 +3731,13 @@
 		IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &v6dst);
 		dstport = sin->sin_port;
 		flowinfo = 0;
+		/* Don't bother with ip_srcid_find_id(), but indicate anyway. */
 		srcid = 0;
 		ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
-		if (srcid != 0 && V4_PART_OF_V6(&v6src) == INADDR_ANY) {
-			ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
-			    connp->conn_netstack);
-		}
 		ixa->ixa_flags |= IXAF_IS_IPV4;
 	} else {
+		boolean_t v4mapped;
+
 		v6dst = sin6->sin6_addr;
 		dstport = sin6->sin6_port;
 		flowinfo = sin6->sin6_flowinfo;
@@ -3740,14 +3748,20 @@
 		} else {
 			ixa->ixa_flags &= ~IXAF_SCOPEID_SET;
 		}
-		if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
-			ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
-			    connp->conn_netstack);
-		}
-		if (IN6_IS_ADDR_V4MAPPED(&v6dst))
+		v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
+		if (v4mapped)
 			ixa->ixa_flags |= IXAF_IS_IPV4;
 		else
 			ixa->ixa_flags &= ~IXAF_IS_IPV4;
+		if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
+			if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+			    v4mapped, connp->conn_netstack)) {
+				/* Mismatched v4mapped/v6 specified by srcid. */
+				mutex_exit(&connp->conn_lock);
+				error = EADDRNOTAVAIL;
+				goto ud_error;
+			}
+		}
 	}
 	/* Handle IP_PKTINFO/IPV6_PKTINFO setting source address. */
 	if (connp->conn_xmit_ipp.ipp_fields & IPPF_ADDR) {
@@ -5526,6 +5540,7 @@
 	uint_t		scopeid = 0;
 	uint_t		srcid = 0;
 	in6_addr_t	v6src = connp->conn_saddr_v6;
+	boolean_t	v4mapped;
 
 	udp = connp->conn_udp;
 	us = udp->udp_us;
@@ -5554,11 +5569,15 @@
 		v6dst = sin6->sin6_addr;
 		dstport = sin6->sin6_port;
 		srcid = sin6->__sin6_src_id;
+		v4mapped = IN6_IS_ADDR_V4MAPPED(&v6dst);
 		if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&v6src)) {
-			ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
-			    connp->conn_netstack);
+			if (ip_srcid_find_id(srcid, &v6src, IPCL_ZONEID(connp),
+			    v4mapped, connp->conn_netstack)) {
+				/* Mismatch v4mapped/v6 specified by srcid. */
+				return (EADDRNOTAVAIL);
+			}
 		}
-		if (IN6_IS_ADDR_V4MAPPED(&v6dst)) {
+		if (v4mapped) {
 			if (connp->conn_ipv6_v6only)
 				return (EADDRNOTAVAIL);
 
