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);
 }
 
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to