PSARC 2006/407 SO_EXCLBIND, socket exclusive binding
authorkcpoon
Mon, 24 Jul 2006 23:50:09 -0700
changeset 2429 d2b380bdc797
parent 2428 31f1987cf127
child 2430 18ebe2aef932
PSARC 2006/407 SO_EXCLBIND, socket exclusive binding 6410719 ASSERT() panic in ipsec_in_is_secure() 6442609 TCP_EXCLBIND handling has problem with server restarting 6445396 Add SO_EXCLBIND socket option
usr/src/cmd/truss/print.c
usr/src/lib/libnsl/rpc/svc_generic.c
usr/src/lib/libnsl/rpc/ti_opts.c
usr/src/lib/libsocket/inet/rcmd.c
usr/src/uts/common/inet/sctp/sctp_hash.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/truss/print.c	Mon Jul 24 21:00:20 2006 -0700
+++ b/usr/src/cmd/truss/print.c	Mon Jul 24 23:50:09 2006 -0700
@@ -1759,6 +1759,7 @@
 		case SO_TYPE:		return ("SO_TYPE");
 		case SO_PROTOTYPE:	return ("SO_PROTOTYPE");
 		case SO_ALLZONES:	return ("SO_ALLZONES");
+		case SO_EXCLBIND:	return ("SO_EXCLBIND");
 
 		default:		(void) snprintf(pri->code_buf, CBSIZE,
 						    "0x%lx", val);
--- a/usr/src/lib/libnsl/rpc/svc_generic.c	Mon Jul 24 21:00:20 2006 -0700
+++ b/usr/src/lib/libnsl/rpc/svc_generic.c	Mon Jul 24 23:50:09 2006 -0700
@@ -340,7 +340,7 @@
 		}
 
 		/*
-		 * {TCP,UDP}_EXCLBIND has the following properties
+		 * SO_EXCLBIND has the following properties
 		 *    - an fd bound to port P via IPv4 will prevent an IPv6
 		 *    bind to port P (and vice versa)
 		 *    - an fd bound to a wildcard IP address for port P will
@@ -355,10 +355,8 @@
 		    (tcp || (strcmp(nconf->nc_proto, NC_UDP) == 0)) &&
 		    rpc_control(__RPC_SVC_EXCLBIND_GET, &exclbind)) {
 			if (exclbind) {
-				if (__rpc_tli_set_options(fd,
-					tcp ? IPPROTO_TCP : IPPROTO_UDP,
-					tcp ? TCP_EXCLBIND : UDP_EXCLBIND,
-							1) < 0) {
+				if (__rpc_tli_set_options(fd, SOL_SOCKET,
+				    SO_EXCLBIND, 1) < 0) {
 					syslog(LOG_ERR,
 			    "svc_tli_create: can't set EXCLBIND [netid='%s']",
 					    nconf->nc_netid);
--- a/usr/src/lib/libnsl/rpc/ti_opts.c	Mon Jul 24 21:00:20 2006 -0700
+++ b/usr/src/lib/libnsl/rpc/ti_opts.c	Mon Jul 24 23:50:09 2006 -0700
@@ -494,6 +494,7 @@
 	case SO_RECVUCRED:
 	case SO_ANON_MLP:
 	case SO_MAC_EXEMPT:
+	case SO_EXCLBIND:
 	case TCP_EXCLBIND:
 	case UDP_EXCLBIND:
 		/* LINTED */
--- a/usr/src/lib/libsocket/inet/rcmd.c	Mon Jul 24 21:00:20 2006 -0700
+++ b/usr/src/lib/libsocket/inet/rcmd.c	Mon Jul 24 23:50:09 2006 -0700
@@ -444,10 +444,10 @@
 		return (-1);
 
 	/*
-	 * Set TCP_EXCLBIND to get a "unique" port, which is not bound
+	 * Set SO_EXCLBIND to get a "unique" port, which is not bound
 	 * to any other sockets.
 	 */
