- Locking compatiability changes. This involves adding

additional flags to many function calls. The flags only
  get used in BSD when we compile with lock testing. These
  flags allow apple to escape the "giant" lock it holds on
  the socket and have more fine-grained locking in the NKE.
  It also allows us to test (with witness) the locking used
  by apple via a compile switch (manually applied).

Approved by:	re@freebsd.org(B Mah)
This commit is contained in:
Randall Stewart 2007-09-08 11:35:11 +00:00
parent fadab45370
commit ceaad40ae7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=172090
18 changed files with 925 additions and 255 deletions

View File

@ -280,7 +280,7 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
aparam_length);
} else {
/* notify upper layer */
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa);
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
if (response_required) {
m_reply =
sctp_asconf_success_response(aph->correlation_id);
@ -316,7 +316,7 @@ sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src)
(struct sockaddr *)&net->ro._l_addr);
/* notify upper layer */
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0,
(struct sockaddr *)&net->ro._l_addr);
(struct sockaddr *)&net->ro._l_addr, SCTP_SO_NOT_LOCKED);
}
}
return 0;
@ -451,7 +451,7 @@ sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
m_reply = sctp_asconf_success_response(aph->correlation_id);
}
/* notify upper layer */
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa);
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
}
return m_reply;
}
@ -545,7 +545,7 @@ sctp_process_asconf_set_primary(struct mbuf *m,
SCTPDBG(SCTP_DEBUG_ASCONF1,
"process_asconf_set_primary: primary address set\n");
/* notify upper layer */
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa);
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
if (response_required) {
m_reply = sctp_asconf_success_response(aph->correlation_id);
@ -1592,7 +1592,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_CAUSE_ILLEGAL_ASCONF_ACK, NULL, SCTP_SO_NOT_LOCKED);
return;
}
if (serial_num != asoc->asconf_seq_out) {
@ -2199,7 +2199,7 @@ sctp_set_primary_ip_address(struct sctp_ifa *ifa)
if (!sctp_asconf_queue_add(stcb, ifa,
SCTP_SET_PRIM_ADDR)) {
/* set primary queuing succeeded */
SCTPDBG(SCTP_DEBUG_ASCONF1, ": queued on stcb=%p, ",
SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
stcb);
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {

View File

@ -1843,7 +1843,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
/* 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);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
}

View File

@ -321,7 +321,6 @@ sctp_addr_change(struct ifaddr *ifa, int cmd)
ifa->ifa_ifp->if_index, ifa->ifa_ifp->if_type,
ifa->ifa_ifp->if_xname,
(void *)ifa, ifa->ifa_addr, ifa_flags, 1);
} else if (cmd == RTM_DELETE) {
sctp_del_addr_from_vrf(SCTP_DEFAULT_VRFID, ifa->ifa_addr, ifa->ifa_ifp->if_index);

View File

@ -221,7 +221,7 @@ sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
net->dest_state |= SCTP_ADDR_REACHABLE;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
SCTP_RECEIVED_SACK, (void *)net);
SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
/* now was it the primary? if so restore */
if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
(void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
@ -710,7 +710,7 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
net->dest_state |= SCTP_ADDR_REACHABLE;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
SCTP_RECEIVED_SACK, (void *)net);
SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
/* now was it the primary? if so restore */
if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
(void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
@ -1011,7 +1011,7 @@ sctp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp,
old_cwnd = net->cwnd;
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
/*
* make a small adjustment to cwnd and force to CA.
*/
@ -1405,7 +1405,7 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
net->dest_state |= SCTP_ADDR_REACHABLE;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
SCTP_RECEIVED_SACK, (void *)net);
SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
/* now was it the primary? if so restore */
if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
(void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
@ -1591,7 +1591,7 @@ sctp_htcp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp,
old_cwnd = net->cwnd;
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
net->htcp_ca.last_cong = sctp_get_tick_count();
/*
* make a small adjustment to cwnd and force to CA.

View File

@ -1028,6 +1028,13 @@ __FBSDID("$FreeBSD$");
#define SCTP_DEF_ASOC_RESC_LIMIT 10
#define SCTP_DEF_SYSTEM_RESC_LIMIT 1000
/*-
* defines for socket lock states.
* Used by __APPLE__ and SCTP_SO_LOCK_TESTING
*/
#define SCTP_SO_LOCKED 1
#define SCTP_SO_NOT_LOCKED 0
#define IN4_ISPRIVATE_ADDRESS(a) \
((((uint8_t *)&(a)->s_addr)[0] == 10) || \

View File

@ -432,7 +432,7 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
else
end = 0;
sctp_add_to_readq(stcb->sctp_ep,
stcb, control, &stcb->sctp_socket->so_rcv, end);
stcb, control, &stcb->sctp_socket->so_rcv, end, SCTP_SO_NOT_LOCKED);
cntDel++;
} else {
if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG)
@ -508,7 +508,7 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
strm->last_sequence_delivered++;
sctp_add_to_readq(stcb->sctp_ep, stcb,
ctl,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
ctl = ctlat;
} else {
break;
@ -601,7 +601,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
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_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
@ -618,7 +618,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc,
strm->last_sequence_delivered++;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
control = TAILQ_FIRST(&strm->inqueue);
while (control != NULL) {
/* all delivered */
@ -641,7 +641,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
control = at;
continue;
}
@ -876,7 +876,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_PEER_FAULTY, 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) {
@ -908,7 +908,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_3;
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_PEER_FAULTY, oper);
SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
} else if (asoc->fragmented_delivery_inprogress) {
/*
@ -945,7 +945,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_4;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
} else if ((asoc->fragment_flags & SCTP_DATA_UNORDERED) !=
SCTP_DATA_UNORDERED &&
@ -980,7 +980,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);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
}
}
@ -1078,7 +1078,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);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
}
@ -1115,7 +1115,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_7;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
@ -1154,7 +1154,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_8;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
@ -1190,7 +1190,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);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
@ -1235,7 +1235,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_10;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
@ -1277,7 +1277,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);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
@ -1316,7 +1316,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);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
@ -1355,11 +1355,10 @@ 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_13;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return;
}
}
}
@ -1520,7 +1519,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_abort_an_association(stcb->sctp_ep, stcb, 0, op_err, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return (0);
}
@ -1541,7 +1540,25 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
*/
if (stcb->sctp_socket->so_rcv.sb_cc) {
/* some to read, wake-up */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/* assoc was freed while we were unlocked */
SCTP_SOCKET_UNLOCK(so, 1);
return (0);
}
#endif
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
/* now is it in the mapping array of what we have accepted? */
if (compare_with_wrap(tsn,
@ -1661,7 +1678,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_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return (0);
}
@ -1746,7 +1763,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (control == NULL) {
goto failed_express_del;
}
sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1);
sctp_add_to_readq(stcb->sctp_ep, stcb, control, &stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) {
/* for ordered, bump what we delivered */
asoc->strmin[strmno].last_sequence_delivered++;
@ -1911,7 +1928,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_15;
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_PEER_FAULTY, oper);
SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return (0);
@ -1949,7 +1966,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_16;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return (0);
@ -1996,7 +2013,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_17;
sctp_abort_an_association(stcb->sctp_ep,
stcb, SCTP_PEER_FAULTY, oper);
stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
*abort_flag = 1;
return (0);
@ -2008,7 +2025,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
/* queue directly into socket buffer */
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
} else {
/*
* Special check for when streams are resetting. We
@ -2257,9 +2274,11 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
asoc->highest_tsn_inside_map,
MAX_TSN)) {
#ifdef INVARIANTS
panic("huh, cumack greater than high-tsn in map");
panic("huh, cumack 0x%x greater than high-tsn 0x%x in map",
asoc->cumulative_tsn, asoc->highest_tsn_inside_map);
#else
SCTP_PRINTF("huh, cumack greater than high-tsn in map - should panic?\n");
SCTP_PRINTF("huh, cumack 0x%x greater than high-tsn 0x%x in map - should panic?\n",
asoc->cumulative_tsn, asoc->highest_tsn_inside_map);
asoc->highest_tsn_inside_map = asoc->cumulative_tsn;
#endif
}
@ -2717,7 +2736,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
}
if (num_chunks) {
/*
* Did we get data, if sa update the time for auto-close and
* Did we get data, if so update the time for auto-close and
* give peer credit for being alive.
*/
SCTP_STAT_INCR(sctps_recvpktwithdata);
@ -3209,7 +3228,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->data != NULL) {
(void)sctp_release_pr_sctp_chunk(stcb, tp1,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
&asoc->sent_queue);
&asoc->sent_queue, SCTP_SO_NOT_LOCKED);
}
tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
@ -3222,7 +3241,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->data != NULL) {
(void)sctp_release_pr_sctp_chunk(stcb, tp1,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
&asoc->sent_queue);
&asoc->sent_queue, SCTP_SO_NOT_LOCKED);
}
tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
@ -3386,7 +3405,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
tp1->sent++;
}
}
}
@ -3637,7 +3655,7 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
if (tp1->data) {
(void)sctp_release_pr_sctp_chunk(stcb, tp1,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
&asoc->sent_queue);
&asoc->sent_queue, SCTP_SO_NOT_LOCKED);
}
} else {
/*
@ -3670,12 +3688,32 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
*/
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
tp1);
tp1, SCTP_SO_NOT_LOCKED);
sctp_m_freem(tp1->data);
tp1->data = NULL;
if (stcb->sctp_socket) {
sctp_sowwakeup(stcb->sctp_ep,
stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/*
* assoc was freed while we
* were unlocked
*/
SCTP_SOCKET_UNLOCK(so, 1);
return (NULL);
}
#endif
sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
if (sctp_logging_level & SCTP_WAKE_LOGGING_ENABLE) {
sctp_wakeup_log(stcb, tp1->rec.data.TSN_seq, 1, SCTP_WAKESND_FROM_FWDTSN);
}
@ -3781,7 +3819,6 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
int win_probe_recovered = 0;
int j, done_once = 0;
if (sctp_logging_level & SCTP_LOG_SACK_ARRIVALS_ENABLE) {
sctp_misc_ints(SCTP_SACK_LOG_EXPRESS, cumack,
rwnd, stcb->asoc.last_acked_seq, stcb->asoc.peers_rwnd);
@ -3811,7 +3848,6 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
goto again;
}
return;
}
/* First setup for CC stuff */
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
@ -3862,7 +3898,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_abort_an_association(stcb->sctp_ep, stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
return;
#endif
}
@ -3981,11 +4017,32 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
}
if (stcb->sctp_socket) {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
SOCKBUF_LOCK(&stcb->sctp_socket->so_snd);
if (sctp_logging_level & SCTP_WAKE_LOGGING_ENABLE) {
sctp_wakeup_log(stcb, cumack, 1, SCTP_WAKESND_FROM_SACK);
}
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/* assoc was freed while we were unlocked */
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
#endif
sctp_sowwakeup_locked(stcb->sctp_ep, stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
} else {
if (sctp_logging_level & SCTP_WAKE_LOGGING_ENABLE) {
sctp_wakeup_log(stcb, cumack, 1, SCTP_NOWAKE_FROM_SACK);
@ -4195,7 +4252,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_abort_an_association(stcb->sctp_ep, stcb, SCTP_RESPONSE_TO_USER_REQ, oper, SCTP_SO_NOT_LOCKED);
} else {
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@ -4344,8 +4401,6 @@ sctp_handle_sack(struct mbuf *m, int offset,
if (dupdata == NULL)
break;
off_to_dup += sizeof(uint32_t);
}
}
} else {
@ -4396,7 +4451,7 @@ sctp_handle_sack(struct mbuf *m, int offset,
*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_abort_an_association(stcb->sctp_ep, stcb, SCTP_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
return;
#endif
}
@ -4707,11 +4762,31 @@ sctp_handle_sack(struct mbuf *m, int offset,
done_with_it:
if ((wake_him) && (stcb->sctp_socket)) {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
SOCKBUF_LOCK(&stcb->sctp_socket->so_snd);
if (sctp_logging_level & SCTP_WAKE_LOGGING_ENABLE) {
sctp_wakeup_log(stcb, cum_ack, wake_him, SCTP_WAKESND_FROM_SACK);
}
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/* assoc was freed while we were unlocked */
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
#endif
sctp_sowwakeup_locked(stcb->sctp_ep, stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
} else {
if (sctp_logging_level & SCTP_WAKE_LOGGING_ENABLE) {
sctp_wakeup_log(stcb, cum_ack, wake_him, SCTP_NOWAKE_FROM_SACK);
@ -4865,7 +4940,7 @@ sctp_handle_sack(struct mbuf *m, int offset,
*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_abort_an_association(stcb->sctp_ep, stcb, SCTP_RESPONSE_TO_USER_REQ, oper, SCTP_SO_NOT_LOCKED);
return;
} else {
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
@ -4926,7 +5001,6 @@ sctp_handle_sack(struct mbuf *m, int offset,
asoc->advanced_peer_ack_point = cum_ack;
}
/* C2. try to further move advancedPeerAckPoint ahead */
if ((asoc->peer_supports_prsctp) && (asoc->pr_sctp_cnt > 0)) {
struct sctp_tmit_chunk *lchk;
@ -5167,7 +5241,7 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
if (stcb->sctp_socket) {
sctp_add_to_readq(stcb->sctp_ep, stcb,
ctl,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
}
} else {
/* no more delivery now. */
@ -5194,7 +5268,7 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
if (stcb->sctp_socket) {
sctp_add_to_readq(stcb->sctp_ep, stcb,
ctl,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
}
tt = strmin->last_sequence_delivered + 1;
} else {
@ -5308,7 +5382,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
}
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_PEER_FAULTY, oper, SCTP_SO_NOT_LOCKED);
return;
}
SCTP_STAT_INCR(sctps_fwdtsn_map_over);
@ -5322,7 +5396,6 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
sctp_log_map(0, 3, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
}
asoc->last_echo_tsn = asoc->highest_tsn_inside_map;
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
if ((compare_with_wrap(((uint32_t) asoc->cumulative_tsn + gap), asoc->highest_tsn_inside_map, MAX_TSN)) ||
@ -5435,7 +5508,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
str_seq = (asoc->str_of_pdapi << 16) | asoc->ssn_of_pdapi;
sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
stcb, SCTP_PARTIAL_DELIVERY_ABORTED, (void *)&str_seq);
stcb, SCTP_PARTIAL_DELIVERY_ABORTED, (void *)&str_seq, SCTP_SO_NOT_LOCKED);
}
break;
@ -5452,7 +5525,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
str_seq = (asoc->str_of_pdapi << 16) | asoc->ssn_of_pdapi;
sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
stcb, SCTP_PARTIAL_DELIVERY_ABORTED, (void *)&str_seq);
stcb, SCTP_PARTIAL_DELIVERY_ABORTED, (void *)&str_seq, SCTP_SO_NOT_LOCKED);
asoc->fragmented_delivery_inprogress = 0;
}
/*************************************************************/

View File

@ -271,7 +271,7 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
asoc->stream_queue_cnt--;
sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL,
stcb, SCTP_NOTIFY_DATAGRAM_UNSENT,
sp);
sp, SCTP_SO_NOT_LOCKED);
if (sp->data) {
sctp_m_freem(sp->data);
sp->data = NULL;
@ -382,7 +382,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
&abort_flag, (struct sctp_chunkhdr *)cp);
if (abort_flag) {
/* Send an abort and notify peer */
sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_CAUSE_PROTOCOL_VIOLATION, op_err);
sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_CAUSE_PROTOCOL_VIOLATION, op_err, SCTP_SO_NOT_LOCKED);
*abort_no_unlock = 1;
return (-1);
}
@ -550,7 +550,7 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
}
}
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
stcb, 0, (void *)r_net);
stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED);
}
r_net->error_count = 0;
r_net->hb_responded = 1;
@ -560,7 +560,7 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
r_net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
r_net->dest_state |= SCTP_ADDR_REACHABLE;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
SCTP_HEARTBEAT_SUCCESS, (void *)r_net);
SCTP_HEARTBEAT_SUCCESS, (void *)r_net, SCTP_SO_NOT_LOCKED);
/* now was it the primary? if so restore */
if (r_net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
(void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, r_net);
@ -593,6 +593,11 @@ static void
sctp_handle_abort(struct sctp_abort_chunk *cp,
struct sctp_tcb *stcb, struct sctp_nets *net)
{
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n");
if (stcb == NULL)
return;
@ -600,7 +605,7 @@ sctp_handle_abort(struct sctp_abort_chunk *cp,
/* 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_abort_notification(stcb, 0, SCTP_SO_NOT_LOCKED);
/* free the tcb */
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
@ -609,10 +614,21 @@ sctp_handle_abort(struct sctp_abort_chunk *cp,
}
#ifdef SCTP_ASOCLOG_OF_TSNS
sctp_print_out_track_log(stcb);
#endif
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_6);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n");
}
@ -623,6 +639,11 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
struct sctp_association *asoc;
int some_on_streamwheel;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_shutdown: handling SHUTDOWN\n");
if (stcb == NULL)
@ -647,7 +668,23 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
asoc->control_pdapi->pdapi_aborted = 1;
asoc->control_pdapi = NULL;
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/* assoc was freed while we were unlocked */
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
#endif
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
/* goto SHUTDOWN_RECEIVED state to block new requests */
if (stcb->sctp_socket) {
@ -659,7 +696,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
* notify upper layer that peer has initiated a
* shutdown
*/
sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL);
sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
/* reset time */
(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
@ -705,6 +742,11 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
{
struct sctp_association *asoc;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(stcb->sctp_ep);
#endif
SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n");
if (stcb == NULL)
@ -727,13 +769,28 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
asoc->control_pdapi->pdapi_aborted = 1;
asoc->control_pdapi = NULL;
SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/* assoc was freed while we were unlocked */
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
#endif
sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
/* are the queues empty? */
if (!TAILQ_EMPTY(&asoc->send_queue) ||
!TAILQ_EMPTY(&asoc->sent_queue) ||
!TAILQ_EMPTY(&asoc->out_wheel)) {
sctp_report_all_outbound(stcb, 0);
sctp_report_all_outbound(stcb, 0, SCTP_SO_NOT_LOCKED);
}
/* stop the timer */
sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9);
@ -741,7 +798,7 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
sctp_send_shutdown_complete(stcb, net);
/* notify upper layer protocol */
if (stcb->sctp_socket) {
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL);
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
/* Set the connected flag to disconnected */
@ -750,8 +807,18 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
}
SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
/* free the TCB but first save off the ep */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_10);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
/*
@ -835,9 +902,13 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
uint16_t error_type;
uint16_t error_len;
struct sctp_association *asoc;
int adjust;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
/* parse through all of the errors and process */
asoc = &stcb->asoc;
phdr = (struct sctp_paramhdr *)((caddr_t)ch +
@ -875,10 +946,21 @@ 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_abort_notification(stcb, 0, SCTP_SO_NOT_LOCKED);
/* now free the asoc */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
return (-1);
}
/* blast back to INIT state */
@ -886,7 +968,7 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
asoc->state |= SCTP_STATE_COOKIE_WAIT;
sctp_stop_all_cookie_timers(stcb);
sctp_send_initiate(stcb->sctp_ep, stcb);
sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
}
break;
case SCTP_CAUSE_UNRESOLVABLE_ADDR:
@ -1021,7 +1103,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
stcb->asoc.primary_destination->dest_state &=
~SCTP_ADDR_UNCONFIRMED;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
stcb, 0, (void *)stcb->asoc.primary_destination);
stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED);
}
if (sctp_process_init_ack(m, iphlen, offset, sh, cp, stcb,
net, abort_no_unlock, vrf_id) < 0) {
@ -1219,6 +1301,10 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
(inp->sctp_socket->so_qlimit == 0)
) {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
/*
* Here is where collision would go if we
* did a connect() and instead got a
@ -1227,7 +1313,22 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
*/
stcb->sctp_ep->sctp_flags |=
SCTP_PCB_FLAGS_CONNECTED;
soisconnected(stcb->sctp_ep->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_add_int(&stcb->asoc.refcnt, -1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
SCTP_SOCKET_UNLOCK(so, 1);
return (NULL);
}
#endif
soisconnected(stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
/* notify upper layer */
*notification = SCTP_NOTIFY_ASSOC_UP;
@ -1375,9 +1476,28 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
(inp->sctp_socket->so_qlimit == 0)) {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
stcb->sctp_ep->sctp_flags |=
SCTP_PCB_FLAGS_CONNECTED;
soisconnected(stcb->sctp_ep->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_add_int(&stcb->asoc.refcnt, -1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
SCTP_SOCKET_UNLOCK(so, 1);
return (NULL);
}
#endif
soisconnected(stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)
SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
@ -1407,7 +1527,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
* sctp_chunk_output will get the retrans out behind
* this.
*/
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK, SCTP_SO_NOT_LOCKED);
}
if (how_indx < sizeof(asoc->cookie_how))
asoc->cookie_how[how_indx] = 11;
@ -1476,7 +1596,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* send up all the data */
SCTP_TCB_SEND_LOCK(stcb);
sctp_report_all_outbound(stcb, 1);
sctp_report_all_outbound(stcb, 1, SCTP_SO_NOT_LOCKED);
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
stcb->asoc.strmout[i].stream_no = i;
stcb->asoc.strmout[i].next_sequence_sent = 0;
@ -1577,6 +1697,12 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
uint32_t old_tag;
uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE];
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(inp);
#endif
/*
* find and validate the INIT chunk in the cookie (peer's info) the
* INIT should start after the cookie-echo header struct (chunk
@ -1673,9 +1799,17 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
sh, op_err, vrf_id);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
atomic_add_int(&stcb->asoc.refcnt, -1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
/* process the INIT-ACK info (my info) */
@ -1698,8 +1832,16 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
retval = 0;
if (retval < 0) {
atomic_add_int(&stcb->asoc.refcnt, 1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
atomic_add_int(&stcb->asoc.refcnt, -1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
/* load all addresses */
@ -1707,8 +1849,16 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh,
init_src)) {
atomic_add_int(&stcb->asoc.refcnt, 1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_17);
atomic_add_int(&stcb->asoc.refcnt, -1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
/*
@ -1728,8 +1878,16 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
SCTPDBG(SCTP_DEBUG_AUTH1,
"COOKIE-ECHO: AUTH failed\n");
atomic_add_int(&stcb->asoc.refcnt, 1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_18);
atomic_add_int(&stcb->asoc.refcnt, -1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
} else {
/* remaining chunks checked... good to go */
@ -1776,8 +1934,16 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
sizeof(sin6->sin6_addr));
} else {
atomic_add_int(&stcb->asoc.refcnt, 1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_19);
atomic_add_int(&stcb->asoc.refcnt, -1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
@ -1802,7 +1968,21 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
* a bit of protection is worth having..
*/
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
soisconnected(stcb->sctp_ep->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
SCTP_SOCKET_UNLOCK(so, 1);
return (NULL);
}
#endif
soisconnected(stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
} else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(inp->sctp_socket->so_qlimit)) {
/*
@ -2163,7 +2343,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
(void)sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL,
netl);
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
(*stcb), 0, (void *)netl);
(*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
}
}
if (*stcb) {
@ -2186,7 +2366,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
* For a restart we will keep the same
* socket, no need to do anything. I THINK!!
*/
sctp_ulp_notify(notification, *stcb, 0, (void *)&sac_restart_id);
sctp_ulp_notify(notification, *stcb, 0, (void *)&sac_restart_id, SCTP_SO_NOT_LOCKED);
return (m);
}
oso = (*inp_p)->sctp_socket;
@ -2200,12 +2380,27 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
if (so == NULL) {
struct mbuf *op_err;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *pcb_so;
#endif
/* Too many sockets */
SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n");
op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
sctp_abort_association(*inp_p, NULL, m, iphlen,
sh, op_err, vrf_id);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
pcb_so = SCTP_INP_SO(*inp_p);
atomic_add_int(&(*stcb)->asoc.refcnt, 1);
SCTP_TCB_UNLOCK((*stcb));
SCTP_SOCKET_LOCK(pcb_so, 1);
SCTP_TCB_LOCK((*stcb));
atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_20);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(pcb_so, 1);
#endif
return (NULL);
}
inp = (struct sctp_inpcb *)so->so_pcb;
@ -2222,7 +2417,6 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
(SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) |
SCTP_PCB_FLAGS_DONT_WAKE);
inp->sctp_features = (*inp_p)->sctp_features;
inp->sctp_socket = so;
inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
inp->partial_delivery_point = (*inp_p)->partial_delivery_point;
@ -2274,18 +2468,28 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
SCTP_INP_DECR_REF(inp);
/* Switch over to the new guy */
*inp_p = inp;
sctp_ulp_notify(notification, *stcb, 0, NULL);
sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
/*
* Pull it from the incomplete queue and wake the
* guy
*/
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
atomic_add_int(&(*stcb)->asoc.refcnt, 1);
SCTP_TCB_UNLOCK((*stcb));
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK((*stcb));
atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
#endif
soisconnected(so);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
return (m);
}
}
if ((notification) && ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
sctp_ulp_notify(notification, *stcb, 0, NULL);
sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
}
return (m);
}
@ -2323,11 +2527,30 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
&asoc->time_entered, sctp_align_safe_nocopy);
}
(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL);
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
soisconnected(stcb->sctp_ep->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
#endif
soisconnected(stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
stcb, net);
@ -2477,6 +2700,11 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
{
struct sctp_association *asoc;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n");
if (stcb == NULL)
@ -2493,12 +2721,12 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
}
/* notify upper layer protocol */
if (stcb->sctp_socket) {
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL);
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
/* are the queues empty? they should be */
if (!TAILQ_EMPTY(&asoc->send_queue) ||
!TAILQ_EMPTY(&asoc->sent_queue) ||
!TAILQ_EMPTY(&asoc->out_wheel)) {
sctp_report_all_outbound(stcb, 0);
sctp_report_all_outbound(stcb, 0, SCTP_SO_NOT_LOCKED);
}
}
/* stop the timer */
@ -2507,8 +2735,18 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
/* free the TCB */
SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_shutdown_complete: calls free-asoc\n");
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_23);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
return;
}
@ -2683,7 +2921,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
*/
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep,
stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_25);
sctp_send_initiate(stcb->sctp_ep, stcb);
sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
}
break;
case SCTP_SELECTIVE_ACK:
@ -2775,7 +3013,7 @@ sctp_reset_in_stream(struct sctp_tcb *stcb, int number_entries, uint16_t * list)
stcb->asoc.strmin[i].last_sequence_delivered = 0xffff;
}
}
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list);
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
}
static void
@ -2799,7 +3037,7 @@ sctp_reset_out_streams(struct sctp_tcb *stcb, int number_entries, uint16_t * lis
stcb->asoc.strmout[temp].next_sequence_sent = 0;
}
}
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list);
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
}
@ -2904,7 +3142,7 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
/* do it */
sctp_reset_out_streams(stcb, number_entries, srparam->list_of_streams);
} else {
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, srparam->list_of_streams);
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
}
} else if (type == SCTP_STR_RESET_IN_REQUEST) {
/* Answered my request */
@ -2912,7 +3150,7 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
if (asoc->stream_reset_outstanding)
asoc->stream_reset_outstanding--;
if (action != SCTP_STREAM_RESET_PERFORMED) {
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb, number_entries, srparam->list_of_streams);
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
}
} else if (type == SCTP_STR_RESET_TSN_REQUEST) {
/**
@ -3492,6 +3730,11 @@ __attribute__((noinline))
int auth_skipped = 0;
int asconf_cnt = 0;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n",
iphlen, *offset, length, stcb);
@ -3825,7 +4068,7 @@ __attribute__((noinline))
sctp_send_shutdown_ack(stcb,
stcb->asoc.primary_destination);
*offset = length;
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
if (locked_tcb) {
SCTP_TCB_UNLOCK(locked_tcb);
}
@ -3860,7 +4103,18 @@ __attribute__((noinline))
}
*offset = length;
if (stcb) {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
return (NULL);
}
@ -3887,7 +4141,7 @@ __attribute__((noinline))
return (NULL);
if ((stcb) && ret == 0)
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
*offset = length;
if (locked_tcb) {
SCTP_TCB_UNLOCK(locked_tcb);
@ -4187,7 +4441,18 @@ __attribute__((noinline))
if ((stcb) && (stcb->asoc.total_output_queue_size)) {
;
} else if (stcb) {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
*offset = length;
return (NULL);
}
@ -4336,7 +4601,18 @@ __attribute__((noinline))
*fwd_tsn_seen = 1;
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/* We are not interested anymore */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_29);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
*offset = length;
return (NULL);
}
@ -4370,7 +4646,18 @@ __attribute__((noinline))
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
/* We are not interested anymore */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_30);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
*offset = length;
return (NULL);
}
@ -4821,7 +5108,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
(stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) {
sctp_mobility_feature_off(inp, SCTP_MOBILITY_DO_FASTHANDOFF);
SCTPDBG(SCTP_DEBUG_INPUT3, "Calling chunk OUTPUT\n");
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
SCTPDBG(SCTP_DEBUG_INPUT3, "chunk OUTPUT returns\n");
}
#ifdef SCTP_AUDITING_ENABLED
@ -4947,7 +5234,7 @@ sctp_input(i_pak, off)
vrf_id);
if ((inp) && (stcb)) {
sctp_send_packet_dropped(stcb, net, m, iphlen, 1);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
} else if ((inp != NULL) && (stcb == NULL)) {
refcount_up = 1;
}

