Author: tuexen
Date: Sat May 12 20:11:35 2012
New Revision: 235360
URL: http://svn.freebsd.org/changeset/base/235360

Log:
  Provide in the association change notification the received ABORT chunk
  if case of SCTP_COMM_LOST or SCTP_CANT_STR_ASSOC as required by RFC 6458.
  
  MFC after: 3 days

Modified:
  head/sys/netinet/sctp_asconf.c
  head/sys/netinet/sctp_indata.c
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_output.c
  head/sys/netinet/sctp_pcb.c
  head/sys/netinet/sctp_timer.c
  head/sys/netinet/sctp_usrreq.c
  head/sys/netinet/sctputil.c
  head/sys/netinet/sctputil.h
  head/sys/netinet6/sctp6_usrreq.c

Modified: head/sys/netinet/sctp_asconf.c
==============================================================================
--- head/sys/netinet/sctp_asconf.c      Sat May 12 20:10:18 2012        
(r235359)
+++ head/sys/netinet/sctp_asconf.c      Sat May 12 20:11:35 2012        
(r235360)
@@ -1789,8 +1789,7 @@ sctp_handle_asconf_ack(struct mbuf *m, i
         */
        if (serial_num == (asoc->asconf_seq_out + 1)) {
                SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected 
next serial number! Aborting asoc!\n");
-               sctp_abort_an_association(stcb->sctp_ep, stcb,
-                   SCTP_CAUSE_ILLEGAL_ASCONF_ACK, NULL, SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, 
SCTP_SO_NOT_LOCKED);
                *abort_no_unlock = 1;
                return;
        }

Modified: head/sys/netinet/sctp_indata.c
==============================================================================
--- head/sys/netinet/sctp_indata.c      Sat May 12 20:10:18 2012        
(r235359)
+++ head/sys/netinet/sctp_indata.c      Sat May 12 20:11:35 2012        
(r235360)
@@ -607,9 +607,7 @@ protocol_error:
                        *ippp = ((control->sinfo_stream << 16) | 
control->sinfo_ssn);
                }
                stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_1;
-               sctp_abort_an_association(stcb->sctp_ep, stcb,
-                   SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+               sctp_abort_an_association(stcb->sctp_ep, stcb, oper, 
SCTP_SO_NOT_LOCKED);
                *abort_flag = 1;
                return;
 
@@ -892,8 +890,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
 
                                }
                                stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_2;
