Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 May 2010 17:02:29 +0000 (UTC)
From:      Randall Stewart <rrs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r207924 - head/sys/netinet
Message-ID:  <201005111702.o4BH2TLA041721@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rrs
Date: Tue May 11 17:02:29 2010
New Revision: 207924
URL: http://svn.freebsd.org/changeset/base/207924

Log:
  This fixes a bug with the one-2-one model socket when a
  user sets up a socket to a server sends data and closes
  the socket before the server has called accept(). It used
  to NOT work at all. Now we add a flag to the assoc and
  defer assoc cleanup so that the accept will suceed.

Modified:
  head/sys/netinet/sctp_constants.h
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_pcb.c
  head/sys/netinet/sctp_usrreq.c

Modified: head/sys/netinet/sctp_constants.h
==============================================================================
--- head/sys/netinet/sctp_constants.h	Tue May 11 17:02:12 2010	(r207923)
+++ head/sys/netinet/sctp_constants.h	Tue May 11 17:02:29 2010	(r207924)
@@ -498,6 +498,7 @@ __FBSDID("$FreeBSD$");
 #define SCTP_STATE_ABOUT_TO_BE_FREED    0x0200
 #define SCTP_STATE_PARTIAL_MSG_LEFT     0x0400
 #define SCTP_STATE_WAS_ABORTED          0x0800
+#define SCTP_STATE_IN_ACCEPT_QUEUE      0x1000
 #define SCTP_STATE_MASK			0x007f
 
 #define SCTP_GET_STATE(asoc)	((asoc)->state & SCTP_STATE_MASK)

Modified: head/sys/netinet/sctp_input.c
==============================================================================
--- head/sys/netinet/sctp_input.c	Tue May 11 17:02:12 2010	(r207923)
+++ head/sys/netinet/sctp_input.c	Tue May 11 17:02:29 2010	(r207924)
@@ -2743,6 +2743,14 @@ sctp_handle_cookie_echo(struct mbuf *m, 
 			 * Now we must move it from one hash table to
 			 * another and get the tcb in the right place.
 			 */
+
+			/*
+			 * This is where the one-2-one socket is put into
+			 * the accept state waiting for the accept!
+			 */
+			if (*stcb) {
+				(*stcb)->asoc.state |= SCTP_STATE_IN_ACCEPT_QUEUE;
+			}
 			sctp_move_pcb_and_assoc(*inp_p, inp, *stcb);
 
 			atomic_add_int(&(*stcb)->asoc.refcnt, 1);
@@ -4859,8 +4867,8 @@ process_control_chunks:
 			}
 			/*
 			 * First are we accepting? We do this again here
-			 * sincen it is possible that a previous endpoint
-			 * WAS listening responded to a INIT-ACK and then
+			 * since it is possible that a previous endpoint WAS
+			 * listening responded to a INIT-ACK and then
 			 * closed. We opened and bound.. and are now no
 			 * longer listening.
 			 */

Modified: head/sys/netinet/sctp_pcb.c
==============================================================================
--- head/sys/netinet/sctp_pcb.c	Tue May 11 17:02:12 2010	(r207923)
+++ head/sys/netinet/sctp_pcb.c	Tue May 11 17:02:29 2010	(r207924)
@@ -4576,12 +4576,13 @@ sctp_free_assoc(struct sctp_inpcb *inp, 
 			stcb->block_entry = NULL;
 		}
 	}
-	if (stcb->asoc.refcnt) {
+	if ((stcb->asoc.refcnt) || (stcb->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE)) {
 		/*
-		 * reader or writer in the way, we have hopefully given him
-		 * something to chew on above.
+		 * Someone holds a reference OR the socket is unaccepted
+		 * yet.
 		 */
-		sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
+		if (stcb->asoc.refcnt)
+			sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
 		SCTP_TCB_UNLOCK(stcb);
 		if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
 		    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE))

Modified: head/sys/netinet/sctp_usrreq.c
==============================================================================
--- head/sys/netinet/sctp_usrreq.c	Tue May 11 17:02:12 2010	(r207923)
+++ head/sys/netinet/sctp_usrreq.c	Tue May 11 17:02:29 2010	(r207924)
@@ -1510,7 +1510,7 @@ sctp_do_connect_x(struct socket *so, str
 	added = sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
 	/* Fill in the return id */
 	if (error) {
-		(void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12);
+		(void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6);
 		goto out_now;
 	}
 	a_id = (sctp_assoc_t *) optval;
@@ -4670,6 +4670,7 @@ sctp_accept(struct socket *so, struct so
 	SCTP_TCB_LOCK(stcb);
 	SCTP_INP_RUNLOCK(inp);
 	store = stcb->asoc.primary_destination->ro._l_addr;
+	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
 	SCTP_TCB_UNLOCK(stcb);
 	switch (store.sa.sa_family) {
 	case AF_INET:
@@ -4736,6 +4737,10 @@ sctp_accept(struct socket *so, struct so
 		}
 		SCTP_INP_WUNLOCK(inp);
 	}
+	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+		SCTP_TCB_LOCK(stcb);
+		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
+	}
 	return (0);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201005111702.o4BH2TLA041721>