Author: tuexen
Date: Sat Apr  7 14:40:21 2018
New Revision: 332171
URL: https://svnweb.freebsd.org/changeset/base/332171

Log:
  MFC r321197:
  
  Fix the accounting and add code to detect errors in accounting.
  Joint work with rrs@

Modified:
  stable/11/sys/netinet/sctp_auth.c
  stable/11/sys/netinet/sctp_indata.c
  stable/11/sys/netinet/sctp_pcb.c
  stable/11/sys/netinet/sctputil.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet/sctp_auth.c
==============================================================================
--- stable/11/sys/netinet/sctp_auth.c   Sat Apr  7 14:40:09 2018        
(r332170)
+++ stable/11/sys/netinet/sctp_auth.c   Sat Apr  7 14:40:21 2018        
(r332171)
@@ -1797,8 +1797,8 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint
                sctp_m_freem(m_notify);
                return;
        }
-       control->spec_flags = M_NOTIFICATION;
        control->length = SCTP_BUF_LEN(m_notify);
+       control->spec_flags = M_NOTIFICATION;
        /* not that we need this */
        control->tail_mbuf = m_notify;
        sctp_add_to_readq(stcb->sctp_ep, stcb, control,

Modified: stable/11/sys/netinet/sctp_indata.c
==============================================================================
--- stable/11/sys/netinet/sctp_indata.c Sat Apr  7 14:40:09 2018        
(r332170)
+++ stable/11/sys/netinet/sctp_indata.c Sat Apr  7 14:40:21 2018        
(r332171)
@@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$");
  * This will cause sctp_service_queues() to get called on the top entry in
  * the list.
  */
-static void
+static uint32_t
 sctp_add_chk_to_control(struct sctp_queued_to_read *control,
     struct sctp_stream_in *strm,
     struct sctp_tcb *stcb,
@@ -92,6 +92,8 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_asso
            asoc->size_on_reasm_queue == 0 &&
            asoc->size_on_all_streams == 0) {
                /* Full rwnd granted */
+               KASSERT(asoc->cnt_on_reasm_queue == 0, ("cnt_on_reasm_queue is 
%u", asoc->cnt_on_reasm_queue));
+               KASSERT(asoc->cnt_on_all_streams == 0, ("cnt_on_all_streams is 
%u", asoc->cnt_on_all_streams));
                calc = max(SCTP_SB_LIMIT_RCV(stcb->sctp_socket), 
SCTP_MINIMAL_RWND);
                return (calc);
        }
@@ -558,7 +560,15 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb,
                }
                /* EY it wont be queued if it could be delivered directly */
                queue_needed = 0;
-               asoc->size_on_all_streams -= control->length;
+               if (asoc->size_on_all_streams >= control->length) {
+                       asoc->size_on_all_streams -= control->length;
+               } else {
+#ifdef INVARIANTS
+                       panic("size_on_all_streams = %u smaller than control 
length %u", asoc->size_on_all_streams, control->length);
+#else
+                       asoc->size_on_all_streams = 0;
+#endif
+               }
                sctp_ucount_decr(asoc->cnt_on_all_streams);
                strm->last_mid_delivered++;
                sctp_mark_non_revokable(asoc, control->sinfo_tsn);
@@ -571,11 +581,19 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb,
                        nxt_todel = strm->last_mid_delivered + 1;
                        if (SCTP_MID_EQ(asoc->idata_supported, nxt_todel, 
control->mid) &&
                            (((control->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) 
== SCTP_DATA_NOT_FRAG)) {
-                               asoc->size_on_all_streams -= control->length;
-                               sctp_ucount_decr(asoc->cnt_on_all_streams);
                                if (control->on_strm_q == SCTP_ON_ORDERED) {
                                        TAILQ_REMOVE(&strm->inqueue, control, 
next_instrm);
+                                       if (asoc->size_on_all_streams >= 
control->length) {
+                                               asoc->size_on_all_streams -= 
control->length;
+                                       } else {
 #ifdef INVARIANTS
+                                               panic("size_on_all_streams = %u 
smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+                                               asoc->size_on_all_streams = 0;
+#endif
+                                       }
+                                       
sctp_ucount_decr(asoc->cnt_on_all_streams);
+#ifdef INVARIANTS
                                } else {
                                        panic("Huh control: %p is on_strm_q: 
%d",
                                            control, control->on_strm_q);
@@ -671,7 +689,7 @@ sctp_setup_tail_pointer(struct sctp_queued_to_read *co
 }
 
 static void
-sctp_add_to_tail_pointer(struct sctp_queued_to_read *control, struct mbuf *m)
+sctp_add_to_tail_pointer(struct sctp_queued_to_read *control, struct mbuf *m, 
uint32_t *added)
 {
        struct mbuf *prev = NULL;
        struct sctp_tcb *stcb;
@@ -715,6 +733,7 @@ sctp_add_to_tail_pointer(struct sctp_queued_to_read *c
                         */
                        sctp_sballoc(stcb, &stcb->sctp_socket->so_rcv, m);
                }
+               *added += SCTP_BUF_LEN(m);
                atomic_add_int(&control->length, SCTP_BUF_LEN(m));
                m = SCTP_BUF_NEXT(m);
        }
@@ -815,7 +834,15 @@ restart:
                                        tchk = TAILQ_FIRST(&control->reasm);
                                        if (tchk->rec.data.rcv_flags & 
SCTP_DATA_FIRST_FRAG) {
                                                TAILQ_REMOVE(&control->reasm, 
tchk, sctp_next);
-                                               asoc->size_on_reasm_queue -= 
tchk->send_size;
+                                               if (asoc->size_on_reasm_queue 
>= tchk->send_size) {
+                                                       
asoc->size_on_reasm_queue -= tchk->send_size;
+                                               } else {
+#ifdef INVARIANTS
+                                                       
panic("size_on_reasm_queue = %u smaller than chunk length %u", 
asoc->size_on_reasm_queue, tchk->send_size);
+#else
+                                                       
asoc->size_on_reasm_queue = 0;
+#endif
+                                               }
                                                
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
                                                nc->first_frag_seen = 1;
                                                nc->fsn_included = 
tchk->rec.data.fsn;
@@ -1127,6 +1154,16 @@ done_un:
 #endif
                                SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
                                TAILQ_REMOVE(&strm->inqueue, control, 
next_instrm);
+                               if (asoc->size_on_all_streams >= 
control->length) {
+                                       asoc->size_on_all_streams -= 
control->length;
+                               } else {
+#ifdef INVARIANTS
+                                       panic("size_on_all_streams = %u smaller 
than control length %u", asoc->size_on_all_streams, control->length);
+#else
+                                       asoc->size_on_all_streams = 0;
+#endif
+                               }
+                               sctp_ucount_decr(asoc->cnt_on_all_streams);
                                control->on_strm_q = 0;
                        }
                        if (strm->pd_api_started && control->pdapi_started) {
@@ -1173,6 +1210,16 @@ deliver_more:
 #endif
                                        
SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
                                        TAILQ_REMOVE(&strm->inqueue, control, 
next_instrm);
+                                       if (asoc->size_on_all_streams >= 
control->length) {
+                                               asoc->size_on_all_streams -= 
control->length;
+                                       } else {
+#ifdef INVARIANTS
+                                               panic("size_on_all_streams = %u 
smaller than control length %u", asoc->size_on_all_streams, control->length);
+#else
+                                               asoc->size_on_all_streams = 0;
+#endif
+                                       }
+                                       
sctp_ucount_decr(asoc->cnt_on_all_streams);
                                        control->on_strm_q = 0;
                                }
                                ret++;
@@ -1219,7 +1266,7 @@ out:
 }
 
 
-void
+uint32_t
 sctp_add_chk_to_control(struct sctp_queued_to_read *control,
     struct sctp_stream_in *strm,
     struct sctp_tcb *stcb, struct sctp_association *asoc,
@@ -1229,6 +1276,7 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *co
         * Given a control and a chunk, merge the data from the chk onto the
         * control and free up the chunk resources.
         */
+       uint32_t added = 0;
        int i_locked = 0;
 
        if (control->on_read_q && (hold_rlock == 0)) {
@@ -1242,7 +1290,7 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *co
                control->data = chk->data;
                sctp_setup_tail_pointer(control);
        } else {
-               sctp_add_to_tail_pointer(control, chk->data);
+               sctp_add_to_tail_pointer(control, chk->data, &added);
        }
        control->fsn_included = chk->rec.data.fsn;
        asoc->size_on_reasm_queue -= chk->send_size;
@@ -1268,6 +1316,16 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *co
                        } else if (control->on_strm_q == SCTP_ON_ORDERED) {
                                /* Ordered */
                                TAILQ_REMOVE(&strm->inqueue, control, 
next_instrm);
+                               if (asoc->size_on_all_streams >= 
control->length) {
+                                       asoc->size_on_all_streams -= 
control->length;
+                               } else {
+#ifdef INVARIANTS
+                                       panic("size_on_all_streams = %u smaller 
than control length %u", asoc->size_on_all_streams, control->length);
+#else
+                                       asoc->size_on_all_streams = 0;
+#endif
+                               }
+                               sctp_ucount_decr(asoc->cnt_on_all_streams);
                                control->on_strm_q = 0;
 #ifdef INVARIANTS
                        } else if (control->on_strm_q) {
@@ -1283,6 +1341,7 @@ sctp_add_chk_to_control(struct sctp_queued_to_read *co
                SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
        }
        sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
+       return (added);
 }
 
 /*
@@ -1302,6 +1361,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struc
        struct sctp_tmit_chunk *at, *nat;
        struct sctp_stream_in *strm;
        int do_wakeup, unordered;
+       uint32_t lenadded;
 
        strm = &asoc->strmin[control->sinfo_stream];
        /*
@@ -1314,6 +1374,9 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struc
        }
        /* Must be added to the stream-in queue */
        if (created_control) {
+               if (unordered == 0) {
+                       sctp_ucount_incr(asoc->cnt_on_all_streams);
+               }
                if (sctp_place_control_in_stream(strm, asoc, control)) {
                        /* Duplicate SSN? */
                        sctp_clean_up_control(stcb, control);
@@ -1373,6 +1436,7 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struc
                chk->data = NULL;
                sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
                sctp_setup_tail_pointer(control);
+               asoc->size_on_all_streams += control->length;
        } else {
                /* Place the chunk in our list */
                int inserted = 0;
@@ -1529,7 +1593,8 @@ sctp_queue_data_for_reasm(struct sctp_tcb *stcb, struc
                                    at->rec.data.fsn,
                                    next_fsn, control->fsn_included);
                                TAILQ_REMOVE(&control->reasm, at, sctp_next);
-                               sctp_add_chk_to_control(control, strm, stcb, 
asoc, at, SCTP_READ_LOCK_NOT_HELD);
+                               lenadded = sctp_add_chk_to_control(control, 
strm, stcb, asoc, at, SCTP_READ_LOCK_NOT_HELD);
+                               asoc->size_on_all_streams += lenadded;
                                if (control->on_read_q) {
                                        do_wakeup = 1;
                                }
@@ -1600,7 +1665,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struc
        uint16_t sid;
        struct mbuf *op_err;
        char msg[SCTP_DIAG_INFO_LEN];
-       struct sctp_queued_to_read *control = NULL;
+       struct sctp_queued_to_read *control, *ncontrol;
        uint32_t ppid;
        uint8_t chk_flags;
        struct sctp_stream_reset_list *liste;
@@ -2006,7 +2071,13 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struc
                        return (0);
                }
                if ((chk_flags & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG) {
+                       struct mbuf *m;
+
                        control->data = dmbuf;
+                       m = control->data;
+                       for (m = control->data; m; m = m->m_next) {
+                               control->length += SCTP_BUF_LEN(m);
+                       }
                        control->tail_mbuf = NULL;
                        control->end_added = 1;
                        control->last_frag_seen = 1;
@@ -2116,16 +2187,16 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struc
                                /* first one on */
                                TAILQ_INSERT_TAIL(&asoc->pending_reply_queue, 
control, next);
                        } else {
-                               struct sctp_queued_to_read *ctlOn, *nctlOn;
+                               struct sctp_queued_to_read *lcontrol, 
*nlcontrol;
                                unsigned char inserted = 0;
 
-                               TAILQ_FOREACH_SAFE(ctlOn, 
&asoc->pending_reply_queue, next, nctlOn) {
-                                       if (SCTP_TSN_GT(control->sinfo_tsn, 
ctlOn->sinfo_tsn)) {
+                               TAILQ_FOREACH_SAFE(lcontrol, 
&asoc->pending_reply_queue, next, nlcontrol) {
+                                       if (SCTP_TSN_GT(control->sinfo_tsn, 
lcontrol->sinfo_tsn)) {
 
                                                continue;
                                        } else {
                                                /* found it */
-                                               TAILQ_INSERT_BEFORE(ctlOn, 
control, next);
+                                               TAILQ_INSERT_BEFORE(lcontrol, 
control, next);
                                                inserted = 1;
                                                break;
                                        }
@@ -2216,8 +2287,6 @@ finish_express_del:
                 * pending_reply space 3: distribute any chunks in
                 * pending_reply_queue.
                 */
-               struct sctp_queued_to_read *ctl, *nctl;
-
                sctp_reset_in_stream(stcb, liste->number_entries, 
liste->list_of_streams);
                TAILQ_REMOVE(&asoc->resetHead, liste, next_resp);
                sctp_send_deferred_reset_response(stcb, liste, 
SCTP_STREAM_RESET_RESULT_PERFORMED);
@@ -2226,34 +2295,34 @@ finish_express_del:
                liste = TAILQ_FIRST(&asoc->resetHead);
                if (TAILQ_EMPTY(&asoc->resetHead)) {
                        /* All can be removed */
-                       TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, 
next, nctl) {
-                               TAILQ_REMOVE(&asoc->pending_reply_queue, ctl, 
next);
-                               sctp_queue_data_to_stream(stcb, asoc, ctl, 
abort_flag, &need_reasm_check);
+                       TAILQ_FOREACH_SAFE(control, &asoc->pending_reply_queue, 
next, ncontrol) {
+                               TAILQ_REMOVE(&asoc->pending_reply_queue, 
control, next);
+                               sctp_queue_data_to_stream(stcb, asoc, control, 
abort_flag, &need_reasm_check);
                                if (*abort_flag) {
                                        return (0);
                                }
                                if (need_reasm_check) {
-                                       (void)sctp_deliver_reasm_check(stcb, 
asoc, &asoc->strmin[ctl->sinfo_stream], SCTP_READ_LOCK_NOT_HELD);
+                                       (void)sctp_deliver_reasm_check(stcb, 
asoc, &asoc->strmin[control->sinfo_stream], SCTP_READ_LOCK_NOT_HELD);
                                        need_reasm_check = 0;
                                }
                        }
                } else {
-                       TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, 
next, nctl) {
-                               if (SCTP_TSN_GT(ctl->sinfo_tsn, liste->tsn)) {
+                       TAILQ_FOREACH_SAFE(control, &asoc->pending_reply_queue, 
next, ncontrol) {
+                               if (SCTP_TSN_GT(control->sinfo_tsn, 
liste->tsn)) {
                                        break;
                                }
                                /*
-                                * if ctl->sinfo_tsn is <= liste->tsn we can
-                                * process it which is the NOT of
-                                * ctl->sinfo_tsn > liste->tsn
+                                * if control->sinfo_tsn is <= liste->tsn we
+                                * can process it which is the NOT of
+                                * control->sinfo_tsn > liste->tsn
                                 */
-                               TAILQ_REMOVE(&asoc->pending_reply_queue, ctl, 
next);
-                               sctp_queue_data_to_stream(stcb, asoc, ctl, 
abort_flag, &need_reasm_check);
+                               TAILQ_REMOVE(&asoc->pending_reply_queue, 
control, next);
+                               sctp_queue_data_to_stream(stcb, asoc, control, 
abort_flag, &need_reasm_check);
                                if (*abort_flag) {
                                        return (0);
                                }
                                if (need_reasm_check) {
-                                       (void)sctp_deliver_reasm_check(stcb, 
asoc, &asoc->strmin[ctl->sinfo_stream], SCTP_READ_LOCK_NOT_HELD);
+                                       (void)sctp_deliver_reasm_check(stcb, 
asoc, &asoc->strmin[control->sinfo_stream], SCTP_READ_LOCK_NOT_HELD);
                                        need_reasm_check = 0;
                                }
                        }
@@ -5181,7 +5250,7 @@ static void
 sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
     struct sctp_stream_in *strmin)
 {
-       struct sctp_queued_to_read *ctl, *nctl;
+       struct sctp_queued_to_read *control, *ncontrol;
        struct sctp_association *asoc;
        uint32_t mid;
        int need_reasm_check = 0;
@@ -5192,43 +5261,51 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
         * First deliver anything prior to and including the stream no that
         * came in.
         */
-       TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next_instrm, nctl) {
-               if (SCTP_MID_GE(asoc->idata_supported, mid, ctl->mid)) {
+       TAILQ_FOREACH_SAFE(control, &strmin->inqueue, next_instrm, ncontrol) {
+               if (SCTP_MID_GE(asoc->idata_supported, mid, control->mid)) {
                        /* this is deliverable now */
-                       if (((ctl->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == 
SCTP_DATA_NOT_FRAG) {
-                               if (ctl->on_strm_q) {
-                                       if (ctl->on_strm_q == SCTP_ON_ORDERED) {
-                                               TAILQ_REMOVE(&strmin->inqueue, 
ctl, next_instrm);
-                                       } else if (ctl->on_strm_q == 
SCTP_ON_UNORDERED) {
-                                               
TAILQ_REMOVE(&strmin->uno_inqueue, ctl, next_instrm);
+                       if (((control->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) 
== SCTP_DATA_NOT_FRAG) {
+                               if (control->on_strm_q) {
+                                       if (control->on_strm_q == 
SCTP_ON_ORDERED) {
+                                               TAILQ_REMOVE(&strmin->inqueue, 
control, next_instrm);
+                                       } else if (control->on_strm_q == 
SCTP_ON_UNORDERED) {
+                                               
TAILQ_REMOVE(&strmin->uno_inqueue, control, next_instrm);
 #ifdef INVARIANTS
                                        } else {
                                                panic("strmin: %p ctl: %p 
unknown %d",
-                                                   strmin, ctl, 
ctl->on_strm_q);
+                                                   strmin, control, 
control->on_strm_q);
 #endif
                                        }
-                                       ctl->on_strm_q = 0;
+                                       control->on_strm_q = 0;
                                }
                                /* subtract pending on streams */
-                               asoc->size_on_all_streams -= ctl->length;
+                               if (asoc->size_on_all_streams >= 
control->length) {
+                                       asoc->size_on_all_streams -= 
control->length;
+                               } else {
+#ifdef INVARIANTS
+                                       panic("size_on_all_streams = %u smaller 
than control length %u", asoc->size_on_all_streams, control->length);
+#else
+                                       asoc->size_on_all_streams = 0;
+#endif
+                               }
                                sctp_ucount_decr(asoc->cnt_on_all_streams);
                                /* deliver it to at least the delivery-q */
                                if (stcb->sctp_socket) {
-                                       sctp_mark_non_revokable(asoc, 
ctl->sinfo_tsn);
+                                       sctp_mark_non_revokable(asoc, 
control->sinfo_tsn);
                                        sctp_add_to_readq(stcb->sctp_ep, stcb,
-                                           ctl,
+                                           control,
                                            &stcb->sctp_socket->so_rcv,
                                            1, SCTP_READ_LOCK_HELD,
                                            SCTP_SO_NOT_LOCKED);
                                }
                        } else {
                                /* Its a fragmented message */
-                               if (ctl->first_frag_seen) {
+                               if (control->first_frag_seen) {
                                        /*
                                         * Make it so this is next to
                                         * deliver, we restore later
                                         */
-                                       strmin->last_mid_delivered = ctl->mid - 
1;
+                                       strmin->last_mid_delivered = 
control->mid - 1;
                                        need_reasm_check = 1;
                                        break;
                                }
@@ -5257,32 +5334,40 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
         * now ready.
         */
        mid = strmin->last_mid_delivered + 1;
-       TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next_instrm, nctl) {
-               if (SCTP_MID_EQ(asoc->idata_supported, mid, ctl->mid)) {
-                       if (((ctl->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) == 
SCTP_DATA_NOT_FRAG) {
+       TAILQ_FOREACH_SAFE(control, &strmin->inqueue, next_instrm, ncontrol) {
+               if (SCTP_MID_EQ(asoc->idata_supported, mid, control->mid)) {
+                       if (((control->sinfo_flags >> 8) & SCTP_DATA_NOT_FRAG) 
== SCTP_DATA_NOT_FRAG) {
                                /* this is deliverable now */
-                               if (ctl->on_strm_q) {
-                                       if (ctl->on_strm_q == SCTP_ON_ORDERED) {
-                                               TAILQ_REMOVE(&strmin->inqueue, 
ctl, next_instrm);
-                                       } else if (ctl->on_strm_q == 
SCTP_ON_UNORDERED) {
-                                               
TAILQ_REMOVE(&strmin->uno_inqueue, ctl, next_instrm);
+                               if (control->on_strm_q) {
+                                       if (control->on_strm_q == 
SCTP_ON_ORDERED) {
+                                               TAILQ_REMOVE(&strmin->inqueue, 
control, next_instrm);
+                                       } else if (control->on_strm_q == 
SCTP_ON_UNORDERED) {
+                                               
TAILQ_REMOVE(&strmin->uno_inqueue, control, next_instrm);
 #ifdef INVARIANTS
                                        } else {
                                                panic("strmin: %p ctl: %p 
unknown %d",
-                                                   strmin, ctl, 
ctl->on_strm_q);
+                                                   strmin, control, 
control->on_strm_q);
 #endif
                                        }
-                                       ctl->on_strm_q = 0;
+                                       control->on_strm_q = 0;
                                }
                                /* subtract pending on streams */
-                               asoc->size_on_all_streams -= ctl->length;
+                               if (asoc->size_on_all_streams >= 
control->length) {
+                                       asoc->size_on_all_streams -= 
control->length;
+                               } else {
+#ifdef INVARIANTS
+                                       panic("size_on_all_streams = %u smaller 
than control length %u", asoc->size_on_all_streams, control->length);
+#else
+                                       asoc->size_on_all_streams = 0;
+#endif
+                               }
                                sctp_ucount_decr(asoc->cnt_on_all_streams);
                                /* deliver it to at least the delivery-q */
-                               strmin->last_mid_delivered = ctl->mid;
+                               strmin->last_mid_delivered = control->mid;
                                if (stcb->sctp_socket) {
-                                       sctp_mark_non_revokable(asoc, 
ctl->sinfo_tsn);
+                                       sctp_mark_non_revokable(asoc, 
control->sinfo_tsn);
                                        sctp_add_to_readq(stcb->sctp_ep, stcb,
-                                           ctl,
+                                           control,
                                            &stcb->sctp_socket->so_rcv, 1,
                                            SCTP_READ_LOCK_HELD, 
SCTP_SO_NOT_LOCKED);
 
@@ -5290,12 +5375,12 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
                                mid = strmin->last_mid_delivered + 1;
                        } else {
                                /* Its a fragmented message */
-                               if (ctl->first_frag_seen) {
+                               if (control->first_frag_seen) {
                                        /*
                                         * Make it so this is next to
                                         * deliver
                                         */
-                                       strmin->last_mid_delivered = ctl->mid - 
1;
+                                       strmin->last_mid_delivered = 
control->mid - 1;
                                        need_reasm_check = 1;
                                        break;
                                }
@@ -5347,7 +5432,15 @@ sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
                }
                cnt_removed++;
                TAILQ_REMOVE(&control->reasm, chk, sctp_next);
-               asoc->size_on_reasm_queue -= chk->send_size;
+               if (asoc->size_on_reasm_queue >= chk->send_size) {
+                       asoc->size_on_reasm_queue -= chk->send_size;
+               } else {
+#ifdef INVARIANTS
+                       panic("size_on_reasm_queue = %u smaller than chunk 
length %u", asoc->size_on_reasm_queue, chk->send_size);
+#else
+                       asoc->size_on_reasm_queue = 0;
+#endif
+               }
                sctp_ucount_decr(asoc->cnt_on_reasm_queue);
                if (chk->data) {
                        sctp_m_freem(chk->data);
@@ -5373,6 +5466,16 @@ sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
        }
        if (control->on_strm_q == SCTP_ON_ORDERED) {
                TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
+               if (asoc->size_on_all_streams >= control->length) {
+                       asoc->size_on_all_streams -= control->length;
+               } else {
+#ifdef INVARIANTS
+                       panic("size_on_all_streams = %u smaller than control 
length %u", asoc->size_on_all_streams, control->length);
+#else
+                       asoc->size_on_all_streams = 0;
+#endif
+               }
+               sctp_ucount_decr(asoc->cnt_on_all_streams);
                control->on_strm_q = 0;
        } else if (control->on_strm_q == SCTP_ON_UNORDERED) {
                TAILQ_REMOVE(&strm->uno_inqueue, control, next_instrm);
@@ -5416,7 +5519,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
        unsigned int i, fwd_sz, m_size;
        uint32_t str_seq;
        struct sctp_stream_in *strm;
-       struct sctp_queued_to_read *ctl, *sv;
+       struct sctp_queued_to_read *control, *sv;
 
        asoc = &stcb->asoc;
        if ((fwd_sz = ntohs(fwd->ch.chunk_length)) < sizeof(struct 
sctp_forward_tsn_chunk)) {
@@ -5575,25 +5678,35 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
                        for (cur_mid = strm->last_mid_delivered; 
SCTP_MID_GE(asoc->idata_supported, mid, cur_mid); cur_mid++) {
                                sctp_flush_reassm_for_str_seq(stcb, asoc, sid, 
cur_mid, ordered, new_cum_tsn);
                        }
-                       TAILQ_FOREACH(ctl, &stcb->sctp_ep->read_queue, next) {
-                               if ((ctl->sinfo_stream == sid) &&
-                                   (SCTP_MID_EQ(asoc->idata_supported, 
ctl->mid, mid))) {
+                       TAILQ_FOREACH(control, &stcb->sctp_ep->read_queue, 
next) {
+                               if ((control->sinfo_stream == sid) &&
+                                   (SCTP_MID_EQ(asoc->idata_supported, 
control->mid, mid))) {
                                        str_seq = (sid << 16) | (0x0000ffff & 
mid);
-                                       ctl->pdapi_aborted = 1;
+                                       control->pdapi_aborted = 1;
                                        sv = stcb->asoc.control_pdapi;
-                                       ctl->end_added = 1;
-                                       if (ctl->on_strm_q == SCTP_ON_ORDERED) {
-                                               TAILQ_REMOVE(&strm->inqueue, 
ctl, next_instrm);
-                                       } else if (ctl->on_strm_q == 
SCTP_ON_UNORDERED) {
-                                               
TAILQ_REMOVE(&strm->uno_inqueue, ctl, next_instrm);
+                                       control->end_added = 1;
+                                       if (control->on_strm_q == 
SCTP_ON_ORDERED) {
+                                               TAILQ_REMOVE(&strm->inqueue, 
control, next_instrm);
+                                               if (asoc->size_on_all_streams 
>= control->length) {
+                                                       
asoc->size_on_all_streams -= control->length;
+                                               } else {
 #ifdef INVARIANTS
-                                       } else if (ctl->on_strm_q) {
+                                                       
panic("size_on_all_streams = %u smaller than control length %u", 
asoc->size_on_all_streams, control->length);
+#else
+                                                       
asoc->size_on_all_streams = 0;
+#endif
+                                               }
+                                               
sctp_ucount_decr(asoc->cnt_on_all_streams);
+                                       } else if (control->on_strm_q == 
SCTP_ON_UNORDERED) {
+                                               
TAILQ_REMOVE(&strm->uno_inqueue, control, next_instrm);
+#ifdef INVARIANTS
+                                       } else if (control->on_strm_q) {
                                                panic("strm: %p ctl: %p unknown 
%d",
-                                                   strm, ctl, ctl->on_strm_q);
+                                                   strm, control, 
control->on_strm_q);
 #endif
                                        }
-                                       ctl->on_strm_q = 0;
-                                       stcb->asoc.control_pdapi = ctl;
+                                       control->on_strm_q = 0;
+                                       stcb->asoc.control_pdapi = control;
                                        
sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
                                            stcb,
                                            SCTP_PARTIAL_DELIVERY_ABORTED,
@@ -5601,8 +5714,8 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
                                            SCTP_SO_NOT_LOCKED);
                                        stcb->asoc.control_pdapi = sv;
                                        break;
-                               } else if ((ctl->sinfo_stream == sid) &&
-                                   SCTP_MID_GT(asoc->idata_supported, 
ctl->mid, mid)) {
+                               } else if ((control->sinfo_stream == sid) &&
+                                   SCTP_MID_GT(asoc->idata_supported, 
control->mid, mid)) {
                                        /* We are past our victim SSN */
                                        break;
                                }

Modified: stable/11/sys/netinet/sctp_pcb.c
==============================================================================
--- stable/11/sys/netinet/sctp_pcb.c    Sat Apr  7 14:40:09 2018        
(r332170)
+++ stable/11/sys/netinet/sctp_pcb.c    Sat Apr  7 14:40:21 2018        
(r332171)
@@ -4599,21 +4599,21 @@ void
 sctp_clean_up_stream(struct sctp_tcb *stcb, struct sctp_readhead *rh)
 {
        struct sctp_tmit_chunk *chk, *nchk;
-       struct sctp_queued_to_read *ctl, *nctl;
+       struct sctp_queued_to_read *control, *ncontrol;
 
-       TAILQ_FOREACH_SAFE(ctl, rh, next_instrm, nctl) {
-               TAILQ_REMOVE(rh, ctl, next_instrm);
-               ctl->on_strm_q = 0;
-               if (ctl->on_read_q == 0) {
-                       sctp_free_remote_addr(ctl->whoFrom);
-                       if (ctl->data) {
-                               sctp_m_freem(ctl->data);
-                               ctl->data = NULL;
+       TAILQ_FOREACH_SAFE(control, rh, next_instrm, ncontrol) {
+               TAILQ_REMOVE(rh, control, next_instrm);
+               control->on_strm_q = 0;
+               if (control->on_read_q == 0) {
+                       sctp_free_remote_addr(control->whoFrom);
+                       if (control->data) {
+                               sctp_m_freem(control->data);
+                               control->data = NULL;
                        }
                }
                /* Reassembly free? */
-               TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, nchk) {
-                       TAILQ_REMOVE(&ctl->reasm, chk, sctp_next);
+               TAILQ_FOREACH_SAFE(chk, &control->reasm, sctp_next, nchk) {
+                       TAILQ_REMOVE(&control->reasm, chk, sctp_next);
                        if (chk->data) {
                                sctp_m_freem(chk->data);
                                chk->data = NULL;
@@ -4629,8 +4629,8 @@ sctp_clean_up_stream(struct sctp_tcb *stcb, struct sct
                 * We don't free the address here since all the net's were
                 * freed above.
                 */
-               if (ctl->on_read_q == 0) {
-                       sctp_free_a_readq(stcb, ctl);
+               if (control->on_read_q == 0) {
+                       sctp_free_a_readq(stcb, control);
                }
        }
 }
@@ -6801,7 +6801,7 @@ sctp_drain_mbufs(struct sctp_tcb *stcb)
        struct sctp_association *asoc;
        struct sctp_tmit_chunk *chk, *nchk;
        uint32_t cumulative_tsn_p1;
-       struct sctp_queued_to_read *ctl, *nctl;
+       struct sctp_queued_to_read *control, *ncontrol;
        int cnt, strmat;
        uint32_t gap, i;
        int fnd = 0;
@@ -6818,88 +6818,124 @@ sctp_drain_mbufs(struct sctp_tcb *stcb)
        cnt = 0;
        /* Ok that was fun, now we will drain all the inbound streams? */
        for (strmat = 0; strmat < asoc->streamincnt; strmat++) {
-               TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].inqueue, 
next_instrm, nctl) {
+               TAILQ_FOREACH_SAFE(control, &asoc->strmin[strmat].inqueue, 
next_instrm, ncontrol) {
 #ifdef INVARIANTS
-                       if (ctl->on_strm_q != SCTP_ON_ORDERED) {
+                       if (control->on_strm_q != SCTP_ON_ORDERED) {
                                panic("Huh control: %p on_q: %d -- not 
ordered?",
-                                   ctl, ctl->on_strm_q);
+                                   control, control->on_strm_q);
                        }
 #endif
-                       if (SCTP_TSN_GT(ctl->sinfo_tsn, cumulative_tsn_p1)) {
+                       if (SCTP_TSN_GT(control->sinfo_tsn, cumulative_tsn_p1)) 
{
                                /* Yep it is above cum-ack */
                                cnt++;
-                               SCTP_CALC_TSN_TO_GAP(gap, ctl->sinfo_tsn, 
asoc->mapping_array_base_tsn);
-                               asoc->size_on_all_streams = 
sctp_sbspace_sub(asoc->size_on_all_streams, ctl->length);
+                               SCTP_CALC_TSN_TO_GAP(gap, control->sinfo_tsn, 
asoc->mapping_array_base_tsn);
+                               KASSERT(control->length > 0, ("control has zero 
length"));
+                               if (asoc->size_on_all_streams >= 
control->length) {
+                                       asoc->size_on_all_streams -= 
control->length;
+                               } else {
+#ifdef INVARIANTS
+                                       panic("size_on_all_streams = %u smaller 
than control length %u", asoc->size_on_all_streams, control->length);
+#else
+                                       asoc->size_on_all_streams = 0;
+#endif
+                               }
                                sctp_ucount_decr(asoc->cnt_on_all_streams);
                                SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, 
gap);
-                               if (ctl->on_read_q) {
-                                       
TAILQ_REMOVE(&stcb->sctp_ep->read_queue, ctl, next);
-                                       ctl->on_read_q = 0;
+                               if (control->on_read_q) {
+                                       
TAILQ_REMOVE(&stcb->sctp_ep->read_queue, control, next);
+                                       control->on_read_q = 0;
                                }
-                               TAILQ_REMOVE(&asoc->strmin[strmat].inqueue, 
ctl, next_instrm);
-                               ctl->on_strm_q = 0;
-                               if (ctl->data) {
-                                       sctp_m_freem(ctl->data);
-                                       ctl->data = NULL;
+                               TAILQ_REMOVE(&asoc->strmin[strmat].inqueue, 
control, next_instrm);
+                               control->on_strm_q = 0;
+                               if (control->data) {
+                                       sctp_m_freem(control->data);
+                                       control->data = NULL;
                                }
-                               sctp_free_remote_addr(ctl->whoFrom);
+                               sctp_free_remote_addr(control->whoFrom);
                                /* Now its reasm? */
-                               TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, 
nchk) {
+                               TAILQ_FOREACH_SAFE(chk, &control->reasm, 
sctp_next, nchk) {
                                        cnt++;
                                        SCTP_CALC_TSN_TO_GAP(gap, 
chk->rec.data.tsn, asoc->mapping_array_base_tsn);
-                                       asoc->size_on_reasm_queue = 
sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size);
+                                       KASSERT(chk->send_size > 0, ("chunk has 
zero length"));
+                                       if (asoc->size_on_reasm_queue >= 
chk->send_size) {
+                                               asoc->size_on_reasm_queue -= 
chk->send_size;
+                                       } else {
+#ifdef INVARIANTS
+                                               panic("size_on_reasm_queue = %u 
smaller than chunk length %u", asoc->size_on_reasm_queue, chk->send_size);
+#else
+                                               asoc->size_on_reasm_queue = 0;
+#endif
+                                       }
                                        
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
                                        
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
-                                       TAILQ_REMOVE(&ctl->reasm, chk, 
sctp_next);
+                                       TAILQ_REMOVE(&control->reasm, chk, 
sctp_next);
                                        if (chk->data) {
                                                sctp_m_freem(chk->data);
                                                chk->data = NULL;
                                        }
                                        sctp_free_a_chunk(stcb, chk, 
SCTP_SO_NOT_LOCKED);
                                }
-                               sctp_free_a_readq(stcb, ctl);
+                               sctp_free_a_readq(stcb, control);
                        }
                }
-               TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].uno_inqueue, 
next_instrm, nctl) {
+               TAILQ_FOREACH_SAFE(control, &asoc->strmin[strmat].uno_inqueue, 
next_instrm, ncontrol) {
 #ifdef INVARIANTS
-                       if (ctl->on_strm_q != SCTP_ON_UNORDERED) {
+                       if (control->on_strm_q != SCTP_ON_UNORDERED) {
                                panic("Huh control: %p on_q: %d -- not 
unordered?",
-                                   ctl, ctl->on_strm_q);
+                                   control, control->on_strm_q);
                        }
 #endif
-                       if (SCTP_TSN_GT(ctl->sinfo_tsn, cumulative_tsn_p1)) {
+                       if (SCTP_TSN_GT(control->sinfo_tsn, cumulative_tsn_p1)) 
{
                                /* Yep it is above cum-ack */
                                cnt++;
-                               SCTP_CALC_TSN_TO_GAP(gap, ctl->sinfo_tsn, 
asoc->mapping_array_base_tsn);
-                               asoc->size_on_all_streams = 
sctp_sbspace_sub(asoc->size_on_all_streams, ctl->length);
+                               SCTP_CALC_TSN_TO_GAP(gap, control->sinfo_tsn, 
asoc->mapping_array_base_tsn);
+                               KASSERT(control->length > 0, ("control has zero 
length"));
+                               if (asoc->size_on_all_streams >= 
control->length) {
+                                       asoc->size_on_all_streams -= 
control->length;
+                               } else {
+#ifdef INVARIANTS
+                                       panic("size_on_all_streams = %u smaller 
than control length %u", asoc->size_on_all_streams, control->length);
+#else
+                                       asoc->size_on_all_streams = 0;
+#endif
+                               }
                                sctp_ucount_decr(asoc->cnt_on_all_streams);
                                SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, 
gap);
-                               if (ctl->on_read_q) {
-                                       
TAILQ_REMOVE(&stcb->sctp_ep->read_queue, ctl, next);
-                                       ctl->on_read_q = 0;
+                               if (control->on_read_q) {
+                                       
TAILQ_REMOVE(&stcb->sctp_ep->read_queue, control, next);
+                                       control->on_read_q = 0;
                                }
-                               TAILQ_REMOVE(&asoc->strmin[strmat].uno_inqueue, 
ctl, next_instrm);
-                               ctl->on_strm_q = 0;
-                               if (ctl->data) {
-                                       sctp_m_freem(ctl->data);
-                                       ctl->data = NULL;
+                               TAILQ_REMOVE(&asoc->strmin[strmat].uno_inqueue, 
control, next_instrm);
+                               control->on_strm_q = 0;
+                               if (control->data) {
+                                       sctp_m_freem(control->data);
+                                       control->data = NULL;
                                }
-                               sctp_free_remote_addr(ctl->whoFrom);
+                               sctp_free_remote_addr(control->whoFrom);
                                /* Now its reasm? */
-                               TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, 
nchk) {
+                               TAILQ_FOREACH_SAFE(chk, &control->reasm, 
sctp_next, nchk) {
                                        cnt++;
                                        SCTP_CALC_TSN_TO_GAP(gap, 
chk->rec.data.tsn, asoc->mapping_array_base_tsn);
-                                       asoc->size_on_reasm_queue = 
sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size);
+                                       KASSERT(chk->send_size > 0, ("chunk has 
zero length"));
+                                       if (asoc->size_on_reasm_queue >= 
chk->send_size) {
+                                               asoc->size_on_reasm_queue -= 
chk->send_size;
+                                       } else {
+#ifdef INVARIANTS
+                                               panic("size_on_reasm_queue = %u 
smaller than chunk length %u", asoc->size_on_reasm_queue, chk->send_size);
+#else
+                                               asoc->size_on_reasm_queue = 0;
+#endif
+                                       }
                                        
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
                                        
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
-                                       TAILQ_REMOVE(&ctl->reasm, chk, 
sctp_next);
+                                       TAILQ_REMOVE(&control->reasm, chk, 
sctp_next);
                                        if (chk->data) {
                                                sctp_m_freem(chk->data);
                                                chk->data = NULL;
                                        }
                                        sctp_free_a_chunk(stcb, chk, 
SCTP_SO_NOT_LOCKED);
                                }
-                               sctp_free_a_readq(stcb, ctl);
+                               sctp_free_a_readq(stcb, control);
                        }
                }
        }

Modified: stable/11/sys/netinet/sctputil.c
==============================================================================
--- stable/11/sys/netinet/sctputil.c    Sat Apr  7 14:40:09 2018        
(r332170)
+++ stable/11/sys/netinet/sctputil.c    Sat Apr  7 14:40:21 2018        
(r332171)
@@ -2754,9 +2754,9 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_t
                    m_notify);
                if (control != NULL) {
                        control->length = SCTP_BUF_LEN(m_notify);
+                       control->spec_flags = M_NOTIFICATION;
                        /* not that we need this */
                        control->tail_mbuf = m_notify;
-                       control->spec_flags = M_NOTIFICATION;
                        sctp_add_to_readq(stcb->sctp_ep, stcb,
                            control,
                            &stcb->sctp_socket->so_rcv, 1, 
SCTP_READ_LOCK_NOT_HELD,
@@ -3038,7 +3038,10 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t
                sctp_m_freem(m_notify);
                return;
        }
+       control->length = SCTP_BUF_LEN(m_notify);
        control->spec_flags = M_NOTIFICATION;
+       /* not that we need this */
+       control->tail_mbuf = m_notify;
        sctp_add_to_readq(stcb->sctp_ep, stcb,
            control,
            &stcb->sctp_socket->so_rcv, 1,
@@ -3138,7 +3141,10 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32
                sctp_m_freem(m_notify);
                return;
        }
+       control->length = SCTP_BUF_LEN(m_notify);
        control->spec_flags = M_NOTIFICATION;
+       /* not that we need this */
+       control->tail_mbuf = m_notify;
        sctp_add_to_readq(stcb->sctp_ep, stcb,
            control,
            &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
@@ -3239,12 +3245,10 @@ sctp_notify_partial_delivery_indication(struct sctp_tc
                sctp_m_freem(m_notify);
                return;
        }
-       control->spec_flags = M_NOTIFICATION;
        control->length = SCTP_BUF_LEN(m_notify);
+       control->spec_flags = M_NOTIFICATION;
        /* not that we need this */
        control->tail_mbuf = m_notify;
-       control->held_length = 0;
-       control->length = 0;
        sb = &stcb->sctp_socket->so_rcv;
        if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
                sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, 
SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify));
@@ -3253,7 +3257,6 @@ sctp_notify_partial_delivery_indication(struct sctp_tc
        if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
                sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, 
SCTP_LOG_SBRESULT, 0);
        }
-       atomic_add_int(&control->length, SCTP_BUF_LEN(m_notify));
        control->end_added = 1;
        if (stcb->asoc.control_pdapi)
                TAILQ_INSERT_AFTER(&stcb->sctp_ep->read_queue, 
stcb->asoc.control_pdapi, control, next);
@@ -3348,8 +3351,8 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
                sctp_m_freem(m_notify);
                return;
        }
-       control->spec_flags = M_NOTIFICATION;
        control->length = SCTP_BUF_LEN(m_notify);
+       control->spec_flags = M_NOTIFICATION;
        /* not that we need this */
        control->tail_mbuf = m_notify;
        sctp_add_to_readq(stcb->sctp_ep, stcb,
@@ -3455,8 +3458,8 @@ sctp_notify_stream_reset_add(struct sctp_tcb *stcb, ui
                sctp_m_freem(m_notify);
                return;
        }
-       control->spec_flags = M_NOTIFICATION;
        control->length = SCTP_BUF_LEN(m_notify);
+       control->spec_flags = M_NOTIFICATION;
        /* not that we need this */
        control->tail_mbuf = m_notify;
        sctp_add_to_readq(stcb->sctp_ep, stcb,
@@ -3505,8 +3508,8 @@ sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, ui
                sctp_m_freem(m_notify);
                return;
        }
-       control->spec_flags = M_NOTIFICATION;
        control->length = SCTP_BUF_LEN(m_notify);
+       control->spec_flags = M_NOTIFICATION;
        /* not that we need this */
        control->tail_mbuf = m_notify;
        sctp_add_to_readq(stcb->sctp_ep, stcb,
@@ -3570,8 +3573,8 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
                sctp_m_freem(m_notify);
                return;
        }
-       control->spec_flags = M_NOTIFICATION;
        control->length = SCTP_BUF_LEN(m_notify);
+       control->spec_flags = M_NOTIFICATION;
        /* not that we need this */
        control->tail_mbuf = m_notify;
        sctp_add_to_readq(stcb->sctp_ep, stcb,
@@ -3626,9 +3629,9 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16
            m_notify);
        if (control != NULL) {
                control->length = SCTP_BUF_LEN(m_notify);
+               control->spec_flags = M_NOTIFICATION;
                /* not that we need this */
                control->tail_mbuf = m_notify;
-               control->spec_flags = M_NOTIFICATION;
                sctp_add_to_readq(stcb->sctp_ep, stcb,
                    control,
                    &stcb->sctp_socket->so_rcv, 1,
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to