-                               sctp_abort_an_association(stcb->sctp_ep, stcb,
-                                   SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+                               sctp_abort_an_association(stcb->sctp_ep, stcb, 
oper, SCTP_SO_NOT_LOCKED);
                                *abort_flag = 1;
                        } else if (asoc->fragmented_delivery_inprogress &&
                            (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == 
SCTP_DATA_FIRST_FRAG) {
@@ -924,8 +921,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
                                        *ippp = ((chk->rec.data.stream_number 
<< 16) | chk->rec.data.stream_seq);
                                }
                                stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_3;
-                               sctp_abort_an_association(stcb->sctp_ep, stcb,
-                                   SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+                               sctp_abort_an_association(stcb->sctp_ep, stcb, 
oper, SCTP_SO_NOT_LOCKED);
                                *abort_flag = 1;
                        } else if (asoc->fragmented_delivery_inprogress) {
                                /*
@@ -961,8 +957,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
                                                *ippp = 
((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_4;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                } else if ((asoc->fragment_flags & 
SCTP_DATA_UNORDERED) !=
                                            SCTP_DATA_UNORDERED &&
@@ -995,8 +990,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
 
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_5;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                }
                        }
@@ -1090,8 +1084,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
 
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_6;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                        return;
                                }
@@ -1127,9 +1120,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
                                                *ippp = 
((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_7;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
-
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                        return;
                                }
@@ -1166,9 +1157,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
                                                *ippp = 
((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_8;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
-
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                        return;
                                }
@@ -1202,9 +1191,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
 
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_9;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
-
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                        return;
                                }
@@ -1247,9 +1234,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
                                                *ippp = 
((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_10;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
-
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                        return;
                                }
@@ -1289,9 +1274,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
 
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_11;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
-
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                        return;
                                }
@@ -1328,9 +1311,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
 
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_12;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
-
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                        return;
                                }
@@ -1367,9 +1348,7 @@ sctp_queue_data_for_reasm(struct sctp_tc
                                                *ippp = 
((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq);
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_13;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
-
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                        return;
                                }
@@ -1531,7 +1510,7 @@ sctp_process_a_data_chunk(struct sctp_tc
                struct mbuf *op_err;
 
                op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
-               sctp_abort_an_association(stcb->sctp_ep, stcb, 0, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
                *abort_flag = 1;
                return (0);
        }
@@ -1678,8 +1657,7 @@ sctp_process_a_data_chunk(struct sctp_tc
 
                }
                stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_14;
-               sctp_abort_an_association(stcb->sctp_ep, stcb,
-                   SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, oper, 
SCTP_SO_NOT_LOCKED);
                *abort_flag = 1;
                return (0);
        }
@@ -1942,9 +1920,7 @@ failed_pdapi_express_del:
                                        *ippp = ((strmno << 16) | strmseq);
                                }
                                stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_15;
-                               sctp_abort_an_association(stcb->sctp_ep, stcb,
-                                   SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
-
+                               sctp_abort_an_association(stcb->sctp_ep, stcb, 
oper, SCTP_SO_NOT_LOCKED);
                                *abort_flag = 1;
                                return (0);
                        } else {
@@ -1980,9 +1956,7 @@ failed_pdapi_express_del:
                                                *ippp = ((strmno << 16) | 
strmseq);
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_16;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
-
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                        return (0);
                                }
@@ -2027,9 +2001,7 @@ failed_pdapi_express_del:
                                                *ippp = ((strmno << 16) | 
strmseq);
                                        }
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_17;
-                                       sctp_abort_an_association(stcb->sctp_ep,
-                                           stcb, SCTP_PEER_FAULTY, oper, 
SCTP_SO_NOT_LOCKED);
-
+                                       
sctp_abort_an_association(stcb->sctp_ep, stcb, oper, SCTP_SO_NOT_LOCKED);
                                        *abort_flag = 1;
                                        return (0);
                                }
@@ -3878,7 +3850,7 @@ sctp_express_handle_sack(struct sctp_tcb
                                *ippp = htonl(SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_25);
                        }
                        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA 
+ SCTP_LOC_25;
-                       sctp_abort_an_association(stcb->sctp_ep, stcb, 
SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(stcb->sctp_ep, stcb, oper, 
SCTP_SO_NOT_LOCKED);
                        return;
 #endif
                }
@@ -4240,7 +4212,7 @@ again:
                                        *ippp = htonl(SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_24);
                                }
                                stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
-                               sctp_abort_an_association(stcb->sctp_ep, stcb, 
SCTP_RESPONSE_TO_USER_REQ, oper, SCTP_SO_NOT_LOCKED);
+                               sctp_abort_an_association(stcb->sctp_ep, stcb, 
oper, SCTP_SO_NOT_LOCKED);
                        } else {
                                struct sctp_nets *netp;
 
@@ -4463,7 +4435,7 @@ sctp_handle_sack(struct mbuf *m, int off
                                *ippp = htonl(SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_25);
                        }
                        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA 
+ SCTP_LOC_25;
-                       sctp_abort_an_association(stcb->sctp_ep, stcb, 
SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(stcb->sctp_ep, stcb, oper, 
SCTP_SO_NOT_LOCKED);
                        return;
                }
        }
@@ -4966,7 +4938,7 @@ sctp_handle_sack(struct mbuf *m, int off
                                        *ippp = htonl(SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_31);
                                }
                                stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_31;
-                               sctp_abort_an_association(stcb->sctp_ep, stcb, 
SCTP_RESPONSE_TO_USER_REQ, oper, SCTP_SO_NOT_LOCKED);
+                               sctp_abort_an_association(stcb->sctp_ep, stcb, 
oper, SCTP_SO_NOT_LOCKED);
                                return;
                        } else {
                                struct sctp_nets *netp;
@@ -5421,8 +5393,7 @@ sctp_handle_forward_tsn(struct sctp_tcb 
                                *ippp = new_cum_tsn;
                        }
                        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA 
+ SCTP_LOC_33;
-                       sctp_abort_an_association(stcb->sctp_ep, stcb,
-                           SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(stcb->sctp_ep, stcb, oper, 
SCTP_SO_NOT_LOCKED);
                        return;
                }
                SCTP_STAT_INCR(sctps_fwdtsn_map_over);

Modified: head/sys/netinet/sctp_input.c
==============================================================================
--- head/sys/netinet/sctp_input.c       Sat May 12 20:10:18 2012        
(r235359)
+++ head/sys/netinet/sctp_input.c       Sat May 12 20:11:35 2012        
(r235360)
@@ -428,7 +428,7 @@ sctp_process_init_ack(struct mbuf *m, in
            &abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly);
        if (abort_flag) {
                /* Send an abort and notify peer */
-               sctp_abort_an_association(stcb->sctp_ep, stcb, 
SCTP_CAUSE_PROTOCOL_VIOLATION, op_err, SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
                *abort_no_unlock = 1;
                return (-1);
        }
@@ -739,7 +739,7 @@ sctp_handle_nat_missing_state(struct sct
 
 
 static void
-sctp_handle_abort(struct sctp_abort_chunk *cp,
+sctp_handle_abort(struct sctp_abort_chunk *abort,
     struct sctp_tcb *stcb, struct sctp_nets *net)
 {
 #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -747,43 +747,42 @@ sctp_handle_abort(struct sctp_abort_chun
 
 #endif
        uint16_t len;
+       uint16_t error;
 
        SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n");
        if (stcb == NULL)
                return;
 
-       len = ntohs(cp->ch.chunk_length);
+       len = ntohs(abort->ch.chunk_length);
        if (len > sizeof(struct sctp_chunkhdr)) {
                /*
                 * Need to check the cause codes for our two magic nat
                 * aborts which don't kill the assoc necessarily.
                 */
-               struct sctp_abort_chunk *cpnext;
                struct sctp_missing_nat_state *natc;
-               uint16_t cause;
 
-               cpnext = cp;
-               cpnext++;
-               natc = (struct sctp_missing_nat_state *)cpnext;
-               cause = ntohs(natc->cause);
-               if (cause == SCTP_CAUSE_NAT_COLLIDING_STATE) {
+               natc = (struct sctp_missing_nat_state *)(abort + 1);
+               error = ntohs(natc->cause);
+               if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) {
                        SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state 
abort flags:%x\n",
-                           cp->ch.chunk_flags);
+                           abort->ch.chunk_flags);
                        if (sctp_handle_nat_colliding_state(stcb)) {
                                return;
                        }
-               } else if (cause == SCTP_CAUSE_NAT_MISSING_STATE) {
+               } else if (error == SCTP_CAUSE_NAT_MISSING_STATE) {
                        SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state 
abort flags:%x\n",
-                           cp->ch.chunk_flags);
+                           abort->ch.chunk_flags);
                        if (sctp_handle_nat_missing_state(stcb, net)) {
                                return;
                        }
                }
+       } else {
+               error = 0;
        }
        /* stop any receive timers */
        sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, 
SCTP_FROM_SCTP_INPUT + SCTP_LOC_6);
        /* notify user of the abort and clean up... */