View File

@ -375,4 +375,10 @@ extern int sctp_logoff_stuff;
} while (0)
#if defined(SCTP_SO_LOCK_TESTING)
#define SCTP_INP_SO(sctpinp) (sctpinp)->ip_inp.inp.inp_socket
#define SCTP_SOCKET_LOCK(so, refcnt)
#define SCTP_SOCKET_UNLOCK(so, refcnt)
#endif
#endif

View File

@ -272,6 +272,7 @@ typedef struct callout sctp_os_timer_t;
/* The packed define for 64 bit platforms */
#define SCTP_PACKED __attribute__((packed))
#define SCTP_UNUSED __attribute__((unused))
/*
* Functions

View File

@ -3270,7 +3270,12 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
int nofragment_flag,
int ecn_ok,
struct sctp_tmit_chunk *chk,
int out_of_asoc_ok)
int out_of_asoc_ok,
int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
/* nofragment_flag to tell if IP_DF should be set (IPv4 only) */
{
/*
@ -3456,7 +3461,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
stcb,
SCTP_FAILED_THRESHOLD,
(void *)net);
(void *)net,
so_locked);
net->dest_state &= ~SCTP_ADDR_REACHABLE;
net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
/*
@ -3840,7 +3846,11 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
void
sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
struct mbuf *m, *m_at, *mp_last;
struct sctp_nets *net;
@ -4108,7 +4118,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - calls lowlevel_output\n");
ret = sctp_lowlevel_chunk_output(inp, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
m, 0, NULL, 0, 0, NULL, 0);
m, 0, NULL, 0, 0, NULL, 0, so_locked);
SCTPDBG(SCTP_DEBUG_OUTPUT4, "lowlevel_output - %d\n", ret);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
@ -5169,7 +5179,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
p_len += padval;
}
(void)sctp_lowlevel_chunk_output(inp, NULL, NULL, to, m, 0, NULL, 0, 0,
NULL, 0);
NULL, 0, SCTP_SO_NOT_LOCKED);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
}
@ -5279,7 +5289,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
cause = SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_UNSENT;
ret_spc = sctp_release_pr_sctp_chunk(stcb, chk,
cause,
&asoc->sent_queue);
&asoc->sent_queue, SCTP_SO_LOCKED);
freed_spc += ret_spc;
if (freed_spc >= dataout) {
return;
@ -5304,7 +5314,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
ret_spc = sctp_release_pr_sctp_chunk(stcb, chk,
SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_UNSENT,
&asoc->send_queue);
&asoc->send_queue, SCTP_SO_LOCKED);
freed_spc += ret_spc;
if (freed_spc >= dataout) {
@ -5670,7 +5680,11 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
int *num_out,
int *reason_code,
int control_only, int *cwnd_full, int from_where,
struct timeval *now, int *now_filled, int frag_point);
struct timeval *now, int *now_filled, int frag_point, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
static void
sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
@ -5720,7 +5734,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
atomic_add_int(&stcb->asoc.refcnt, 1);
sctp_abort_an_association(inp, stcb,
SCTP_RESPONSE_TO_USER_REQ,
m);
m, SCTP_SO_NOT_LOCKED);
/*
* sctp_abort_an_association calls sctp_free_asoc()
* free association will NOT free it since we
@ -5814,7 +5828,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
atomic_add_int(&stcb->asoc.refcnt, 1);
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_RESPONSE_TO_USER_REQ,
NULL);
NULL, SCTP_SO_NOT_LOCKED);
atomic_add_int(&stcb->asoc.refcnt, -1);
goto no_chunk_output;
}
@ -5835,7 +5849,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
do_chunk_output = 0;
}
if (do_chunk_output)
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_NOT_LOCKED);
else if (added_control) {
int num_out = 0, reason = 0, cwnd_full = 0, now_filled = 0;
struct timeval now;
@ -5843,7 +5857,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
(void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out,
&reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point);
&reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point, SCTP_SO_NOT_LOCKED);
}
no_chunk_output:
if (ret) {
@ -6858,7 +6872,11 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
int *num_out,
int *reason_code,
int control_only, int *cwnd_full, int from_where,
struct timeval *now, int *now_filled, int frag_point)
struct timeval *now, int *now_filled, int frag_point, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
/*
* Ok this is the generic chunk service queue. we must do the
@ -7268,7 +7286,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
if ((error = sctp_lowlevel_chunk_output(inp, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
outchain, auth_offset, auth,
no_fragmentflg, 0, NULL, asconf))) {
no_fragmentflg, 0, NULL, asconf, so_locked))) {
if (error == ENOBUFS) {
asoc->ifp_had_enobuf = 1;
SCTP_STAT_INCR(sctps_lowlevelerr);
@ -7548,7 +7566,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
no_fragmentflg,
bundle_at,
data_list[0],
asconf))) {
asconf, so_locked))) {
/* error, we could not output */
if (error == ENOBUFS) {
SCTP_STAT_INCR(sctps_lowlevelerr);
@ -8110,7 +8128,11 @@ static int
sctp_chunk_retransmission(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_association *asoc,
int *cnt_out, struct timeval *now, int *now_filled, int *fr_done)
int *cnt_out, struct timeval *now, int *now_filled, int *fr_done, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
/*-
* send out one MTU of retransmission. If fast_retransmit is
@ -8223,7 +8245,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
if ((error = sctp_lowlevel_chunk_output(inp, stcb, chk->whoTo,
(struct sockaddr *)&chk->whoTo->ro._l_addr, m, auth_offset,
auth, no_fragmentflg, 0, NULL, asconf))) {
auth, no_fragmentflg, 0, NULL, asconf, so_locked))) {
SCTP_STAT_INCR(sctps_lowlevelerr);
return (error);
}
@ -8272,7 +8294,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
chk->snd_count,
sctp_max_retran_chunk);
atomic_add_int(&stcb->asoc.refcnt, 1);
sctp_abort_an_association(stcb->sctp_ep, stcb, 0, NULL);
sctp_abort_an_association(stcb->sctp_ep, stcb, 0, NULL, so_locked);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (SCTP_RETRAN_EXIT);
@ -8461,7 +8483,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
/* Now lets send it, if there is anything to send :> */
if ((error = sctp_lowlevel_chunk_output(inp, stcb, net,
(struct sockaddr *)&net->ro._l_addr, m, auth_offset,
auth, no_fragmentflg, 0, NULL, asconf))) {
auth, no_fragmentflg, 0, NULL, asconf, so_locked))) {
/* error, we could not output */
SCTP_STAT_INCR(sctps_lowlevelerr);
return (error);
@ -8620,7 +8642,12 @@ sctp_timer_validation(struct sctp_inpcb *inp,
void
sctp_chunk_output(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
int from_where)
int from_where,
int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
/*-
* Ok this is the generic chunk service queue. we must do the
@ -8686,12 +8713,12 @@ sctp_chunk_output(struct sctp_inpcb *inp,
*/
(void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1,
&cwnd_full, from_where,
&now, &now_filled, frag_point);
&now, &now_filled, frag_point, so_locked);
return;
} else if (from_where != SCTP_OUTPUT_FROM_HB_TMR) {
/* if its not from a HB then do it */
fr_done = 0;
ret = sctp_chunk_retransmission(inp, stcb, asoc, &num_out, &now, &now_filled, &fr_done);
ret = sctp_chunk_retransmission(inp, stcb, asoc, &num_out, &now, &now_filled, &fr_done, so_locked);
if (fr_done) {
tot_frs++;
}
@ -8711,7 +8738,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
*/
(void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1,
&cwnd_full, from_where,
&now, &now_filled, frag_point);
&now, &now_filled, frag_point, so_locked);
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(8, inp, stcb, NULL);
#endif
@ -8738,7 +8765,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
#endif
/* Push out any control */
(void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1, &cwnd_full, from_where,
&now, &now_filled, frag_point);
&now, &now_filled, frag_point, so_locked);
return;
}
if (tot_frs > asoc->max_burst) {
@ -8811,7 +8838,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
do {
error = sctp_med_chunk_output(inp, stcb, asoc, &num_out,
&reason_code, 0, &cwnd_full, from_where,
&now, &now_filled, frag_point);
&now, &now_filled, frag_point, so_locked);
if (error) {
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Error %d was returned from med-c-op\n", error);
if (sctp_logging_level & SCTP_LOG_MAXBURST_ENABLE) {
@ -9092,7 +9119,6 @@ sctp_send_sack(struct sctp_tcb *stcb)
int num_dups = 0;
int space_req;
a_chk = NULL;
asoc = &stcb->asoc;
SCTP_TCB_LOCK_ASSERT(stcb);
@ -9354,7 +9380,11 @@ sctp_send_sack(struct sctp_tcb *stcb)
void
sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr)
sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
struct mbuf *m_abort;
struct mbuf *m_out = NULL, *m_end = NULL;
@ -9409,7 +9439,6 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr)
abort->ch.chunk_flags = 0;
abort->ch.chunk_length = htons(sizeof(*abort) + sz);
/* prepend and fill in the SCTP header */
SCTP_BUF_PREPEND(m_out, sizeof(struct sctphdr), M_DONTWAIT);
if (m_out == NULL) {
@ -9426,7 +9455,7 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr)
(void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb,
stcb->asoc.primary_destination,
(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr,
m_out, auth_offset, auth, 1, 0, NULL, 0);
m_out, auth_offset, auth, 1, 0, NULL, 0, so_locked);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
}
@ -9455,7 +9484,7 @@ sctp_send_shutdown_complete(struct sctp_tcb *stcb,
SCTP_BUF_LEN(m_shutdown_comp) = sizeof(struct sctp_shutdown_complete_msg);
(void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
m_shutdown_comp, 0, NULL, 1, 0, NULL, 0);
m_shutdown_comp, 0, NULL, 1, 0, NULL, 0, SCTP_SO_NOT_LOCKED);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
return;
}
@ -10877,6 +10906,7 @@ sctp_lower_sosend(struct socket *so,
net = NULL;
stcb = NULL;
asoc = NULL;
t_inp = inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT);
@ -11422,7 +11452,7 @@ sctp_lower_sosend(struct socket *so,
/* release this lock, otherwise we hang on ourselves */
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_RESPONSE_TO_USER_REQ,
mm);
mm, SCTP_SO_LOCKED);
/* now relock the stcb so everything is sane */
hold_tcblock = 0;
stcb = NULL;
@ -11777,7 +11807,7 @@ sctp_lower_sosend(struct socket *so,
queue_only_for_init = 0;
queue_only = 0;
} else {
sctp_send_initiate(inp, stcb);
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
SCTP_SET_STATE(asoc, SCTP_STATE_COOKIE_WAIT);
queue_only_for_init = 0;
queue_only = 1;
@ -11797,12 +11827,12 @@ sctp_lower_sosend(struct socket *so,
hold_tcblock = 1;
sctp_chunk_output(inp,
stcb,
SCTP_OUTPUT_FROM_USR_SEND);
SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED);
}
} else {
sctp_chunk_output(inp,
stcb,
SCTP_OUTPUT_FROM_USR_SEND);
SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED);
}
if (hold_tcblock == 1) {
SCTP_TCB_UNLOCK(stcb);
@ -11960,7 +11990,7 @@ sctp_lower_sosend(struct socket *so,
}
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_RESPONSE_TO_USER_REQ,
NULL);
NULL, SCTP_SO_LOCKED);
/*
* now relock the stcb so everything
* is sane
@ -12039,7 +12069,7 @@ sctp_lower_sosend(struct socket *so,
queue_only_for_init = 0;
queue_only = 0;
} else {
sctp_send_initiate(inp, stcb);
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
queue_only_for_init = 0;
queue_only = 1;
@ -12053,11 +12083,11 @@ sctp_lower_sosend(struct socket *so,
* send
*/
if (SCTP_TCB_TRYLOCK(stcb)) {
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED);
hold_tcblock = 1;
}
} else {
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED);
}
} else if ((queue_only == 0) &&
(stcb->asoc.peers_rwnd == 0) &&
@ -12067,7 +12097,7 @@ sctp_lower_sosend(struct socket *so,
hold_tcblock = 1;
SCTP_TCB_LOCK(stcb);
}
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED);
} else if (some_on_control) {
int num_out, reason, cwnd_full, frag_point;
@ -12078,7 +12108,7 @@ sctp_lower_sosend(struct socket *so,
}
frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
(void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out,
&reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point);
&reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point, SCTP_SO_LOCKED);
}
SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d err:%d",
queue_only, stcb->asoc.peers_rwnd, un_sent,

