Author: tuexen
Date: Mon Sep  9 21:40:07 2013
New Revision: 255434
URL: http://svnweb.freebsd.org/changeset/base/255434

Log:
  Fix the aborting of association with the iterator using an empty
  user initiated error cause (using SCTP_ABORT|SCTP_SENDALL).
  
  Approved by: re (delphij)
  MFC after: 1 week

Modified:
  head/sys/netinet/sctp_output.c

Modified: head/sys/netinet/sctp_output.c
==============================================================================
--- head/sys/netinet/sctp_output.c      Mon Sep  9 21:26:18 2013        
(r255433)
+++ head/sys/netinet/sctp_output.c      Mon Sep  9 21:40:07 2013        
(r255434)
@@ -6412,7 +6412,7 @@ sctp_sendall_iterator(struct sctp_inpcb 
                /* TSNH */
                return;
        }
-       if ((ca->m) && ca->sndlen) {
+       if (ca->sndlen > 0) {
                m = SCTP_M_COPYM(ca->m, 0, M_COPYALL, M_NOWAIT);
                if (m == NULL) {
                        /* can't copy so we are done */
@@ -6441,38 +6441,40 @@ sctp_sendall_iterator(struct sctp_inpcb 
        }
        if (ca->sndrcv.sinfo_flags & SCTP_ABORT) {
                /* Abort this assoc with m as the user defined reason */
-               if (m) {
+               if (m != NULL) {
+                       SCTP_BUF_PREPEND(m, sizeof(struct sctp_paramhdr), 
M_NOWAIT);
+               } else {
+                       m = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
+                           0, M_NOWAIT, 1, MT_DATA);
+                       SCTP_BUF_LEN(m) = sizeof(struct sctp_paramhdr);
+               }
+               if (m != NULL) {
                        struct sctp_paramhdr *ph;
 
-                       SCTP_BUF_PREPEND(m, sizeof(struct sctp_paramhdr), 
M_NOWAIT);
-                       if (m) {
-                               ph = mtod(m, struct sctp_paramhdr *);
-                               ph->param_type = 
htons(SCTP_CAUSE_USER_INITIATED_ABT);
-                               ph->param_length = htons(sizeof(struct 
sctp_paramhdr) + ca->sndlen);
-                       }
-                       /*
-                        * We add one here to keep the assoc from
-                        * dis-appearing on us.
-                        */
-                       atomic_add_int(&stcb->asoc.refcnt, 1);
-                       sctp_abort_an_association(inp, stcb, m, 
SCTP_SO_NOT_LOCKED);
-                       /*
-                        * sctp_abort_an_association calls sctp_free_asoc()
-                        * free association will NOT free it since we
-                        * incremented the refcnt .. we do this to prevent
-                        * it being freed and things getting tricky since we
-                        * could end up (from free_asoc) calling inpcb_free
-                        * which would get a recursive lock call to the
-                        * iterator lock.. But as a consequence of that the
-                        * stcb will return to us un-locked.. since
-                        * free_asoc returns with either no TCB or the TCB
-                        * unlocked, we must relock.. to unlock in the
-                        * iterator timer :-0
-                        */
-                       SCTP_TCB_LOCK(stcb);
-                       atomic_add_int(&stcb->asoc.refcnt, -1);
-                       goto no_chunk_output;
+                       ph = mtod(m, struct sctp_paramhdr *);
+                       ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
+                       ph->param_length = htons(sizeof(struct sctp_paramhdr) + 
ca->sndlen);
                }
+               /*
+                * We add one here to keep the assoc from dis-appearing on
+                * us.
+                */
+               atomic_add_int(&stcb->asoc.refcnt, 1);
+               sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED);
+               /*
+                * sctp_abort_an_association calls sctp_free_asoc() free
+                * association will NOT free it since we incremented the
+                * refcnt .. we do this to prevent it being freed and things
+                * getting tricky since we could end up (from free_asoc)
+                * calling inpcb_free which would get a recursive lock call
+                * to the iterator lock.. But as a consequence of that the
+                * stcb will return to us un-locked.. since free_asoc
+                * returns with either no TCB or the TCB unlocked, we must
+                * relock.. to unlock in the iterator timer :-0
+                */
+               SCTP_TCB_LOCK(stcb);
+               atomic_add_int(&stcb->asoc.refcnt, -1);
+               goto no_chunk_output;
        } else {
                if (m) {
                        ret = sctp_msg_append(stcb, net, m,
@@ -6566,8 +6568,7 @@ sctp_sendall_iterator(struct sctp_inpcb 
 
        if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
            (stcb->asoc.total_flight > 0) &&
-           (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD))
-           ) {
+           (un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD))) {
                do_chunk_output = 0;
        }
        if (do_chunk_output)
@@ -6696,13 +6697,10 @@ sctp_sendall(struct sctp_inpcb *inp, str
                /* Gather the length of the send */
                struct mbuf *mat;
 
-               mat = m;
                ca->sndlen = 0;
-               while (m) {
-                       ca->sndlen += SCTP_BUF_LEN(m);
-                       m = SCTP_BUF_NEXT(m);
+               for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
+                       ca->sndlen += SCTP_BUF_LEN(mat);
                }
-               ca->m = mat;
        }
        ret = sctp_initiate_iterator(NULL, sctp_sendall_iterator, NULL,
            SCTP_PCB_ANY_FLAGS, SCTP_PCB_ANY_FEATURES,
_______________________________________________
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