-       sctp_abort_notification(stcb, 0, SCTP_SO_NOT_LOCKED);
+       sctp_abort_notification(stcb, error, abort, SCTP_SO_NOT_LOCKED);
        /* free the tcb */
        SCTP_STAT_INCR_COUNTER32(sctps_aborted);
        if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
@@ -1174,7 +1173,7 @@ sctp_handle_error(struct sctp_chunkhdr *
                                asoc->stale_cookie_count++;
                                if (asoc->stale_cookie_count >
                                    asoc->max_init_times) {
-                                       sctp_abort_notification(stcb, 0, 
SCTP_SO_NOT_LOCKED);
+                                       sctp_abort_notification(stcb, 0, NULL, 
SCTP_SO_NOT_LOCKED);
                                        /* now free the asoc */
 #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
                                        so = SCTP_INP_SO(stcb->sctp_ep);

Modified: head/sys/netinet/sctp_output.c
==============================================================================
--- head/sys/netinet/sctp_output.c      Sat May 12 20:10:18 2012        
(r235359)
+++ head/sys/netinet/sctp_output.c      Sat May 12 20:11:35 2012        
(r235360)
@@ -6573,9 +6573,7 @@ sctp_sendall_iterator(struct sctp_inpcb 
                         * dis-appearing on us.
                         */
                        atomic_add_int(&stcb->asoc.refcnt, 1);
-                       sctp_abort_an_association(inp, stcb,
-                           SCTP_RESPONSE_TO_USER_REQ,
-                           m, SCTP_SO_NOT_LOCKED);
+                       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
@@ -6669,7 +6667,6 @@ sctp_sendall_iterator(struct sctp_inpcb 
                                abort_anyway:
                                                
atomic_add_int(&stcb->asoc.refcnt, 1);
                                                
sctp_abort_an_association(stcb->sctp_ep, stcb,
-                                                   SCTP_RESPONSE_TO_USER_REQ,
                                                    NULL, SCTP_SO_NOT_LOCKED);
                                                
atomic_add_int(&stcb->asoc.refcnt, -1);
                                                goto no_chunk_output;
@@ -9504,7 +9501,7 @@ sctp_chunk_retransmission(struct sctp_in
                            chk->snd_count,
                            SCTP_BASE_SYSCTL(sctp_max_retran_chunk));
                        atomic_add_int(&stcb->asoc.refcnt, 1);
-                       sctp_abort_an_association(stcb->sctp_ep, stcb, 0, NULL, 
so_locked);
+                       sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, 
so_locked);
                        SCTP_TCB_LOCK(stcb);
                        atomic_subtract_int(&stcb->asoc.refcnt, 1);
                        return (SCTP_RETRAN_EXIT);
@@ -13138,9 +13135,7 @@ sctp_lower_sosend(struct socket *so,
                atomic_add_int(&stcb->asoc.refcnt, -1);
                free_cnt_applied = 0;
                /* release this lock, otherwise we hang on ourselves */
-               sctp_abort_an_association(stcb->sctp_ep, stcb,
-                   SCTP_RESPONSE_TO_USER_REQ,
-                   mm, SCTP_SO_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, mm, 
SCTP_SO_LOCKED);
                /* now relock the stcb so everything is sane */
                hold_tcblock = 0;
                stcb = NULL;
@@ -13695,7 +13690,6 @@ dataless_eof:
                                                free_cnt_applied = 0;
                                        }
                                        
sctp_abort_an_association(stcb->sctp_ep, stcb,
-                                           SCTP_RESPONSE_TO_USER_REQ,
                                            NULL, SCTP_SO_LOCKED);
                                        /*
                                         * now relock the stcb so everything

Modified: head/sys/netinet/sctp_pcb.c
==============================================================================
--- head/sys/netinet/sctp_pcb.c Sat May 12 20:10:18 2012        (r235359)
+++ head/sys/netinet/sctp_pcb.c Sat May 12 20:11:35 2012        (r235360)
@@ -6347,7 +6347,7 @@ sctp_load_addresses_from_init(struct sct
                                                         * abort this guy
                                                         */
                                                        
sctp_abort_an_association(stcb_tmp->sctp_ep,
-                                                           stcb_tmp, 1, NULL, 
0);
+                                                           stcb_tmp, NULL, 
SCTP_SO_NOT_LOCKED);
                                                        goto add_it_now;
                                                }
                                                SCTP_TCB_UNLOCK(stcb_tmp);
@@ -6438,7 +6438,7 @@ sctp_load_addresses_from_init(struct sct
                                                         * abort this guy
                                                         */
                                                        
sctp_abort_an_association(stcb_tmp->sctp_ep,
-                                                           stcb_tmp, 1, NULL, 
0);
+                                                           stcb_tmp, NULL, 
SCTP_SO_NOT_LOCKED);
                                                        goto add_it_now6;
                                                }
                                        SCTP_TCB_UNLOCK(stcb_tmp);

