summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/tcp/tcp.c
diff options
context:
space:
mode:
authorkcpoon <none@none>2006-07-24 23:50:09 -0700
committerkcpoon <none@none>2006-07-24 23:50:09 -0700
commitae347574c7f17d33bb822cb146d7f67c88ab1f68 (patch)
tree32acd48faeb75f69fb5f1433a4a9613b76d042ed /usr/src/uts/common/inet/tcp/tcp.c
parentb0f490f41a437c14fba5163cca1e65686e66c84b (diff)
downloadillumos-joyent-ae347574c7f17d33bb822cb146d7f67c88ab1f68.tar.gz
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
Diffstat (limited to 'usr/src/uts/common/inet/tcp/tcp.c')
-rw-r--r--usr/src/uts/common/inet/tcp/tcp.c40
1 files changed, 34 insertions, 6 deletions
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);