changeset 10832:1770c9c8b380

6867122 writes on tcp sockets can return ENOTCONN after receiving a RST
author Anders Persson <Anders.Persson@Sun.COM>
date Wed, 21 Oct 2009 19:52:57 -0700
parents e65585ea170c
children 148e8c056d10
files usr/src/uts/common/inet/tcp.h usr/src/uts/common/inet/tcp/tcp.c
diffstat 2 files changed, 20 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/inet/tcp.h	Wed Oct 21 16:35:06 2009 -0700
+++ b/usr/src/uts/common/inet/tcp.h	Wed Oct 21 19:52:57 2009 -0700
@@ -597,11 +597,9 @@
 	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;
 
--- a/usr/src/uts/common/inet/tcp/tcp.c	Wed Oct 21 16:35:06 2009 -0700
+++ b/usr/src/uts/common/inet/tcp/tcp.c	Wed Oct 21 19:52:57 2009 -0700
@@ -5529,7 +5529,7 @@
 	 * 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 @@
 			} 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 @@
 		 */
 		/* 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 @@
 		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);