Modified: head/sys/netinet/sctp_timer.c
==============================================================================
--- head/sys/netinet/sctp_timer.c       Sat May 12 20:10:18 2012        
(r235359)
+++ head/sys/netinet/sctp_timer.c       Sat May 12 20:11:35 2012        
(r235360)
@@ -167,7 +167,7 @@ sctp_threshold_management(struct sctp_in
                        *ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_1);
                }
                inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_1;
-               sctp_abort_an_association(inp, stcb, SCTP_FAILED_THRESHOLD, 
oper, SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(inp, stcb, oper, SCTP_SO_NOT_LOCKED);
                return (1);
        }
        return (0);
@@ -1066,8 +1066,7 @@ sctp_cookie_timer(struct sctp_inpcb *inp
                                *ippp = htonl(SCTP_FROM_SCTP_TIMER + 
SCTP_LOC_3);
                        }
                        inp->last_abort_code = SCTP_FROM_SCTP_TIMER + 
SCTP_LOC_4;
-                       sctp_abort_an_association(inp, stcb, 
SCTP_INTERNAL_ERROR,
-                           oper, SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(inp, stcb, oper, 
SCTP_SO_NOT_LOCKED);
                } else {
 #ifdef INVARIANTS
                        panic("Cookie timer expires in wrong state?");

Modified: head/sys/netinet/sctp_usrreq.c
==============================================================================
--- head/sys/netinet/sctp_usrreq.c      Sat May 12 20:10:18 2012        
(r235359)
+++ head/sys/netinet/sctp_usrreq.c      Sat May 12 20:11:35 2012        
(r235360)
@@ -229,11 +229,9 @@ sctp_notify(struct sctp_inpcb *inp,
        struct socket *so;
 
 #endif
-       /* protection */
-       int reason;
        struct icmp *icmph;
 
-
+       /* protection */
        if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
            (sh == NULL) || (to == NULL)) {
                if (stcb)
@@ -285,8 +283,7 @@ sctp_notify(struct sctp_inpcb *inp,
                 * now is dead. In either case treat it like a OOTB abort
                 * with no TCB
                 */
-               reason = SCTP_PEER_FAULTY;
-               sctp_abort_notification(stcb, reason, SCTP_SO_NOT_LOCKED);
+               sctp_abort_notification(stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
 #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
                so = SCTP_INP_SO(inp);
                atomic_add_int(&stcb->asoc.refcnt, 1);
@@ -1098,7 +1095,6 @@ sctp_shutdown(struct socket *so)
                                }
                                stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
                                sctp_abort_an_association(stcb->sctp_ep, stcb,
-                                   SCTP_RESPONSE_TO_USER_REQ,
                                    op_err, SCTP_SO_LOCKED);
                                goto skip_unlock;
                        } else {

Modified: head/sys/netinet/sctputil.c
==============================================================================
--- head/sys/netinet/sctputil.c Sat May 12 20:10:18 2012        (r235359)
+++ head/sys/netinet/sctputil.c Sat May 12 20:11:35 2012        (r235360)
@@ -1725,8 +1725,7 @@ sctp_timeout_handler(void *t)
                        break;
                }
                SCTP_STAT_INCR(sctps_timoshutdownguard);
-               sctp_abort_an_association(inp, stcb,
-                   SCTP_SHUTDOWN_GUARD_EXPIRES, NULL, SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED);
                /* no need to unlock on tcb its gone */
                goto out_decr;
 
@@ -2593,7 +2592,7 @@ sctp_pad_lastmbuf(struct mbuf *m, int pa
 
 static void
 sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
-    uint16_t error, int so_locked
+    uint16_t error, struct sctp_abort_chunk *abort, int so_locked
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
 #endif
@@ -2602,7 +2601,7 @@ sctp_notify_assoc_change(uint16_t state,
        struct mbuf *m_notify;
        struct sctp_assoc_change *sac;
        struct sctp_queued_to_read *control;
-       size_t len;
+       size_t notif_len, abort_len;
        unsigned int i;
 
 #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -2652,16 +2651,27 @@ sctp_notify_assoc_change(uint16_t state,
                /* event not enabled */
                return;
        }
-       len = sizeof(struct sctp_assoc_change);
+       notif_len = sizeof(struct sctp_assoc_change);
+       if (abort != NULL) {
+               abort_len = htons(abort->ch.chunk_length);
+       } else {
+               abort_len = 0;
+       }
        if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
-               len += SCTP_ASSOC_SUPPORTS_MAX;
+               notif_len += SCTP_ASSOC_SUPPORTS_MAX;
+       } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) 
{
+               notif_len += abort_len;
        }
-       m_notify = sctp_get_mbuf_for_msg(len, 0, M_DONTWAIT, 1, MT_DATA);
-       if (m_notify == NULL)
-               /* no space left */
-               return;
-       SCTP_BUF_LEN(m_notify) = 0;
-
+       m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA);
+       if (m_notify == NULL) {
+               /* Retry with smaller value. */
+               notif_len = sizeof(struct sctp_assoc_change);
+               m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, 
MT_DATA);
+               if (m_notify == NULL) {
+                       return;
+               }
+       }
+       SCTP_BUF_NEXT(m_notify) = NULL;
        sac = mtod(m_notify, struct sctp_assoc_change *);
        sac->sac_type = SCTP_ASSOC_CHANGE;
        sac->sac_flags = 0;