View File

@ -74,7 +74,12 @@ int
int
sctp_v4src_match_nexthop(struct sctp_ifa *sifa, sctp_route_t * ro);
void sctp_send_initiate(struct sctp_inpcb *, struct sctp_tcb *);
void
sctp_send_initiate(struct sctp_inpcb *, struct sctp_tcb *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
void
sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *,
@ -128,8 +133,18 @@ sctp_insert_on_wheel(struct sctp_tcb *stcb,
struct sctp_association *asoc,
struct sctp_stream_out *strq, int holdslock);
void sctp_chunk_output(struct sctp_inpcb *, struct sctp_tcb *, int);
void sctp_send_abort_tcb(struct sctp_tcb *, struct mbuf *);
void
sctp_chunk_output(struct sctp_inpcb *, struct sctp_tcb *, int, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
void
sctp_send_abort_tcb(struct sctp_tcb *, struct mbuf *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
void send_forward_tsn(struct sctp_tcb *, struct sctp_association *);

View File

@ -611,7 +611,6 @@ sctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr,
}
static struct sctp_tcb *
sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
struct sockaddr *to, struct sctp_nets **netp, uint32_t vrf_id)
@ -1243,7 +1242,6 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
return (NULL);
}
struct sctp_inpcb *
sctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock,
uint32_t vrf_id)
@ -2604,7 +2602,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, NULL, 0);
#endif
SCTP_ITERATOR_LOCK();
so = inp->sctp_socket;
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
@ -2650,11 +2647,11 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
cnt_in_sd = 0;
for ((asoc = LIST_FIRST(&inp->sctp_asoc_list)); asoc != NULL;
asoc = nasoc) {
nasoc = LIST_NEXT(asoc, sctp_tcblist);
SCTP_TCB_LOCK(asoc);
nasoc = LIST_NEXT(asoc, sctp_tcblist);
if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
/* Skip guys being freed */
asoc->sctp_socket = NULL;
/* asoc->sctp_socket = NULL; FIXME MT */
cnt_in_sd++;
SCTP_TCB_UNLOCK(asoc);
continue;
@ -2668,7 +2665,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* it wants the data to get across first.
*/
/* Just abandon things in the front states */
if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_NOFORCE,
SCTP_FROM_SCTP_PCB + SCTP_LOC_2) == 0) {
cnt_in_sd++;
@ -2704,7 +2700,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
*ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_3);
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_3;
sctp_send_abort_tcb(asoc, op_err);
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@ -2738,7 +2734,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
asoc->asoc.primary_destination);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc,
asoc->asoc.primary_destination);
sctp_chunk_output(inp, asoc, SCTP_OUTPUT_FROM_CLOSING);
sctp_chunk_output(inp, asoc, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_LOCKED);
}
} else {
/* mark into shutdown pending */
@ -2787,7 +2783,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
*ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_5);
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_5;
sctp_send_abort_tcb(asoc, op_err);
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@ -2800,7 +2796,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
}
continue;
} else {
sctp_chunk_output(inp, asoc, SCTP_OUTPUT_FROM_CLOSING);
sctp_chunk_output(inp, asoc, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
}
}
cnt_in_sd++;
@ -2864,7 +2860,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_7;
sctp_send_abort_tcb(asoc, op_err);
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
} else if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
cnt++;
@ -3018,12 +3014,9 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
SCTP_INP_READ_DESTROY(inp);
SCTP_ASOC_CREATE_LOCK_DESTROY(inp);
SCTP_INP_INFO_WUNLOCK();
SCTP_ITERATOR_UNLOCK();
SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_ep, inp);
SCTP_DECR_EP_COUNT();
}
@ -3780,7 +3773,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
int cnt = 0;
/* first, lets purge the entry from the hash table. */
SCTP_TCB_LOCK_ASSERT(stcb);
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, stcb, 6);
@ -5468,7 +5460,6 @@ sctp_set_primary_addr(struct sctp_tcb *stcb, struct sockaddr *sa,
}
}
int
sctp_is_vtag_good(struct sctp_inpcb *inp, uint32_t tag, struct timeval *now)
{
@ -5712,7 +5703,7 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
asoc->last_revoke_count = cnt;
(void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
sctp_send_sack(stcb);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_DRAIN);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_DRAIN, SCTP_SO_NOT_LOCKED);
reneged_asoc_ids[reneged_at] = sctp_get_associd(stcb);
reneged_at++;
}