-	if (setsockopt(s, IPPROTO_TCP, TCP_EXCLBIND, &on, sizeof (on)) < 0) {
+	if (setsockopt(s, SOL_SOCKET, SO_EXCLBIND, &on, sizeof (on)) < 0) {
 		(void) close(s);
 		return (-1);
 	}
@@ -460,8 +460,8 @@
 			sin6->sin6_port = htons((ushort_t)*alport);
 		}
 		if (bind(s, (struct sockaddr *)addr, len) >= 0) {
-			/* To be safe, need to turn off TCP_EXCLBIND. */
-			(void) setsockopt(s, IPPROTO_TCP, TCP_EXCLBIND, &off,
+			/* To be safe, need to turn off SO_EXCLBIND. */
+			(void) setsockopt(s, SOL_SOCKET, SO_EXCLBIND, &off,
 			    sizeof (off));
 			return (s);
 		}
@@ -510,7 +510,7 @@
 		 */
 		(void) setsockopt(s, IPPROTO_TCP, TCP_ANONPRIVBIND, &off,
 		    sizeof (off));
-		(void) setsockopt(s, IPPROTO_TCP, TCP_EXCLBIND, &off,
+		(void) setsockopt(s, SOL_SOCKET, SO_EXCLBIND, &off,
 		    sizeof (off));
 		return (s);
 	}
--- a/usr/src/uts/common/inet/sctp/sctp_hash.c	Mon Jul 24 21:00:20 2006 -0700
+++ b/usr/src/uts/common/inet/sctp/sctp_hash.c	Mon Jul 24 23:50:09 2006 -0700
@@ -456,7 +456,7 @@
 	}
 	if ((connp = sctp_fanout(src, dst, ports, ipif_seqid, zoneid, mp)) ==
 	    NULL) {
-		ip_fanout_sctp_raw(mp, recv_ill, ipha, isv4,
+		ip_fanout_sctp_raw(first_mp, recv_ill, ipha, isv4,
 		    ports, mctl_present, flags, ip_policy,
 		    ipif_seqid, zoneid);
 		return;
--- a/usr/src/uts/common/inet/tcp/tcp.c	Mon Jul 24 21:00:20 2006 -0700
+++ b/usr/src/uts/common/inet/tcp/tcp.c	Mon Jul 24 23:50:09 2006 -0700
@@ -3500,6 +3500,9 @@
 		mutex_enter(&tbf->tf_lock);
 		for (ltcp = tbf->tf_tcp; ltcp != NULL;
 		    ltcp = ltcp->tcp_bind_hash) {
+			boolean_t not_socket;
+			boolean_t exclbind;
+
 			if (lport != ltcp->tcp_lport)
 				continue;
 
@@ -3533,7 +3536,7 @@
 			 * spec		spec		yes if A
 			 *
 			 * For labeled systems, SO_MAC_EXEMPT behaves the same
-			 * as UDP_EXCLBIND, except that zoneid is ignored.
+			 * as TCP_EXCLBIND, except that zoneid is ignored.
 			 *
 			 * Note:
 			 *
@@ -3558,12 +3561,18 @@
 			 * TCPS_LISTEN and both endpoints have SO_REUSEADDR
 			 * set, let the bind succeed.
 			 *
-			 * But because of (1), we cannot do that now.  If
-			 * in future, we can change this going back semantics,
-			 * we can add the above check.
-			 */
-			if (ltcp->tcp_exclbind || tcp->tcp_exclbind ||
-			    lconnp->conn_mac_exempt || connp->conn_mac_exempt) {
+			 * Because of (1), we cannot do that for TLI
+			 * endpoints.  But we can do that for socket endpoints.
+			 * If in future, we can change this going back
+			 * semantics, we can use the above check for TLI also.
+			 */
+			not_socket = !(TCP_IS_SOCKET(ltcp) &&
+			    TCP_IS_SOCKET(tcp));
+			exclbind = ltcp->tcp_exclbind || tcp->tcp_exclbind;
+
+			if (lconnp->conn_mac_exempt || connp->conn_mac_exempt ||
+			    (exclbind && (not_socket ||
+			    ltcp->tcp_state <= TCPS_ESTABLISHED))) {
 				if (V6_OR_V4_INADDR_ANY(
 				    ltcp->tcp_bound_source_v6) ||
 				    V6_OR_V4_INADDR_ANY(*laddr) ||
@@ -9599,6 +9608,9 @@
 		case SO_MAC_EXEMPT:
 			*i1 = connp->conn_mac_exempt;
 			break;
+		case SO_EXCLBIND:
+			*i1 = tcp->tcp_exclbind ? SO_EXCLBIND : 0;
+			break;
 		default:
 			return (-1);
 		}
@@ -10098,6 +10110,10 @@
 				mutex_exit(&connp->conn_lock);
 			}
 			break;
+		case SO_EXCLBIND:
+			if (!checkonly)
+				tcp->tcp_exclbind = onoff;
+			break;
 		default:
 			*outlenp = 0;
 			return (EINVAL);
@@ -14332,6 +14348,12 @@
 		case TCPS_CLOSING:
 			if (tcp->tcp_fin_acked) {
 				tcp->tcp_state = TCPS_TIME_WAIT;
+				/*
+				 * Unconditionally clear the exclusive binding
+				 * bit so this TIME-WAIT connection won't
+				 * interfere with new ones.
+				 */
+				tcp->tcp_exclbind = 0;
 				if (!TCP_IS_DETACHED(tcp)) {
 					TCP_TIMER_RESTART(tcp,
 					    tcp_time_wait_interval);
@@ -14381,6 +14403,12 @@
 				/* FALLTHRU */
 			case TCPS_FIN_WAIT_2:
 				tcp->tcp_state = TCPS_TIME_WAIT;
+				/*
+				 * Unconditionally clear the exclusive binding
+				 * bit so this TIME-WAIT connection won't
+				 * interfere with new ones.
+				 */
+				tcp->tcp_exclbind = 0;
 				if (!TCP_IS_DETACHED(tcp)) {
 					TCP_TIMER_RESTART(tcp,
 					    tcp_time_wait_interval);
--- a/usr/src/uts/common/inet/tcp/tcp_opt_data.c	Mon Jul 24 21:00:20 2006 -0700
+++ b/usr/src/uts/common/inet/tcp/tcp_opt_data.c	Mon Jul 24 23:50:09 2006 -0700
@@ -80,6 +80,8 @@
 	0 },
 { SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, OP_PASSNEXT, sizeof (int),
 	0 },
+{ SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 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	Mon Jul 24 21:00:20 2006 -0700
+++ b/usr/src/uts/common/inet/udp/udp.c	Mon Jul 24 23:50:09 2006 -0700
@@ -3129,6 +3129,9 @@
 		case SO_ALLZONES:
 			*i1 = connp->conn_allzones;
 			break;	/* goto sizeof (int) option return */
+		case SO_EXCLBIND:
+			*i1 = udp->udp_exclbind ? SO_EXCLBIND : 0;
+			break;
 		default:
 			return (-1);
 		}
@@ -3555,6 +3558,10 @@
 			}
 			break;
 		}
+		case SO_EXCLBIND:
+			if (!checkonly)
+				udp->udp_exclbind = onoff;
+			break;
 		default:
 			*outlenp = 0;
 			return (EINVAL);
--- a/usr/src/uts/common/inet/udp/udp_opt_data.c	Mon Jul 24 21:00:20 2006 -0700
+++ b/usr/src/uts/common/inet/udp/udp_opt_data.c	Mon Jul 24 23:50:09 2006 -0700
@@ -80,6 +80,7 @@
 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, OP_PASSNEXT, sizeof (int),
     0 },
 { SCM_UCRED, SOL_SOCKET, OA_W, OA_W, OP_NP, OP_VARLEN|OP_NODEFAULT, 512, 0 },
+{ SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 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 */ },
--- a/usr/src/uts/common/sys/socket.h	Mon Jul 24 21:00:20 2006 -0700
+++ b/usr/src/uts/common/sys/socket.h	Mon Jul 24 23:50:09 2006 -0700
@@ -154,6 +154,7 @@
 #define	SCM_TIMESTAMP	SO_TIMESTAMP	/* socket control message timestamp */
 
 #define	SO_ALLZONES	0x1014		/* bind in all zones */
+#define	SO_EXCLBIND	0x1015		/* exclusive binding */
 
 #ifdef	_KERNEL
 #define	SO_SRCADDR	0x2001		/* Internal: AF_UNIX source address */