@@ -2672,25 +2682,29 @@ sctp_notify_assoc_change(uint16_t state,
        sac->sac_outbound_streams = stcb->asoc.streamoutcnt;
        sac->sac_inbound_streams = stcb->asoc.streamincnt;
        sac->sac_assoc_id = sctp_get_associd(stcb);
-       if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
-               i = 0;
-               if (stcb->asoc.peer_supports_prsctp) {
-                       sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR;
-               }
-               if (stcb->asoc.peer_supports_auth) {
-                       sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH;
+       if (notif_len > sizeof(struct sctp_assoc_change)) {
+               if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
+                       i = 0;
+                       if (stcb->asoc.peer_supports_prsctp) {
+                               sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR;
+                       }
+                       if (stcb->asoc.peer_supports_auth) {
+                               sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH;
+                       }
+                       if (stcb->asoc.peer_supports_asconf) {
+                               sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
+                       }
+                       sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
+                       if (stcb->asoc.peer_supports_strreset) {
+                               sac->sac_info[i++] = 
SCTP_ASSOC_SUPPORTS_RE_CONFIG;
+                       }
+                       sac->sac_length += i;
+               } else if ((state == SCTP_COMM_LOST) || (state == 
SCTP_CANT_STR_ASSOC)) {
+                       memcpy(sac->sac_info, abort, abort_len);
+                       sac->sac_length += abort_len;
                }
-               if (stcb->asoc.peer_supports_asconf) {
-                       sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
-               }
-               sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
-               if (stcb->asoc.peer_supports_strreset) {
-                       sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG;
-               }
-               sac->sac_length += i;
        }
        SCTP_BUF_LEN(m_notify) = sac->sac_length;
-       SCTP_BUF_NEXT(m_notify) = NULL;
        control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
            0, 0, stcb->asoc.context, 0, 0, 0,
            m_notify);