View File

@ -60,8 +60,8 @@ sctp_can_peel_off(struct socket *head, sctp_assoc_t assoc_id)
}
stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1);
if (stcb == NULL) {
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOTCONN);
return (ENOTCONN);
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOENT);
return (ENOENT);
}
state = SCTP_GET_STATE((&stcb->asoc));
if ((state == SCTP_STATE_EMPTY) ||
@ -161,26 +161,27 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
*error = ENOTCONN;
return (NULL);
}
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
newso = sonewconn(head, SS_ISCONNECTED
);
if (newso == NULL) {
SCTPDBG(SCTP_DEBUG_PEEL1, "sctp_peeloff:sonewconn failed\n");
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_PEELOFF, ENOMEM);
*error = ENOMEM;
SCTP_TCB_UNLOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (NULL);
}
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
n_inp = (struct sctp_inpcb *)newso->so_pcb;
SOCK_LOCK(head);
SCTP_INP_WLOCK(inp);
SCTP_INP_WLOCK(n_inp);
n_inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE |
SCTP_PCB_FLAGS_CONNECTED |
SCTP_PCB_FLAGS_IN_TCPPOOL | /* Turn on Blocking IO */
(SCTP_PCB_COPY_FLAGS & inp->sctp_flags));
n_inp->sctp_features = inp->sctp_features;
n_inp->sctp_mobility_features = inp->sctp_mobility_features;
n_inp->sctp_frag_point = inp->sctp_frag_point;
n_inp->partial_delivery_point = inp->partial_delivery_point;
n_inp->sctp_context = inp->sctp_context;
@ -222,8 +223,6 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
* Now we must move it from one hash table to another and get the
* stcb in the right place.
*/
SCTP_INP_WUNLOCK(n_inp);
SCTP_INP_WUNLOCK(inp);
sctp_move_pcb_and_assoc(inp, n_inp, stcb);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@ -233,6 +232,5 @@ sctp_get_peeloff(struct socket *head, sctp_assoc_t assoc_id, int *error)
*/
sctp_pull_off_control_to_new_inp(inp, n_inp, stcb, M_WAITOK);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (newso);
}

