summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/truss/print.c1
-rw-r--r--usr/src/lib/libnsl/rpc/svc_generic.c8
-rw-r--r--usr/src/lib/libnsl/rpc/ti_opts.c1
-rw-r--r--usr/src/lib/libsocket/inet/rcmd.c10
-rw-r--r--usr/src/uts/common/inet/sctp/sctp_hash.c2
-rw-r--r--usr/src/uts/common/inet/tcp/tcp.c40
-rw-r--r--usr/src/uts/common/inet/tcp/tcp_opt_data.c2
-rw-r--r--usr/src/uts/common/inet/udp/udp.c7
-rw-r--r--usr/src/uts/common/inet/udp/udp_opt_data.c1
-rw-r--r--usr/src/uts/common/sys/socket.h1
10 files changed, 56 insertions, 17 deletions
diff --git a/usr/src/cmd/truss/print.c b/usr/src/cmd/truss/print.c
index 99b64d354a..2438bf3ec7 100644
--- a/usr/src/cmd/truss/print.c
+++ b/usr/src/cmd/truss/print.c
@@ -1759,6 +1759,7 @@ sol_optname(private_t *pri, long val)
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);
diff --git a/usr/src/lib/libnsl/rpc/svc_generic.c b/usr/src/lib/libnsl/rpc/svc_generic.c
index a0673e43c8..553a6390b6 100644
--- a/usr/src/lib/libnsl/rpc/svc_generic.c
+++ b/usr/src/lib/libnsl/rpc/svc_generic.c
@@ -340,7 +340,7 @@ svc_tli_create_common(const int ofd, const struct netconfig *nconf,
}
/*
- * {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 @@ svc_tli_create_common(const int ofd, const struct netconfig *nconf,
(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);
diff --git a/usr/src/lib/libnsl/rpc/ti_opts.c b/usr/src/lib/libnsl/rpc/ti_opts.c
index ae32fa9788..f01984eabc 100644
--- a/usr/src/lib/libnsl/rpc/ti_opts.c
+++ b/usr/src/lib/libnsl/rpc/ti_opts.c
@@ -494,6 +494,7 @@ __rpc_tli_set_options(int fd, int optlevel, int optname, int optval)
case SO_RECVUCRED:
case SO_ANON_MLP:
case SO_MAC_EXEMPT:
+ case SO_EXCLBIND:
case TCP_EXCLBIND:
case UDP_EXCLBIND:
/* LINTED */
diff --git a/usr/src/lib/libsocket/inet/rcmd.c b/usr/src/lib/libsocket/inet/rcmd.c
index 0bfecc28c6..5cb0fb674f 100644
--- a/usr/src/lib/libsocket/inet/rcmd.c
+++ b/usr/src/lib/libsocket/inet/rcmd.c
@@ -444,10 +444,10 @@ _rresvport_addr(int *alport, struct sockaddr_storage *addr)
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 @@ _rresvport_addr(int *alport, struct sockaddr_storage *addr)
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 @@ _rresvport_addr(int *alport, struct sockaddr_storage *addr)
*/
(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);
}
diff --git a/usr/src/uts/common/inet/sctp/sctp_hash.c b/usr/src/uts/common/inet/sctp/sctp_hash.c
index ff21e9c950..606448d6a3 100644
--- a/usr/src/uts/common/inet/sctp/sctp_hash.c
+++ b/usr/src/uts/common/inet/sctp/sctp_hash.c
@@ -456,7 +456,7 @@ ip_fanout_sctp(mblk_t *mp, ill_t *recv_ill, ipha_t *ipha,
}
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;
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index ea0175f165..5c34200c3f 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -3500,6 +3500,9 @@ tcp_bindi(tcp_t *tcp, in_port_t port, const in6_addr_t *laddr,
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 @@ tcp_bindi(tcp_t *tcp, in_port_t port, const in6_addr_t *laddr,
* 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 @@ tcp_bindi(tcp_t *tcp, in_port_t port, const in6_addr_t *laddr,
* 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.
+ * 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.
*/
- if (ltcp->tcp_exclbind || tcp->tcp_exclbind ||
- lconnp->conn_mac_exempt || connp->conn_mac_exempt) {
+ 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 @@ tcp_opt_get(queue_t *q, int level, int name, uchar_t *ptr)
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 @@ tcp_opt_set(queue_t *q, uint_t optset_context, int level, int name,
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 @@ est:
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 @@ est:
/* 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);
diff --git a/usr/src/uts/common/inet/tcp/tcp_opt_data.c b/usr/src/uts/common/inet/tcp/tcp_opt_data.c
index 350ff7ec30..468424f1ff 100644
--- a/usr/src/uts/common/inet/tcp/tcp_opt_data.c
+++ b/usr/src/uts/common/inet/tcp/tcp_opt_data.c
@@ -80,6 +80,8 @@ opdes_t tcp_opt_arr[] = {
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),
diff --git a/usr/src/uts/common/inet/udp/udp.c b/usr/src/uts/common/inet/udp/udp.c
index b1b6e99445..9206d72a4b 100644
--- a/usr/src/uts/common/inet/udp/udp.c
+++ b/usr/src/uts/common/inet/udp/udp.c
@@ -3129,6 +3129,9 @@ udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
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 @@ udp_opt_set(queue_t *q, uint_t optset_context, int level,
}
break;
}
+ case SO_EXCLBIND:
+ if (!checkonly)
+ udp->udp_exclbind = onoff;
+ break;
default:
*outlenp = 0;
return (EINVAL);
diff --git a/usr/src/uts/common/inet/udp/udp_opt_data.c b/usr/src/uts/common/inet/udp/udp_opt_data.c
index 0ac5bb9a62..1d2ccf7259 100644
--- a/usr/src/uts/common/inet/udp/udp_opt_data.c
+++ b/usr/src/uts/common/inet/udp/udp_opt_data.c
@@ -80,6 +80,7 @@ opdes_t udp_opt_arr[] = {
{ 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 */ },
diff --git a/usr/src/uts/common/sys/socket.h b/usr/src/uts/common/sys/socket.h
index 2d6b58d8c3..7cdcd5b84c 100644
--- a/usr/src/uts/common/sys/socket.h
+++ b/usr/src/uts/common/sys/socket.h
@@ -154,6 +154,7 @@ typedef void *_RESTRICT_KYWD Psocklen_t;
#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 */