summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorAnders Persson <Anders.Persson@Sun.COM>2009-10-21 19:52:57 -0700
committerAnders Persson <Anders.Persson@Sun.COM>2009-10-21 19:52:57 -0700
commitdc7c11716d554aadaff1e4f6a09a5f3d222f421d (patch)
tree89994738c88ee43d66b9fab4bd4a4d1fd75ebe15 /usr/src
parent491f61a1e1c1fc54a47bbcf53dbbbe1293b93b27 (diff)
downloadillumos-gate-dc7c11716d554aadaff1e4f6a09a5f3d222f421d.tar.gz
6867122 writes on tcp sockets can return ENOTCONN after receiving a RST
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/inet/tcp.h8
-rw-r--r--usr/src/uts/common/inet/tcp/tcp.c26
2 files changed, 20 insertions, 14 deletions
diff --git a/usr/src/uts/common/inet/tcp.h b/usr/src/uts/common/inet/tcp.h
index ae7f471809..8442c4f384 100644
--- a/usr/src/uts/common/inet/tcp.h
+++ b/usr/src/uts/common/inet/tcp.h
@@ -597,11 +597,9 @@ typedef struct tcp_s {
uint32_t tcp_snxt_shrunk;
/*
- * The socket generation number is bumped when an outgoing connection
- * attempts is made, and it sent up to the socket when the
- * connection was successfully established, or an error occured. The
- * generation is used to ensure that the socket does not miss the
- * asynchronous notification.
+ * Socket generation number which is bumped when a connection attempt
+ * is initiated. Its main purpose is to ensure that the socket does not
+ * miss the asynchronous connected/disconnected notification.
*/
sock_connid_t tcp_connid;
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index 96a762f1e9..a6f3ee8331 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -5529,7 +5529,7 @@ tcp_conn_request(void *arg, mblk_t *mp, void *arg2)
* Also check that source is not a multicast or broadcast address.
*/
eager->tcp_state = TCPS_SYN_RCVD;
-
+ SOCK_CONNID_BUMP(eager->tcp_connid);
/*
* There should be no ire in the mp as we are being called after
@@ -25858,6 +25858,14 @@ tcp_post_ip_bind(tcp_t *tcp, mblk_t *mp, int error, cred_t *cr, pid_t pid)
} else {
mblk_setcred(syn_mp, cr, pid);
}
+
+ /*
+ * We must bump the generation before sending the syn
+ * to ensure that we use the right generation in case
+ * this thread issues a "connected" up call.
+ */
+ SOCK_CONNID_BUMP(tcp->tcp_connid);
+
tcp_send_data(tcp, tcp->tcp_wq, syn_mp);
}
after_syn_sent:
@@ -26385,13 +26393,6 @@ tcp_do_connect(conn_t *connp, const struct sockaddr *sa, socklen_t len,
*/
/* FALLTHRU */
case TCPS_BOUND:
- /*
- * We must bump the generation before the operation start.
- * This is done to ensure that any upcall made later on sends
- * up the right generation to the socket.
- */
- SOCK_CONNID_BUMP(tcp->tcp_connid);
-
if (tcp->tcp_family == AF_INET6) {
if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
return (tcp_connect_ipv6(tcp,
@@ -26635,7 +26636,14 @@ tcp_sendmsg(sock_lower_handle_t proto_handle, mblk_t *mp, struct nmsghdr *msg,
tcpstate = tcp->tcp_state;
if (tcpstate < TCPS_ESTABLISHED) {
freemsg(mp);
- return (ENOTCONN);
+ /*
+ * We return ENOTCONN if the endpoint is trying to
+ * connect or has never been connected, and EPIPE if it
+ * has been disconnected. The connection id helps us
+ * distinguish between the last two cases.
+ */
+ return ((tcpstate == TCPS_SYN_SENT) ? ENOTCONN :
+ ((tcp->tcp_connid > 0) ? EPIPE : ENOTCONN));
} else if (tcpstate > TCPS_CLOSE_WAIT) {
freemsg(mp);
return (EPIPE);