View File

@ -143,7 +143,7 @@ sctp_early_fr_timer(struct sctp_inpcb *inp,
*/
stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer(inp, stcb, net);
} else if (cnt_resend) {
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
}
/* Restart it? */
if (net->flight_size < net->cwnd) {
@ -219,7 +219,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
stcb,
SCTP_FAILED_THRESHOLD,
(void *)net);
(void *)net, SCTP_SO_NOT_LOCKED);
}
}
/*********HOLD THIS COMMENT FOR PATCH OF ALTERNATE
@ -280,7 +280,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_abort_an_association(inp, stcb, SCTP_FAILED_THRESHOLD, oper, SCTP_SO_NOT_LOCKED);
return (1);
}
return (0);
@ -702,7 +702,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
(void)sctp_release_pr_sctp_chunk(stcb,
chk,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
&stcb->asoc.sent_queue);
&stcb->asoc.sent_queue, SCTP_SO_NOT_LOCKED);
}
}
continue;
@ -714,7 +714,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
(void)sctp_release_pr_sctp_chunk(stcb,
chk,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
&stcb->asoc.sent_queue);
&stcb->asoc.sent_queue, SCTP_SO_NOT_LOCKED);
}
}
continue;
@ -1132,7 +1132,7 @@ sctp_t1init_timer(struct sctp_inpcb *inp,
* complete the rest of its sends.
*/
stcb->asoc.delayed_connection = 0;
sctp_send_initiate(inp, stcb);
sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED);
return (0);
}
if (SCTP_GET_STATE((&stcb->asoc)) != SCTP_STATE_COOKIE_WAIT) {
@ -1159,7 +1159,7 @@ sctp_t1init_timer(struct sctp_inpcb *inp,
}
}
/* Send out a new init */
sctp_send_initiate(inp, stcb);
sctp_send_initiate(inp, stcb, SCTP_SO_NOT_LOCKED);
return (0);
}
@ -1203,7 +1203,7 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
}
inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_4;
sctp_abort_an_association(inp, stcb, SCTP_INTERNAL_ERROR,
oper);
oper, SCTP_SO_NOT_LOCKED);
} else {
#ifdef INVARIANTS
panic("Cookie timer expires in wrong state?");
@ -1501,7 +1501,7 @@ sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
}
if (chks_in_queue) {
/* call the output queue function */
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
if ((TAILQ_EMPTY(&stcb->asoc.send_queue)) &&
(TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
/*
@ -1725,7 +1725,7 @@ sctp_autoclose_timer(struct sctp_inpcb *inp,
* queues and know that we are clear to send
* shutdown
*/
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED);
/* Are we clean? */
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue)) {
@ -1875,7 +1875,7 @@ sctp_iterator_timer(struct sctp_iterator *it)
* first I must verify that this won't effect things :-0
*/
if (it->no_chunk_output == 0)
sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3);
sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
SCTP_TCB_UNLOCK(it->stcb);
next_assoc:

