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
--- 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 */