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
This commit is contained in:
Michael Tuexen 2012-05-12 20:11:35 +00:00
parent 13a0b7bcc4
commit a2b42326b5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=235360
10 changed files with 108 additions and 136 deletions

View File

@ -1789,8 +1789,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
*/
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;
}

View File

@ -607,9 +607,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc,
*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_tcb *stcb, struct sctp_association *asoc,
}
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_tcb *stcb, struct sctp_association *asoc,
*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_tcb *stcb, struct sctp_association *asoc,
*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_tcb *stcb, struct sctp_association *asoc,
}
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_tcb *stcb, struct sctp_association *asoc,
}
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_tcb *stcb, struct sctp_association *asoc,
*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_tcb *stcb, struct sctp_association *asoc,
*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_tcb *stcb, struct sctp_association *asoc,
}
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_tcb *stcb, struct sctp_association *asoc,
*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_tcb *stcb, struct sctp_association *asoc,
}
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_tcb *stcb, struct sctp_association *asoc,
}
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_tcb *stcb, struct sctp_association *asoc,
*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_tcb *stcb, struct sctp_association *asoc,
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_tcb *stcb, struct sctp_association *asoc,
}
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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
*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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
*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 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
*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 *stcb, uint32_t cumack,
*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 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
*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 offset_seg, int offset_dup,
*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 offset_seg, int offset_dup,
*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 *stcb,
*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);

View File

@ -428,7 +428,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
&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 sctp_tcb *stcb,
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_chunk *cp,
#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 *ch,
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);

View File

@ -6573,9 +6573,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
* 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 *inp, struct sctp_tcb *stcb, void *ptr,
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_inpcb *inp,
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 @@ sctp_lower_sosend(struct socket *so,
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

View File

@ -6347,7 +6347,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* 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 sctp_tcb *stcb, struct mbuf *m,
* 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);

View File

@ -167,7 +167,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
*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?");

View File

@ -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 {

View File

@ -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 padval, struct mbuf *last_mbuf)
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 sctp_tcb *stcb,
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, struct sctp_tcb *stcb,
/* event not enabled */
return;
}
len = sizeof(struct sctp_assoc_change);
if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
len += SCTP_ASSOC_SUPPORTS_MAX;
notif_len = sizeof(struct sctp_assoc_change);
if (abort != NULL) {
abort_len = htons(abort->ch.chunk_length);
} else {
abort_len = 0;
}
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;
if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
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(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, struct sctp_tcb *stcb,
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 (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_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;
}
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, struct sctp_tcb *stcb,
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, struct sctp_tcb *stcb,
}
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, struct sctp_tcb *stcb,
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, struct sctp_tcb *stcb,
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 *stcb, int holds_lock, int so_locked
}
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 *stcb, int error, int so_locked
}
/* 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 *inp, struct sctp_tcb *stcb,
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 @@ sctp_print_out_track_log(struct sctp_tcb *stcb)
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_inpcb *inp, struct sctp_tcb *stcb,
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);

View File

@ -179,7 +179,8 @@ sctp_report_all_outbound(struct sctp_tcb *, int, int
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 *, struct sctp_tcb *,
/* 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

View File

@ -388,10 +388,8 @@ sctp6_notify(struct sctp_inpcb *inp,
struct socket *so;
#endif
/* protection */
int reason;
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);