View File

@ -229,6 +229,10 @@ sctp_notify(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_nets *net)
{
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
/* protection */
if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
(sh == NULL) || (to == NULL)) {
@ -285,7 +289,7 @@ sctp_notify(struct sctp_inpcb *inp,
net->error_count = net->failure_threshold + 1;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
stcb, SCTP_FAILED_THRESHOLD,
(void *)net);
(void *)net, SCTP_SO_NOT_LOCKED);
}
if (stcb) {
SCTP_TCB_UNLOCK(stcb);
@ -299,8 +303,23 @@ sctp_notify(struct sctp_inpcb *inp,
* either case treat it like a OOTB abort with no
* TCB
*/
sctp_abort_notification(stcb, SCTP_PEER_FAULTY);
sctp_abort_notification(stcb, SCTP_PEER_FAULTY, SCTP_SO_NOT_LOCKED);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
/*
* SCTP_TCB_UNLOCK(stcb); MT: I think this is not
* needed.
*/
#endif
/* no need to unlock here, since the TCB is gone */
}
} else {
@ -526,12 +545,10 @@ sctp_attach(struct socket *so, int proto, struct thread *p)
}
inp = (struct sctp_inpcb *)so->so_pcb;
SCTP_INP_WLOCK(inp);
inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6; /* I'm not v6! */
ip_inp = &inp->ip_inp.inp;
ip_inp->inp_vflag |= INP_IPV4;
ip_inp->inp_ip_ttl = ip_defttl;
#ifdef IPSEC
error = ipsec_init_policy(so, &ip_inp->inp_sp);
#ifdef SCTP_LOG_CLOSING
@ -789,7 +806,7 @@ sctp_disconnect(struct socket *so)
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(err));
}
sctp_send_abort_tcb(stcb, err);
sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
}
SCTP_INP_RUNLOCK(inp);
@ -814,7 +831,7 @@ sctp_disconnect(struct socket *so)
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown(stcb,
stcb->asoc.primary_destination);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
@ -881,7 +898,7 @@ sctp_disconnect(struct socket *so)
*ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4);
}
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
sctp_send_abort_tcb(stcb, op_err);
sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@ -891,7 +908,7 @@ sctp_disconnect(struct socket *so)
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
return (0);
} else {
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
}
}
SCTP_TCB_UNLOCK(stcb);
@ -961,7 +978,7 @@ sctp_shutdown(struct socket *so)
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown(stcb,
stcb->asoc.primary_destination);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
@ -1023,10 +1040,10 @@ 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);
op_err, SCTP_SO_LOCKED);
goto skip_unlock;
} else {
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
}
}
SCTP_TCB_UNLOCK(stcb);
@ -1412,7 +1429,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
} else {
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
sctp_send_initiate(inp, stcb);
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
}
SCTP_TCB_UNLOCK(stcb);
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
@ -3095,7 +3112,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
send_out, (stcb->asoc.str_reset_seq_in - 3),
send_in, send_tsn);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
}
break;
@ -3161,7 +3178,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
stcb->asoc.primary_destination,
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
sctp_send_initiate(inp, stcb);
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
} else {
/*
* already expired or did not use delayed
@ -4064,7 +4081,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
/* initialize authentication parameters for the assoc */
sctp_initialize_auth_params(inp, stcb);
sctp_send_initiate(inp, stcb);
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
out_now:
if (create_lock_on) {

View File

@ -1277,7 +1277,7 @@ sctp_iterator_work(struct sctp_iterator *it)
* first I must verify that this won't effect things :-0
*/
if (it->no_chunk_output == 0)
sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3);
sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
SCTP_TCB_UNLOCK(it->stcb);
next_assoc:
@ -1391,10 +1391,14 @@ sctp_timeout_handler(void *t)
struct sctp_tcb *stcb;
struct sctp_nets *net;
struct sctp_timer *tmr;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
int did_output;
struct sctp_iterator *it = NULL;
tmr = (struct sctp_timer *)t;
inp = (struct sctp_inpcb *)tmr->ep;
stcb = (struct sctp_tcb *)tmr->tcb;
@ -1547,7 +1551,7 @@ sctp_timeout_handler(void *t)
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
if ((stcb->asoc.num_send_timers_up == 0) &&
(stcb->asoc.sent_queue_cnt > 0)
) {
@ -1592,7 +1596,7 @@ sctp_timeout_handler(void *t)
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SACK_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SACK_TMR, SCTP_SO_NOT_LOCKED);
break;
case SCTP_TIMER_TYPE_SHUTDOWN:
if ((stcb == NULL) || (inp == NULL)) {
@ -1607,7 +1611,7 @@ sctp_timeout_handler(void *t)
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_NOT_LOCKED);
break;
case SCTP_TIMER_TYPE_HEARTBEAT:
{
@ -1637,7 +1641,7 @@ sctp_timeout_handler(void *t)
#endif
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT,
stcb->sctp_ep, stcb, lnet);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_HB_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_HB_TMR, SCTP_SO_NOT_LOCKED);
}
break;
case SCTP_TIMER_TYPE_COOKIE:
@ -1657,7 +1661,7 @@ sctp_timeout_handler(void *t)
* We consider T3 and Cookie timer pretty much the same with
* respect to where from in chunk_output.
*/
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
break;
case SCTP_TIMER_TYPE_NEWCOOKIE:
{
@ -1709,7 +1713,7 @@ sctp_timeout_handler(void *t)
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_ACK_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_ACK_TMR, SCTP_SO_NOT_LOCKED);
break;
case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
if ((stcb == NULL) || (inp == NULL)) {
@ -1717,7 +1721,7 @@ sctp_timeout_handler(void *t)
}
SCTP_STAT_INCR(sctps_timoshutdownguard);
sctp_abort_an_association(inp, stcb,
SCTP_SHUTDOWN_GUARD_EXPIRES, NULL);
SCTP_SHUTDOWN_GUARD_EXPIRES, NULL, SCTP_SO_NOT_LOCKED);
/* no need to unlock on tcb its gone */
goto out_decr;
@ -1730,7 +1734,7 @@ sctp_timeout_handler(void *t)
goto out_decr;
}
SCTP_STAT_INCR(sctps_timostrmrst);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_TMR, SCTP_SO_NOT_LOCKED);
break;
case SCTP_TIMER_TYPE_EARLYFR:
/* Need to do FR of things for net */
@ -1752,7 +1756,7 @@ sctp_timeout_handler(void *t)
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_ASCONF_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_ASCONF_TMR, SCTP_SO_NOT_LOCKED);
break;
case SCTP_TIMER_TYPE_AUTOCLOSE:
@ -1761,7 +1765,7 @@ sctp_timeout_handler(void *t)
}
SCTP_STAT_INCR(sctps_timoautoclose);
sctp_autoclose_timer(inp, stcb, net);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED);
did_output = 0;
break;
case SCTP_TIMER_TYPE_ASOCKILL:
@ -1772,7 +1776,18 @@ sctp_timeout_handler(void *t)
/* Can we free it yet? */
SCTP_INP_DECR_REF(inp);
sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_1);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_2);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
/*
* free asoc, always unlocks (or destroy's) so prevent
* duplicate unlock or unlock of a free mtx :-0
@ -2829,12 +2844,21 @@ int sctp_asoc_change_wake = 0;
static void
sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
uint32_t error, void *data)
uint32_t error, void *data, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
struct mbuf *m_notify;
struct sctp_assoc_change *sac;
struct sctp_queued_to_read *control;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
/*
* First if we are are going down dump everything we can to the
* socket rcv queue.
@ -2863,8 +2887,27 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
stcb->sctp_socket->so_error = ECONNRESET;
}
/* Wake ANY sleepers */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
if (!so_locked) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
}
#endif
sorwakeup(stcb->sctp_socket);
sowwakeup(stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
SCTP_SOCKET_UNLOCK(so, 1);
}
#endif
sctp_asoc_change_wake++;
}
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
@ -2903,10 +2946,29 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
control->spec_flags = M_NOTIFICATION;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, so_locked);
if (event == SCTP_COMM_LOST) {
/* Wake up any sleeper */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
if (!so_locked) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
}
#endif
sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
SCTP_SOCKET_UNLOCK(so, 1);
}
#endif
}
}
@ -2970,13 +3032,17 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
}
static void
sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
struct sctp_tmit_chunk *chk)
struct sctp_tmit_chunk *chk, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
struct mbuf *m_notify;
struct sctp_send_failed *ssf;
@ -3036,13 +3102,17 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
control->spec_flags = M_NOTIFICATION;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, so_locked);
}
static void
sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
struct sctp_stream_queue_pending *sp)
struct sctp_stream_queue_pending *sp, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
struct mbuf *m_notify;
struct sctp_send_failed *ssf;
@ -3102,7 +3172,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
control->spec_flags = M_NOTIFICATION;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, so_locked);
}
@ -3149,7 +3219,7 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb,
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
}
/* This always must be called with the read-queue LOCKED in the INP */
@ -3242,7 +3312,24 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
/* mark socket closed for read/write and wakeup! */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(stcb->sctp_ep);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
#endif
socantsendmore(stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
/* event not enabled */
@ -3276,7 +3363,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
}
static void
@ -3344,13 +3431,17 @@ sctp_notify_stream_reset(struct sctp_tcb *stcb,
control->tail_mbuf = m_notify;
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1);
&stcb->sctp_socket->so_rcv, 1, SCTP_SO_NOT_LOCKED);
}
void
sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
uint32_t error, void *data)
uint32_t error, void *data, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
if (stcb == NULL) {
/* unlikely but */
@ -3379,7 +3470,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, NULL);
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)) {
@ -3387,7 +3478,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, NULL);
sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, so_locked);
break;
case SCTP_NOTIFY_INTERFACE_DOWN:
{
@ -3418,11 +3509,11 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
}
case SCTP_NOTIFY_SPECIAL_SP_FAIL:
sctp_notify_send_failed2(stcb, error,
(struct sctp_stream_queue_pending *)data);
(struct sctp_stream_queue_pending *)data, so_locked);
break;
case SCTP_NOTIFY_DG_FAIL:
sctp_notify_send_failed(stcb, error,
(struct sctp_tmit_chunk *)data);
(struct sctp_tmit_chunk *)data, so_locked);
break;
case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION:
{
@ -3438,9 +3529,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, NULL);
sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, NULL, so_locked);
} else {
sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, NULL);
sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, NULL, so_locked);
}
break;
case SCTP_NOTIFY_PEER_OPENED_STREAM:
@ -3448,7 +3539,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, data);
sctp_notify_assoc_change(SCTP_RESTART, stcb, error, data, so_locked);
break;
case SCTP_NOTIFY_HB_RESP:
break;
@ -3505,7 +3596,11 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
}
void
sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock)
sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
struct sctp_association *asoc;
struct sctp_stream_out *outs;
@ -3546,7 +3641,7 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock)
}
sctp_free_bufspace(stcb, asoc, chk, 1);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
SCTP_NOTIFY_DATAGRAM_SENT, chk);
SCTP_NOTIFY_DATAGRAM_SENT, chk, so_locked);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
@ -3574,7 +3669,7 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock)
}
}
sctp_free_bufspace(stcb, asoc, chk, 1);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk, so_locked);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
@ -3595,7 +3690,7 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock)
TAILQ_REMOVE(&outs->outqueue, sp, next);
sctp_free_spbufspace(stcb, asoc, sp);
sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb,
SCTP_NOTIFY_DATAGRAM_UNSENT, (void *)sp);
SCTP_NOTIFY_DATAGRAM_UNSENT, (void *)sp, so_locked);
if (sp->data) {
sctp_m_freem(sp->data);
sp->data = NULL;
@ -3616,7 +3711,11 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock)
}
void
sctp_abort_notification(struct sctp_tcb *stcb, int error)
sctp_abort_notification(struct sctp_tcb *stcb, int error, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
if (stcb == NULL) {
@ -3628,13 +3727,13 @@ sctp_abort_notification(struct sctp_tcb *stcb, int error)
return;
}
/* Tell them we lost the asoc */
sctp_report_all_outbound(stcb, 1);
sctp_report_all_outbound(stcb, 1, so_locked);
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED;
}
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL);
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL, so_locked);
}
void
@ -3644,11 +3743,16 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
{
uint32_t vtag;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
vtag = 0;
if (stcb != NULL) {
/* We have a TCB to abort, send notification too */
vtag = stcb->asoc.peer_vtag;
sctp_abort_notification(stcb, 0);
sctp_abort_notification(stcb, 0, 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;
@ -3656,7 +3760,18 @@ sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_send_abort(m, iphlen, sh, vtag, op_err, vrf_id);
if (stcb != NULL) {
/* Ok, now lets free it */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_4);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
} else {
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
@ -3733,10 +3848,23 @@ 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)
int error, struct mbuf *op_err,
int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
uint32_t vtag;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(inp);
#endif
if (stcb == NULL) {
/* Got to have a TCB */
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
@ -3752,9 +3880,9 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
vtag = stcb->asoc.peer_vtag;
/* notify the ulp */
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)
sctp_abort_notification(stcb, error);
sctp_abort_notification(stcb, error, so_locked);
/* notify the peer */
sctp_send_abort_tcb(stcb, op_err);
sctp_send_abort_tcb(stcb, op_err, so_locked);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@ -3763,8 +3891,22 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* now free the asoc */
#ifdef SCTP_ASOCLOG_OF_TSNS
sctp_print_out_track_log(stcb);
#endif
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
}
#endif
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_5);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
SCTP_SOCKET_UNLOCK(so, 1);
}
#endif
}
void
@ -4105,7 +4247,12 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_queued_to_read *control,
struct sockbuf *sb,
int end)
int end,
int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
/*
* Here we must place the control on the end of the socket read
@ -4172,8 +4319,30 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
if (inp && inp->sctp_socket) {
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
} else
} else {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(inp);
if (!so_locked) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
SCTP_SOCKET_UNLOCK(so, 1);
return;
}
}
#endif
sctp_sorwakeup(inp, inp->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
SCTP_SOCKET_UNLOCK(so, 1);
}
#endif
}
}
}
@ -4296,8 +4465,26 @@ sctp_append_to_readq(struct sctp_inpcb *inp,
if (inp && inp->sctp_socket) {
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
} else
} else {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
so = SCTP_INP_SO(inp);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
SCTP_SOCKET_UNLOCK(so, 1);
return (0);
}
#endif
sctp_sorwakeup(inp, inp->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
}
}
return (0);
}
@ -4367,7 +4554,11 @@ sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
int
sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
int reason, struct sctpchunk_listhead *queue)
int reason, struct sctpchunk_listhead *queue, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
int ret_sz = 0;
int notdone;
@ -4377,11 +4568,38 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
ret_sz += tp1->book_size;
tp1->sent = SCTP_FORWARD_TSN_SKIP;
if (tp1->data) {
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1, SCTP_SO_NOT_LOCKED);
sctp_m_freem(tp1->data);
tp1->data = NULL;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
so = SCTP_INP_SO(stcb->sctp_ep);
if (!so_locked) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
SCTP_SOCKET_LOCK(so, 1);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
/*
* assoc was freed while we were
* unlocked
*/
SCTP_SOCKET_UNLOCK(so, 1);
return (ret_sz);
}
}
#endif
sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
if (!so_locked) {
SCTP_SOCKET_UNLOCK(so, 1);
}
#endif
}
if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
stcb->asoc.sent_queue_cnt_removeable--;
@ -4423,7 +4641,7 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
*/
if (tp1) {
ret_sz += sctp_release_pr_sctp_chunk(stcb, tp1, reason,
&stcb->asoc.send_queue);
&stcb->asoc.send_queue, so_locked);
} else {
SCTP_PRINTF("hmm, nothing on the send queue and no EOM?\n");
}
@ -4627,7 +4845,7 @@ sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t * freed_so_far, int hold_rlock,
SCTP_STAT_INCR(sctps_wu_sacks_sent);
sctp_send_sack(stcb);
sctp_chunk_output(stcb->sctp_ep, stcb,
SCTP_OUTPUT_FROM_USR_RCVD);
SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED);
/* make sure no timer is running */
sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_6);
SCTP_TCB_UNLOCK(stcb);