@@ -3500,7 +3514,7 @@ sctp_ulp_notify(uint32_t notification, s
        switch (notification) {
        case SCTP_NOTIFY_ASSOC_UP:
                if (stcb->asoc.assoc_up_sent == 0) {
-                       sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, 
so_locked);
+                       sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, 
NULL, so_locked);
                        stcb->asoc.assoc_up_sent = 1;
                }
                if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent 
== 0)) {
@@ -3512,7 +3526,7 @@ sctp_ulp_notify(uint32_t notification, s
                }
                break;
        case SCTP_NOTIFY_ASSOC_DOWN:
-               sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, 
so_locked);
+               sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 
so_locked);
                break;
        case SCTP_NOTIFY_INTERFACE_DOWN:
                {
@@ -3563,9 +3577,9 @@ sctp_ulp_notify(uint32_t notification, s
        case SCTP_NOTIFY_ASSOC_ABORTED:
                if ((stcb) && (((stcb->asoc.state & SCTP_STATE_MASK) == 
SCTP_STATE_COOKIE_WAIT) ||
                    ((stcb->asoc.state & SCTP_STATE_MASK) == 
SCTP_STATE_COOKIE_ECHOED))) {
-                       sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, 
error, so_locked);
+                       sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, 
error, data, so_locked);
                } else {
-                       sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, 
so_locked);
+                       sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, 
data, so_locked);
                }
                break;
        case SCTP_NOTIFY_PEER_OPENED_STREAM:
@@ -3573,7 +3587,7 @@ sctp_ulp_notify(uint32_t notification, s
        case SCTP_NOTIFY_STREAM_OPENED_OK:
                break;
        case SCTP_NOTIFY_ASSOC_RESTART:
-               sctp_notify_assoc_change(SCTP_RESTART, stcb, error, so_locked);
+               sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 
so_locked);
                if (stcb->asoc.peer_supports_auth == 0) {
                        sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
                            NULL, so_locked);
@@ -3742,7 +3756,8 @@ sctp_report_all_outbound(struct sctp_tcb
 }
 
 void
-sctp_abort_notification(struct sctp_tcb *stcb, int error, int so_locked
+sctp_abort_notification(struct sctp_tcb *stcb, uint16_t error,
+    struct sctp_abort_chunk *abort, int so_locked
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
 #endif
@@ -3763,7 +3778,7 @@ sctp_abort_notification(struct sctp_tcb 
        }
        /* Tell them we lost the asoc */
        sctp_report_all_outbound(stcb, 1, so_locked);
-       sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL, 
so_locked);
+       sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, abort, 
so_locked);
 }
 
 void
@@ -3782,7 +3797,7 @@ sctp_abort_association(struct sctp_inpcb
        if (stcb != NULL) {
                /* We have a TCB to abort, send notification too */
                vtag = stcb->asoc.peer_vtag;
-               sctp_abort_notification(stcb, 0, SCTP_SO_NOT_LOCKED);
+               sctp_abort_notification(stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
                /* get the assoc vrf id and table id */
                vrf_id = stcb->asoc.vrf_id;
                stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
@@ -3876,7 +3891,7 @@ none_in:
 
 void
 sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
-    int error, struct mbuf *op_err,
+    struct mbuf *op_err,
     int so_locked
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
@@ -3904,8 +3919,9 @@ sctp_abort_an_association(struct sctp_in
                stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
        }
        /* notify the ulp */
-       if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)
-               sctp_abort_notification(stcb, error, so_locked);
+       if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
+               sctp_abort_notification(stcb, 0, NULL, so_locked);
+       }
        /* notify the peer */
        sctp_send_abort_tcb(stcb, op_err, so_locked);
        SCTP_STAT_INCR_COUNTER32(sctps_aborted);

Modified: head/sys/netinet/sctputil.h
==============================================================================
--- head/sys/netinet/sctputil.h Sat May 12 20:10:18 2012        (r235359)
+++ head/sys/netinet/sctputil.h Sat May 12 20:11:35 2012        (r235360)
@@ -179,7 +179,8 @@ sctp_report_all_outbound(struct sctp_tcb
 int sctp_expand_mapping_array(struct sctp_association *, uint32_t);
 
 void 
-sctp_abort_notification(struct sctp_tcb *, int, int
+sctp_abort_notification(struct sctp_tcb *, uint16_t,
+    struct sctp_abort_chunk *, int
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED
 #endif
@@ -193,7 +194,7 @@ sctp_abort_association(struct sctp_inpcb
 
 /* We choose to abort via user input */
 void
-sctp_abort_an_association(struct sctp_inpcb *, struct sctp_tcb *, int,
+sctp_abort_an_association(struct sctp_inpcb *, struct sctp_tcb *,
     struct mbuf *, int
 #if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
     SCTP_UNUSED

Modified: head/sys/netinet6/sctp6_usrreq.c
==============================================================================
--- head/sys/netinet6/sctp6_usrreq.c    Sat May 12 20:10:18 2012        
(r235359)
+++ head/sys/netinet6/sctp6_usrreq.c    Sat May 12 20:11:35 2012        
(r235360)
@@ -388,10 +388,8 @@ sctp6_notify(struct sctp_inpcb *inp,
        struct socket *so;
 
 #endif
-       /* protection */
-       int reason;
-
 
+       /* protection */
        if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
            (sh == NULL) || (to == NULL)) {
                if (stcb)
@@ -441,8 +439,7 @@ sctp6_notify(struct sctp_inpcb *inp,
                 * now is dead. In either case treat it like a OOTB abort
                 * with no TCB
                 */
-               reason = SCTP_PEER_FAULTY;
-               sctp_abort_notification(stcb, reason, SCTP_SO_NOT_LOCKED);
+               sctp_abort_notification(stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
 #if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
                so = SCTP_INP_SO(inp);
                atomic_add_int(&stcb->asoc.refcnt, 1);
_______________________________________________
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