View File

@ -104,7 +104,12 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_queued_to_read *control,
struct sockbuf *sb,
int end);
int end,
int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
int
sctp_append_to_readq(struct sctp_inpcb *inp,
@ -139,7 +144,12 @@ int sctp_add_pad_tombuf(struct mbuf *, int);
int sctp_pad_lastmbuf(struct mbuf *, int, struct mbuf *);
void sctp_ulp_notify(uint32_t, struct sctp_tcb *, uint32_t, void *);
void
sctp_ulp_notify(uint32_t, struct sctp_tcb *, uint32_t, void *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
void
sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
@ -149,11 +159,21 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
void sctp_stop_timers_for_shutdown(struct sctp_tcb *);
void sctp_report_all_outbound(struct sctp_tcb *, int);
void
sctp_report_all_outbound(struct sctp_tcb *, int, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
int sctp_expand_mapping_array(struct sctp_association *, uint32_t);
void sctp_abort_notification(struct sctp_tcb *, int);
void
sctp_abort_notification(struct sctp_tcb *, int, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
/* We abort responding to an IP packet for some reason */
void
@ -164,7 +184,11 @@ 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,
struct mbuf *);
struct mbuf *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
void
sctp_handle_ootb(struct mbuf *, int, int, struct sctphdr *,
@ -211,7 +235,11 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
int
sctp_release_pr_sctp_chunk(struct sctp_tcb *, struct sctp_tmit_chunk *,
int, struct sctpchunk_listhead *);
int, struct sctpchunk_listhead *, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
);
struct mbuf *sctp_generate_invmanparam(int);

View File

@ -139,7 +139,7 @@ sctp6_input(struct mbuf **i_pak, int *offp, int proto)
/* in6p's ref-count increased && stcb locked */
if ((in6p) && (stcb)) {
sctp_send_packet_dropped(stcb, net, m, iphlen, 1);
sctp_chunk_output((struct sctp_inpcb *)in6p, stcb, 2);
sctp_chunk_output((struct sctp_inpcb *)in6p, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
} else if ((in6p != NULL) && (stcb == NULL)) {
refcount_up = 1;
}
@ -911,7 +911,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
/* initialize authentication parameters for the assoc */
sctp_initialize_auth_params(inp, stcb);
sctp_send_initiate(inp, stcb);
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
return error;
}