Code cleanup: Use LIST_FOREACH, LIST_FOREACH_SAFE, TAILQ_FOREACH,

TAILQ_FOREACH_SAFE where appropriate.
No functional change.

MFC after: 3 months.
This commit is contained in:
Michael Tuexen 2010-12-30 16:56:20 +00:00
parent 8ced7318a0
commit 4a9ef3f833
9 changed files with 441 additions and 740 deletions

View File

@ -656,19 +656,16 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
/* delete old cache */
SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: Now processing firstASCONF. Try to delte old cache\n");
ack = TAILQ_FIRST(&stcb->asoc.asconf_ack_sent);
while (ack != NULL) {
ack_next = TAILQ_NEXT(ack, next);
TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) {
if (ack->serial_number == serial_num)
break;
SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: delete old(%u) < first(%u)\n",
ack->serial_number, serial_num);
TAILQ_REMOVE(&stcb->asoc.asconf_ack_sent, ack, next);
TAILQ_REMOVE(&asoc->asconf_ack_sent, ack, next);
if (ack->data != NULL) {
sctp_m_freem(ack->data);
}
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack);
ack = ack_next;
}
}
m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0,
@ -1264,9 +1261,7 @@ sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
struct sockaddr *sa;
/* make sure the request isn't already in the queue */
for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
aa = aa_next) {
aa_next = TAILQ_NEXT(aa, next);
TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
/* address match? */
if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0)
continue;
@ -1480,9 +1475,7 @@ sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
return (-1);
}
/* make sure the request isn't already in the queue */
for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
aa = aa_next) {
aa_next = TAILQ_NEXT(aa, next);
TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
/* address match? */
if (sctp_asconf_addr_match(aa, sa) == 0)
continue;
@ -1836,9 +1829,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
*/
if (last_error_id == 0)
last_error_id--;/* set to "max" value */
for (aa = TAILQ_FIRST(&stcb->asoc.asconf_queue); aa != NULL;
aa = aa_next) {
aa_next = TAILQ_NEXT(aa, next);
TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
if (aa->sent == 1) {
/*
* implicitly successful or failed if correlation_id
@ -2098,14 +2089,11 @@ sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val)
}
}
} else if (l->action == SCTP_DEL_IP_ADDRESS) {
laddr = LIST_FIRST(&inp->sctp_addr_list);
while (laddr) {
nladdr = LIST_NEXT(laddr, sctp_nxt_addr);
LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
/* remove only after all guys are done */
if (laddr->ifa == ifa) {
sctp_del_local_addr_ep(inp, ifa);
}
laddr = nladdr;
}
}
}
@ -2285,12 +2273,10 @@ sctp_asconf_iterator_end(void *ptr, uint32_t val)
{
struct sctp_asconf_iterator *asc;
struct sctp_ifa *ifa;
struct sctp_laddr *l, *l_next;
struct sctp_laddr *l, *nl;
asc = (struct sctp_asconf_iterator *)ptr;
l = LIST_FIRST(&asc->list_of_work);
while (l != NULL) {
l_next = LIST_NEXT(l, sctp_nxt_addr);
LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) {
ifa = l->ifa;
if (l->action == SCTP_ADD_IP_ADDRESS) {
/* Clear the defer use flag */
@ -2299,7 +2285,6 @@ sctp_asconf_iterator_end(void *ptr, uint32_t val)
sctp_free_ifa(ifa);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l);
SCTP_DECR_LADDR_COUNT();
l = l_next;
}
SCTP_FREE(asc, SCTP_M_ASC_IT);
}
@ -2394,11 +2379,7 @@ sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
add_cnt = del_cnt = 0;
last_param_type = 0;
for (chk = TAILQ_FIRST(&stcb->asoc.asconf_send_queue); chk != NULL;
chk = nchk) {
/* get next chk */
nchk = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) {
if (chk->data == NULL) {
SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n");
continue;

View File

@ -77,9 +77,9 @@ static int __sctp_thread_based_iterator_started = 0;
static void
sctp_cleanup_itqueue(void)
{
struct sctp_iterator *it;
struct sctp_iterator *it, *nit;
while ((it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead)) != NULL) {
TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
if (it->function_atend != NULL) {
(*it->function_atend) (it->pointer, it->val);
}

View File

@ -344,13 +344,12 @@ sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn)
static void
sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
{
struct sctp_tmit_chunk *chk;
struct sctp_tmit_chunk *chk, *nchk;
uint16_t nxt_todel;
uint16_t stream_no;
int end = 0;
int cntDel;
struct sctp_queued_to_read *control, *ctl, *ctlat;
struct sctp_queued_to_read *control, *ctl, *nctl;
if (stcb == NULL)
return;
@ -362,8 +361,7 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
/* socket above is long gone or going.. */
abandon:
asoc->fragmented_delivery_inprogress = 0;
chk = TAILQ_FIRST(&asoc->reasmqueue);
while (chk) {
TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
asoc->size_on_reasm_queue -= chk->send_size;
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
@ -378,16 +376,11 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
/* Now free the address and data */
sctp_free_a_chunk(stcb, chk);
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->reasmqueue);
}
return;
}
SCTP_TCB_LOCK_ASSERT(stcb);
do {
chk = TAILQ_FIRST(&asoc->reasmqueue);
if (chk == NULL) {
return;
}
TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
if (chk->rec.data.TSN_seq != (asoc->tsn_last_delivered + 1)) {
/* Can't deliver more :< */
return;
@ -496,33 +489,26 @@ sctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
strm = &asoc->strmin[stream_no];
nxt_todel = strm->last_sequence_delivered + 1;
ctl = TAILQ_FIRST(&strm->inqueue);
if (ctl && (nxt_todel == ctl->sinfo_ssn)) {
while (ctl != NULL) {
/* Deliver more if we can. */
if (nxt_todel == ctl->sinfo_ssn) {
ctlat = TAILQ_NEXT(ctl, next);
TAILQ_REMOVE(&strm->inqueue, ctl, next);
asoc->size_on_all_streams -= ctl->length;
sctp_ucount_decr(asoc->cnt_on_all_streams);
strm->last_sequence_delivered++;
sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
sctp_add_to_readq(stcb->sctp_ep, stcb,
ctl,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
ctl = ctlat;
} else {
break;
}
nxt_todel = strm->last_sequence_delivered + 1;
TAILQ_FOREACH_SAFE(ctl, &strm->inqueue, next, nctl) {
/* Deliver more if we can. */
if (nxt_todel == ctl->sinfo_ssn) {
TAILQ_REMOVE(&strm->inqueue, ctl, next);
asoc->size_on_all_streams -= ctl->length;
sctp_ucount_decr(asoc->cnt_on_all_streams);
strm->last_sequence_delivered++;
sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
sctp_add_to_readq(stcb->sctp_ep, stcb,
ctl,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
} else {
break;
}
nxt_todel = strm->last_sequence_delivered + 1;
}
break;
}
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->reasmqueue);
} while (chk);
}
}
/*
@ -626,12 +612,10 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc,
control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
control = TAILQ_FIRST(&strm->inqueue);
while (control != NULL) {
TAILQ_FOREACH_SAFE(control, &strm->inqueue, next, at) {
/* all delivered */
nxt_todel = strm->last_sequence_delivered + 1;
if (nxt_todel == control->sinfo_ssn) {
at = TAILQ_NEXT(control, next);
TAILQ_REMOVE(&strm->inqueue, control, next);
asoc->size_on_all_streams -= control->length;
sctp_ucount_decr(asoc->cnt_on_all_streams);
@ -652,7 +636,6 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD,
SCTP_SO_NOT_LOCKED);
control = at;
continue;
}
break;
@ -756,7 +739,7 @@ sctp_is_all_msg_on_reasm(struct sctp_association *asoc, uint32_t * t_size)
return (0);
}
tsn = chk->rec.data.TSN_seq;
while (chk) {
TAILQ_FOREACH(chk, &asoc->reasmqueue, sctp_next) {
if (tsn != chk->rec.data.TSN_seq) {
return (0);
}
@ -765,7 +748,6 @@ sctp_is_all_msg_on_reasm(struct sctp_association *asoc, uint32_t * t_size)
return (1);
}
tsn++;
chk = TAILQ_NEXT(chk, sctp_next);
}
return (0);
}
@ -2090,14 +2072,14 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
/* first one on */
TAILQ_INSERT_TAIL(&asoc->pending_reply_queue, control, next);
} else {
struct sctp_queued_to_read *ctlOn;
struct sctp_queued_to_read *ctlOn,
*nctlOn;
unsigned char inserted = 0;
ctlOn = TAILQ_FIRST(&asoc->pending_reply_queue);
while (ctlOn) {
TAILQ_FOREACH_SAFE(ctlOn, &asoc->pending_reply_queue, next, nctlOn) {
if (compare_with_wrap(control->sinfo_tsn,
ctlOn->sinfo_tsn, MAX_TSN)) {
ctlOn = TAILQ_NEXT(ctlOn, next);
continue;
} else {
/* found it */
TAILQ_INSERT_BEFORE(ctlOn, control, next);
@ -2166,27 +2148,27 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
* pending_reply space 3: distribute any chunks in
* pending_reply_queue.
*/
struct sctp_queued_to_read *ctl;
struct sctp_queued_to_read *ctl, *nctl;
sctp_reset_in_stream(stcb, liste->number_entries, liste->req.list_of_streams);
TAILQ_REMOVE(&asoc->resetHead, liste, next_resp);
SCTP_FREE(liste, SCTP_M_STRESET);
/* sa_ignore FREED_MEMORY */
liste = TAILQ_FIRST(&asoc->resetHead);
ctl = TAILQ_FIRST(&asoc->pending_reply_queue);
if (ctl && (liste == NULL)) {
if (TAILQ_EMPTY(&asoc->resetHead)) {
/* All can be removed */
while (ctl) {
TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, next, nctl) {
TAILQ_REMOVE(&asoc->pending_reply_queue, ctl, next);
sctp_queue_data_to_stream(stcb, asoc, ctl, abort_flag);
if (*abort_flag) {
return (0);
}
ctl = TAILQ_FIRST(&asoc->pending_reply_queue);
}
} else if (ctl) {
/* more than one in queue */
while (!compare_with_wrap(ctl->sinfo_tsn, liste->tsn, MAX_TSN)) {
} else {
TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, next, nctl) {
if (compare_with_wrap(ctl->sinfo_tsn, liste->tsn, MAX_TSN)) {
break;
}
/*
* if ctl->sinfo_tsn is <= liste->tsn we can
* process it which is the NOT of
@ -2197,7 +2179,6 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (*abort_flag) {
return (0);
}
ctl = TAILQ_FIRST(&asoc->pending_reply_queue);
}
}
/*
@ -3143,8 +3124,7 @@ sctp_check_for_revoked(struct sctp_tcb *stcb,
struct sctp_tmit_chunk *tp1;
int tot_revoked = 0;
tp1 = TAILQ_FIRST(&asoc->sent_queue);
while (tp1) {
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
if (compare_with_wrap(tp1->rec.data.TSN_seq, cumack,
MAX_TSN)) {
/*
@ -3196,7 +3176,6 @@ sctp_check_for_revoked(struct sctp_tcb *stcb,
}
if (tp1->sent == SCTP_DATAGRAM_UNSENT)
break;
tp1 = TAILQ_NEXT(tp1, sctp_next);
}
if (tot_revoked > 0) {
/*
@ -3252,12 +3231,10 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (stcb->asoc.peer_supports_prsctp) {
(void)SCTP_GETTIME_TIMEVAL(&now);
}
tp1 = TAILQ_FIRST(&asoc->sent_queue);
while (tp1) {
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
strike_flag = 0;
if (tp1->no_fr_allowed) {
/* this one had a timeout or something */
tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
@ -3283,7 +3260,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
SCTP_SO_NOT_LOCKED);
}
tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
}
}
@ -3300,7 +3276,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
/* Continue strikin FWD-TSN chunks */
tp1->rec.data.fwd_tsn_cnt++;
}
tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
}
/*
@ -3313,7 +3288,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
* CMT, no data sent to this dest can be marked for
* FR using this SACK.
*/
tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
} else if (tp1->whoTo && compare_with_wrap(tp1->rec.data.TSN_seq,
tp1->whoTo->this_sack_highest_newack, MAX_TSN)) {
@ -3325,7 +3299,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
* this SACK. This step covers part of the DAC algo
* and the HTNA algo as well.
*/
tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
}
/*
@ -3546,7 +3519,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
/* Make sure to flag we had a FR */
tp1->whoTo->net_ack++;
tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
}
}
@ -3660,8 +3632,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
atomic_add_int(&alt->ref_count, 1);
}
}
tp1 = TAILQ_NEXT(tp1, sctp_next);
} /* while (tp1) */
}
if (tot_retrans > 0) {
/*
@ -3686,8 +3657,7 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
if (asoc->peer_supports_prsctp == 0) {
return (NULL);
}
tp1 = TAILQ_FIRST(&asoc->sent_queue);
while (tp1) {
TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
if (tp1->sent != SCTP_FORWARD_TSN_SKIP &&
tp1->sent != SCTP_DATAGRAM_RESEND) {
/* no chance to advance, out of here */
@ -3711,7 +3681,6 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
(void)SCTP_GETTIME_TIMEVAL(&now);
now_filled = 1;
}
tp2 = TAILQ_NEXT(tp1, sctp_next);
/*
* now we got a chunk which is marked for another
* retransmission to a PR-stream but has run out its chances
@ -3763,11 +3732,6 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
*/
break;
}
/*
* If we hit here we just dumped tp1, move to next tsn on
* sent queue.
*/
tp1 = tp2;
}
return (a_adv);
}
@ -3961,9 +3925,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
stcb->asoc.overall_error_count = 0;
if (compare_with_wrap(cumack, asoc->last_acked_seq, MAX_TSN)) {
/* process the new consecutive TSN first */
tp1 = TAILQ_FIRST(&asoc->sent_queue);
while (tp1) {
tp2 = TAILQ_NEXT(tp1, sctp_next);
TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
if (compare_with_wrap(cumack, tp1->rec.data.TSN_seq,
MAX_TSN) ||
cumack == tp1->rec.data.TSN_seq) {
@ -4051,6 +4013,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
/* sa_ignore NO_NULL_CHK */
sctp_free_bufspace(stcb, asoc, tp1, 1);
sctp_m_freem(tp1->data);
tp1->data = NULL;
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
sctp_log_sack(asoc->last_acked_seq,
@ -4060,10 +4023,8 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
0,
SCTP_LOG_FREE_SENT);
}
tp1->data = NULL;
asoc->sent_queue_cnt--;
sctp_free_a_chunk(stcb, tp1);
tp1 = tp2;
} else {
break;
}
@ -4612,8 +4573,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
net->will_exit_fast_recovery = 0;
}
/* process the new consecutive TSN first */
tp1 = TAILQ_FIRST(&asoc->sent_queue);
while (tp1) {
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
if (compare_with_wrap(last_tsn, tp1->rec.data.TSN_seq,
MAX_TSN) ||
last_tsn == tp1->rec.data.TSN_seq) {
@ -4725,7 +4685,6 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
} else {
break;
}
tp1 = TAILQ_NEXT(tp1, sctp_next);
}
biggest_tsn_newly_acked = biggest_tsn_acked = last_tsn;
/* always set this up to cum-ack */
@ -4899,36 +4858,32 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
} else if (asoc->saw_sack_with_frags) {
int cnt_revoked = 0;
tp1 = TAILQ_FIRST(&asoc->sent_queue);
if (tp1 != NULL) {
/* Peer revoked all dg's marked or acked */
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
if (tp1->sent == SCTP_DATAGRAM_ACKED) {
tp1->sent = SCTP_DATAGRAM_SENT;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
tp1->whoTo->flight_size,
tp1->book_size,
(uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_increase(tp1);
sctp_total_flight_increase(stcb, tp1);
tp1->rec.data.chunk_was_revoked = 1;
/*
* To ensure that this increase in
* flightsize, which is artificial,
* does not throttle the sender, we
* also increase the cwnd
* artificially.
*/
tp1->whoTo->cwnd += tp1->book_size;
cnt_revoked++;
/* Peer revoked all dg's marked or acked */
TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
if (tp1->sent == SCTP_DATAGRAM_ACKED) {
tp1->sent = SCTP_DATAGRAM_SENT;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
tp1->whoTo->flight_size,
tp1->book_size,
(uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_increase(tp1);
sctp_total_flight_increase(stcb, tp1);
tp1->rec.data.chunk_was_revoked = 1;
/*
* To ensure that this increase in
* flightsize, which is artificial, does not
* throttle the sender, we also increase the
* cwnd artificially.
*/
tp1->whoTo->cwnd += tp1->book_size;
cnt_revoked++;
}
if (cnt_revoked) {
reneged_all = 1;
}
}
if (cnt_revoked) {
reneged_all = 1;
}
asoc->saw_sack_with_frags = 0;
}
@ -5346,9 +5301,7 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
* First deliver anything prior to and including the stream no that
* came in
*/
ctl = TAILQ_FIRST(&strmin->inqueue);
while (ctl) {
nctl = TAILQ_NEXT(ctl, next);
TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next, nctl) {
if (compare_with_wrap(tt, ctl->sinfo_ssn, MAX_SEQ) ||
(tt == ctl->sinfo_ssn)) {
/* this is deliverable now */
@ -5367,16 +5320,13 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
/* no more delivery now. */
break;
}
ctl = nctl;
}
/*
* now we must deliver things in queue the normal way if any are
* now ready.
*/
tt = strmin->last_sequence_delivered + 1;
ctl = TAILQ_FIRST(&strmin->inqueue);
while (ctl) {
nctl = TAILQ_NEXT(ctl, next);
TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next, nctl) {
if (tt == ctl->sinfo_ssn) {
/* this is deliverable now */
TAILQ_REMOVE(&strmin->inqueue, ctl, next);
@ -5396,7 +5346,6 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
} else {
break;
}
ctl = nctl;
}
}
@ -5405,87 +5354,73 @@ sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
struct sctp_association *asoc,
uint16_t stream, uint16_t seq)
{
struct sctp_tmit_chunk *chk, *at;
struct sctp_tmit_chunk *chk, *nchk;
if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
/* For each one on here see if we need to toss it */
/* For each one on here see if we need to toss it */
/*
* For now large messages held on the reasmqueue that are complete
* will be tossed too. We could in theory do more work to spin
* through and stop after dumping one msg aka seeing the start of a
* new msg at the head, and call the delivery function... to see if
* it can be delivered... But for now we just dump everything on the
* queue.
*/
TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
/*
* For now large messages held on the reasmqueue that are
* complete will be tossed too. We could in theory do more
* work to spin through and stop after dumping one msg aka
* seeing the start of a new msg at the head, and call the
* delivery function... to see if it can be delivered... But
* for now we just dump everything on the queue.
* Do not toss it if on a different stream or marked for
* unordered delivery in which case the stream sequence
* number has no meaning.
*/
chk = TAILQ_FIRST(&asoc->reasmqueue);
while (chk) {
at = TAILQ_NEXT(chk, sctp_next);
/*
* Do not toss it if on a different stream or marked
* for unordered delivery in which case the stream
* sequence number has no meaning.
*/
if ((chk->rec.data.stream_number != stream) ||
((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED)) {
chk = at;
continue;
if ((chk->rec.data.stream_number != stream) ||
((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED)) {
continue;
}
if (chk->rec.data.stream_seq == seq) {
/* It needs to be tossed */
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
if (compare_with_wrap(chk->rec.data.TSN_seq,
asoc->tsn_last_delivered, MAX_TSN)) {
asoc->tsn_last_delivered = chk->rec.data.TSN_seq;
asoc->str_of_pdapi = chk->rec.data.stream_number;
asoc->ssn_of_pdapi = chk->rec.data.stream_seq;
asoc->fragment_flags = chk->rec.data.rcv_flags;
}
if (chk->rec.data.stream_seq == seq) {
/* It needs to be tossed */
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
if (compare_with_wrap(chk->rec.data.TSN_seq,
asoc->tsn_last_delivered, MAX_TSN)) {
asoc->tsn_last_delivered =
chk->rec.data.TSN_seq;
asoc->str_of_pdapi =
chk->rec.data.stream_number;
asoc->ssn_of_pdapi =
chk->rec.data.stream_seq;
asoc->fragment_flags =
chk->rec.data.rcv_flags;
}
asoc->size_on_reasm_queue -= chk->send_size;
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
asoc->size_on_reasm_queue -= chk->send_size;
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
/* Clear up any stream problem */
if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
SCTP_DATA_UNORDERED &&
(compare_with_wrap(chk->rec.data.stream_seq,
asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered,
MAX_SEQ))) {
/*
* We must dump forward this streams
* sequence number if the chunk is
* not unordered that is being
* skipped. There is a chance that
* if the peer does not include the
* last fragment in its FWD-TSN we
* WILL have a problem here since
* you would have a partial chunk in
* queue that may not be
* deliverable. Also if a Partial
* delivery API as started the user
* may get a partial chunk. The next
* read returning a new chunk...
* really ugly but I see no way
* around it! Maybe a notify??
*/
asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered =
chk->rec.data.stream_seq;
}
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
sctp_free_a_chunk(stcb, chk);
} else if (compare_with_wrap(chk->rec.data.stream_seq, seq, MAX_SEQ)) {
/* Clear up any stream problem */
if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
SCTP_DATA_UNORDERED &&
(compare_with_wrap(chk->rec.data.stream_seq,
asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered,
MAX_SEQ))) {
/*
* If the stream_seq is > than the purging
* one, we are done
* We must dump forward this streams
* sequence number if the chunk is not
* unordered that is being skipped. There is
* a chance that if the peer does not
* include the last fragment in its FWD-TSN
* we WILL have a problem here since you
* would have a partial chunk in queue that
* may not be deliverable. Also if a Partial
* delivery API as started the user may get
* a partial chunk. The next read returning
* a new chunk... really ugly but I see no
* way around it! Maybe a notify??
*/
break;
asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered = chk->rec.data.stream_seq;
}
chk = at;
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
sctp_free_a_chunk(stcb, chk);
} else if (compare_with_wrap(chk->rec.data.stream_seq, seq, MAX_SEQ)) {
/*
* If the stream_seq is > than the purging one, we
* are done
*/
break;
}
}
}
@ -5524,7 +5459,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
unsigned int i, fwd_sz, cumack_set_flag, m_size;
uint32_t str_seq;
struct sctp_stream_in *strm;
struct sctp_tmit_chunk *chk, *at;
struct sctp_tmit_chunk *chk, *nchk;
struct sctp_queued_to_read *ctl, *sv;
cumack_set_flag = 0;
@ -5618,77 +5553,64 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
if (asoc->fragmented_delivery_inprogress) {
sctp_service_reassembly(stcb, asoc);
}
if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
/* For each one on here see if we need to toss it */
/*
* For now large messages held on the reasmqueue that are
* complete will be tossed too. We could in theory do more
* work to spin through and stop after dumping one msg aka
* seeing the start of a new msg at the head, and call the
* delivery function... to see if it can be delivered... But
* for now we just dump everything on the queue.
*/
chk = TAILQ_FIRST(&asoc->reasmqueue);
while (chk) {
at = TAILQ_NEXT(chk, sctp_next);
if ((compare_with_wrap(new_cum_tsn,
chk->rec.data.TSN_seq, MAX_TSN)) ||
(new_cum_tsn == chk->rec.data.TSN_seq)) {
/* It needs to be tossed */
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
if (compare_with_wrap(chk->rec.data.TSN_seq,
asoc->tsn_last_delivered, MAX_TSN)) {
asoc->tsn_last_delivered =
chk->rec.data.TSN_seq;
asoc->str_of_pdapi =
chk->rec.data.stream_number;
asoc->ssn_of_pdapi =
chk->rec.data.stream_seq;
asoc->fragment_flags =
chk->rec.data.rcv_flags;
}
asoc->size_on_reasm_queue -= chk->send_size;
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
/* Clear up any stream problem */
if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
SCTP_DATA_UNORDERED &&
(compare_with_wrap(chk->rec.data.stream_seq,
asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered,
MAX_SEQ))) {
/*
* We must dump forward this streams
* sequence number if the chunk is
* not unordered that is being
* skipped. There is a chance that
* if the peer does not include the
* last fragment in its FWD-TSN we
* WILL have a problem here since
* you would have a partial chunk in
* queue that may not be
* deliverable. Also if a Partial
* delivery API as started the user
* may get a partial chunk. The next
* read returning a new chunk...
* really ugly but I see no way
* around it! Maybe a notify??
*/
asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered =
chk->rec.data.stream_seq;
}
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
sctp_free_a_chunk(stcb, chk);
} else {
/*
* Ok we have gone beyond the end of the
* fwd-tsn's mark.
*/
break;
/* For each one on here see if we need to toss it */
/*
* For now large messages held on the reasmqueue that are complete
* will be tossed too. We could in theory do more work to spin
* through and stop after dumping one msg aka seeing the start of a
* new msg at the head, and call the delivery function... to see if
* it can be delivered... But for now we just dump everything on the
* queue.
*/
TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
if ((compare_with_wrap(new_cum_tsn,
chk->rec.data.TSN_seq, MAX_TSN)) ||
(new_cum_tsn == chk->rec.data.TSN_seq)) {
/* It needs to be tossed */
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
if (compare_with_wrap(chk->rec.data.TSN_seq,
asoc->tsn_last_delivered, MAX_TSN)) {
asoc->tsn_last_delivered = chk->rec.data.TSN_seq;
asoc->str_of_pdapi = chk->rec.data.stream_number;
asoc->ssn_of_pdapi = chk->rec.data.stream_seq;
asoc->fragment_flags = chk->rec.data.rcv_flags;
}
chk = at;
asoc->size_on_reasm_queue -= chk->send_size;
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
/* Clear up any stream problem */
if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
SCTP_DATA_UNORDERED &&
(compare_with_wrap(chk->rec.data.stream_seq,
asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered,
MAX_SEQ))) {
/*
* We must dump forward this streams
* sequence number if the chunk is not
* unordered that is being skipped. There is
* a chance that if the peer does not
* include the last fragment in its FWD-TSN
* we WILL have a problem here since you
* would have a partial chunk in queue that
* may not be deliverable. Also if a Partial
* delivery API as started the user may get
* a partial chunk. The next read returning
* a new chunk... really ugly but I see no
* way around it! Maybe a notify??
*/
asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered = chk->rec.data.stream_seq;
}
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
sctp_free_a_chunk(stcb, chk);
} else {
/*
* Ok we have gone beyond the end of the fwd-tsn's
* mark.
*/
break;
}
}
/*******************************************************/

View File

@ -193,7 +193,7 @@ int
sctp_is_there_unsent_data(struct sctp_tcb *stcb)
{
int unsent_data = 0;
struct sctp_stream_queue_pending *sp;
struct sctp_stream_queue_pending *sp, *nsp;
struct sctp_stream_out *strq;
struct sctp_association *asoc;
@ -205,15 +205,9 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb)
*/
asoc = &stcb->asoc;
SCTP_TCB_SEND_LOCK(stcb);
if (!TAILQ_EMPTY(&asoc->out_wheel)) {
/* Check to see if some data queued */
TAILQ_FOREACH(strq, &asoc->out_wheel, next_spoke) {
is_there_another:
/* sa_ignore FREED_MEMORY */
sp = TAILQ_FIRST(&strq->outqueue);
if (sp == NULL) {
continue;
}
TAILQ_FOREACH(strq, &asoc->out_wheel, next_spoke) {
/* sa_ignore FREED_MEMORY */
TAILQ_FOREACH_SAFE(sp, &strq->outqueue, next, nsp) {
if ((sp->msg_is_complete) &&
(sp->length == 0) &&
(sp->sender_all_done)) {
@ -230,7 +224,7 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb)
sp->msg_is_complete,
sp->put_last_out);
}
atomic_subtract_int(&stcb->asoc.stream_queue_cnt, 1);
atomic_subtract_int(&asoc->stream_queue_cnt, 1);
TAILQ_REMOVE(&strq->outqueue, sp, next);
if (sp->net) {
sctp_free_remote_addr(sp->net);
@ -241,10 +235,9 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb)
sp->data = NULL;
}
sctp_free_a_strmoq(stcb, sp);
goto is_there_another;
} else {
unsent_data++;
continue;
break;
}
}
}
@ -280,38 +273,32 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) {
unsigned int newcnt;
struct sctp_stream_out *outs;
struct sctp_stream_queue_pending *sp;
struct sctp_tmit_chunk *chk, *chk_next;
struct sctp_stream_queue_pending *sp, *nsp;
struct sctp_tmit_chunk *chk, *nchk;
/* abandon the upper streams */
newcnt = ntohs(init->num_inbound_streams);
if (!TAILQ_EMPTY(&asoc->send_queue)) {
chk = TAILQ_FIRST(&asoc->send_queue);
while (chk) {
chk_next = TAILQ_NEXT(chk, sctp_next);
if (chk->rec.data.stream_number >= newcnt) {
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
asoc->send_queue_cnt--;
if (chk->data != NULL) {
sctp_free_bufspace(stcb, asoc, chk, 1);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
SCTP_NOTIFY_DATAGRAM_UNSENT, chk, SCTP_SO_NOT_LOCKED);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
if (chk->rec.data.stream_number >= newcnt) {
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
asoc->send_queue_cnt--;
if (chk->data != NULL) {
sctp_free_bufspace(stcb, asoc, chk, 1);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
SCTP_NOTIFY_DATAGRAM_UNSENT, chk, SCTP_SO_NOT_LOCKED);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
sctp_free_a_chunk(stcb, chk);
/* sa_ignore FREED_MEMORY */
}
chk = chk_next;
sctp_free_a_chunk(stcb, chk);
/* sa_ignore FREED_MEMORY */
}
}
if (asoc->strmout) {
for (i = newcnt; i < asoc->pre_open_streams; i++) {
outs = &asoc->strmout[i];
sp = TAILQ_FIRST(&outs->outqueue);
while (sp) {
TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
TAILQ_REMOVE(&outs->outqueue, sp, next);
asoc->stream_queue_cnt--;
sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL,
@ -328,7 +315,6 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
/* Free the chunk */
sctp_free_a_strmoq(stcb, sp);
/* sa_ignore FREED_MEMORY */
sp = TAILQ_FIRST(&outs->outqueue);
}
}
}
@ -355,18 +341,16 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
if (asoc->strmin != NULL) {
/* Free the old ones */
struct sctp_queued_to_read *ctl;
struct sctp_queued_to_read *ctl, *nctl;
for (i = 0; i < asoc->streamincnt; i++) {
ctl = TAILQ_FIRST(&asoc->strmin[i].inqueue);
while (ctl) {
TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) {
TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next);
sctp_free_remote_addr(ctl->whoFrom);
ctl->whoFrom = NULL;
sctp_m_freem(ctl->data);
ctl->data = NULL;
sctp_free_a_readq(stcb, ctl);
ctl = TAILQ_FIRST(&asoc->strmin[i].inqueue);
}
}
SCTP_FREE(asoc->strmin, SCTP_M_STRMI);
@ -456,13 +440,11 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
}
/* if the peer doesn't support asconf, flush the asconf queue */
if (asoc->peer_supports_asconf == 0) {
struct sctp_asconf_addr *aparam;
struct sctp_asconf_addr *param, *nparam;
while (!TAILQ_EMPTY(&asoc->asconf_queue)) {
/* sa_ignore FREED_MEMORY */
aparam = TAILQ_FIRST(&asoc->asconf_queue);
TAILQ_REMOVE(&asoc->asconf_queue, aparam, next);
SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) {
TAILQ_REMOVE(&asoc->asconf_queue, param, next);
SCTP_FREE(param, SCTP_M_ASC_ADDR);
}
}
stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs,
@ -2905,10 +2887,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
struct sctp_tmit_chunk *chk;
chk = TAILQ_FIRST(&asoc->sent_queue);
if (chk) {
sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, chk->whoTo);
}
sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo);
}
}
@ -2938,15 +2917,13 @@ sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
/* Find where it was sent, if possible */
net = NULL;
lchk = TAILQ_FIRST(&stcb->asoc.sent_queue);
while (lchk) {
TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) {
if (lchk->rec.data.TSN_seq == tsn) {
net = lchk->whoTo;
break;
}
if (compare_with_wrap(lchk->rec.data.TSN_seq, tsn, MAX_TSN))
break;
lchk = TAILQ_NEXT(lchk, sctp_next);
}
if (net == NULL)
/* default is we use the primary */
@ -3078,8 +3055,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
struct sctp_tmit_chunk *tp1;
tsn = ntohl(desc->tsn_ifany);
tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
while (tp1) {
TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
if (tp1->rec.data.TSN_seq == tsn) {
/* found it */
break;
@ -3090,7 +3066,6 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
tp1 = NULL;
break;
}
tp1 = TAILQ_NEXT(tp1, sctp_next);
}
if (tp1 == NULL) {
/*
@ -3098,13 +3073,11 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
* attention to queue seq order.
*/
SCTP_STAT_INCR(sctps_pdrpdnfnd);
tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
while (tp1) {
TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
if (tp1->rec.data.TSN_seq == tsn) {
/* found it */
break;
}
tp1 = TAILQ_NEXT(tp1, sctp_next);
}
}
if (tp1 == NULL) {
@ -3755,7 +3728,7 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch
uint16_t num_stream, i;
uint32_t seq;
struct sctp_association *asoc = &stcb->asoc;
struct sctp_queued_to_read *ctl;
struct sctp_queued_to_read *ctl, *nctl;
/* Get the number. */
seq = ntohl(str_add->request_seq);
@ -3789,8 +3762,7 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch
stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered;
stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started;
/* now anything on those queues? */
while (TAILQ_EMPTY(&oldstrm[i].inqueue) == 0) {
ctl = TAILQ_FIRST(&oldstrm[i].inqueue);
TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) {
TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next);
TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next);
}
@ -4965,11 +4937,7 @@ __attribute__((noinline))
struct sctp_tmit_chunk *chk;
chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
if (chk) {
sctp_timer_start(SCTP_TIMER_TYPE_SEND,
stcb->sctp_ep, stcb,
chk->whoTo);
}
sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo);
}
}
break;

View File

@ -5718,9 +5718,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
} /* if chunk has enabled */
} /* tailqforeach */
chk = TAILQ_FIRST(&asoc->send_queue);
while (chk) {
nchk = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
/* Here we must move to the sent queue and mark */
if (PR_SCTP_BUF_ENABLED(chk->flags)) {
if (chk->rec.data.timetodrop.tv_sec >= (long)srcv->sinfo_timetolive) {
@ -5742,8 +5740,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
} /* end if chk->data */
} /* end if right class */
} /* end if chk pr-sctp */
chk = nchk;
} /* end while (chk) */
} /* tailqforeachsafe (chk) */
} /* if enabled in asoc */
}
@ -6445,9 +6442,7 @@ sctp_toss_old_cookies(struct sctp_tcb *stcb, struct sctp_association *asoc)
{
struct sctp_tmit_chunk *chk, *nchk;
chk = TAILQ_FIRST(&asoc->control_send_queue);
while (chk) {
nchk = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) {
if (chk->rec.chunk_id.id == SCTP_COOKIE_ECHO) {
TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
if (chk->data) {
@ -6457,7 +6452,6 @@ sctp_toss_old_cookies(struct sctp_tcb *stcb, struct sctp_association *asoc)
asoc->ctrl_queue_cnt--;
sctp_free_a_chunk(stcb, chk);
}
chk = nchk;
}
}
@ -6465,19 +6459,16 @@ void
sctp_toss_old_asconf(struct sctp_tcb *stcb)
{
struct sctp_association *asoc;
struct sctp_tmit_chunk *chk, *chk_tmp;
struct sctp_tmit_chunk *chk, *nchk;
struct sctp_asconf_chunk *acp;
asoc = &stcb->asoc;
for (chk = TAILQ_FIRST(&asoc->asconf_send_queue); chk != NULL;
chk = chk_tmp) {
/* get next chk */
chk_tmp = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH_SAFE(chk, &asoc->asconf_send_queue, sctp_next, nchk) {
/* find SCTP_ASCONF chunk in queue */
if (chk->rec.chunk_id.id == SCTP_ASCONF) {
if (chk->data) {
acp = mtod(chk->data, struct sctp_asconf_chunk *);
if (compare_with_wrap(ntohl(acp->serial_number), stcb->asoc.asconf_seq_out_acked, MAX_TSN)) {
if (compare_with_wrap(ntohl(acp->serial_number), asoc->asconf_seq_out_acked, MAX_TSN)) {
/* Not Acked yet */
break;
}
@ -6589,9 +6580,7 @@ sctp_clean_up_ctl(struct sctp_tcb *stcb, struct sctp_association *asoc)
{
struct sctp_tmit_chunk *chk, *nchk;
for (chk = TAILQ_FIRST(&asoc->control_send_queue);
chk; chk = nchk) {
nchk = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) {
if ((chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) ||
(chk->rec.chunk_id.id == SCTP_NR_SELECTIVE_ACK) || /* EY */
(chk->rec.chunk_id.id == SCTP_HEARTBEAT_REQUEST) ||
@ -7627,9 +7616,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
/* ASCONF transmission */
/************************/
/* Now first lets go through the asconf queue */
for (chk = TAILQ_FIRST(&asoc->asconf_send_queue);
chk; chk = nchk) {
nchk = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH_SAFE(chk, &asoc->asconf_send_queue, sctp_next, nchk) {
if (chk->rec.chunk_id.id != SCTP_ASCONF) {
continue;
}
@ -7805,9 +7792,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
/* Control transmission */
/************************/
/* Now first lets go through the control queue */
for (chk = TAILQ_FIRST(&asoc->control_send_queue);
chk; chk = nchk) {
nchk = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) {
if (chk->whoTo != net) {
/*
* No, not sent to the network we are
@ -8091,7 +8076,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
if ((((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) &&
(skip_data_for_this_net == 0)) ||
(cookie)) {
for (chk = TAILQ_FIRST(&asoc->send_queue); chk; chk = nchk) {
TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
if (no_data_chunks) {
/* let only control go out */
*reason_code = 1;
@ -8102,7 +8087,6 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
*reason_code = 2;
break;
}
nchk = TAILQ_NEXT(chk, sctp_next);
if ((chk->whoTo != NULL) &&
(chk->whoTo != net)) {
/* Don't send the chunk on this net */

View File

@ -3154,11 +3154,8 @@ sctp_iterator_inp_being_freed(struct sctp_inpcb *inp)
* may be still pending on the list
*/
SCTP_IPI_ITERATOR_WQ_LOCK();
it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead);
while (it) {
nit = TAILQ_NEXT(it, sctp_nxt_itr);
TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
if (it->vn != curvnet) {
it = nit;
continue;
}
if (it->inp == inp) {
@ -3183,7 +3180,6 @@ sctp_iterator_inp_being_freed(struct sctp_inpcb *inp)
*/
SCTP_INP_DECR_REF(inp);
}
it = nit;
}
SCTP_IPI_ITERATOR_WQ_UNLOCK();
}
@ -3206,11 +3202,9 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
struct inpcb *ip_pcb;
struct socket *so;
int being_refed = 0;
struct sctp_queued_to_read *sq;
struct sctp_queued_to_read *sq, *nsq;
int cnt;
sctp_sharedkey_t *shared_key;
sctp_sharedkey_t *shared_key, *nshared_key;
#ifdef SCTP_LOG_CLOSING
@ -3261,10 +3255,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
int cnt_in_sd;
cnt_in_sd = 0;
for ((asoc = LIST_FIRST(&inp->sctp_asoc_list)); asoc != NULL;
asoc = nasoc) {
LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_list, sctp_tcblist, nasoc) {
SCTP_TCB_LOCK(asoc);
nasoc = LIST_NEXT(asoc, sctp_tcblist);
if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
/* Skip guys being freed */
cnt_in_sd++;
@ -3463,10 +3455,8 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* have a contest on the INP lock.. which would cause us to die ...
*/
cnt = 0;
for ((asoc = LIST_FIRST(&inp->sctp_asoc_list)); asoc != NULL;
asoc = nasoc) {
LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_list, sctp_tcblist, nasoc) {
SCTP_TCB_LOCK(asoc);
nasoc = LIST_NEXT(asoc, sctp_tcblist);
if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
if (asoc->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE) {
asoc->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
@ -3581,7 +3571,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
inp->sctp_asocidhash = NULL;
}
/* sa_ignore FREED_MEMORY */
while ((sq = TAILQ_FIRST(&inp->read_queue)) != NULL) {
TAILQ_FOREACH_SAFE(sq, &inp->read_queue, next, nsq) {
/* Its only abandoned if it had data left */
if (sq->length)
SCTP_STAT_INCR(sctps_left_abandon);
@ -3638,12 +3628,10 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
if (inp->sctp_ep.local_hmacs != NULL)
sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
shared_key = LIST_FIRST(&inp->sctp_ep.shared_keys);
while (shared_key) {
LIST_FOREACH_SAFE(shared_key, &inp->sctp_ep.shared_keys, next, nshared_key) {
LIST_REMOVE(shared_key, next);
sctp_free_sharedkey(shared_key);
/* sa_ignore FREED_MEMORY */
shared_key = LIST_FIRST(&inp->sctp_ep.shared_keys);
}
/*
@ -3651,17 +3639,13 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* ifaddr's that are set into this ep. Again macro limitations here,
* since the LIST_FOREACH could be a bad idea.
*/
for ((laddr = LIST_FIRST(&inp->sctp_addr_list)); laddr != NULL;
laddr = nladdr) {
nladdr = LIST_NEXT(laddr, sctp_nxt_addr);
LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
sctp_remove_laddr(laddr);
}
#ifdef SCTP_TRACK_FREED_ASOCS
/* TEMP CODE */
for ((asoc = LIST_FIRST(&inp->sctp_asoc_free_list)); asoc != NULL;
asoc = nasoc) {
nasoc = LIST_NEXT(asoc, sctp_tcblist);
LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_free_list, sctp_tcblist, nasoc) {
LIST_REMOVE(asoc, sctp_tcblist);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), asoc);
SCTP_DECR_ASOC_COUNT();
@ -4359,13 +4343,12 @@ sctp_del_remote_addr(struct sctp_tcb *stcb, struct sockaddr *remaddr)
* no other addresses.
*/
struct sctp_association *asoc;
struct sctp_nets *net, *net_tmp;
struct sctp_nets *net, *nnet;
asoc = &stcb->asoc;
/* locate the address */
for (net = TAILQ_FIRST(&asoc->nets); net != NULL; net = net_tmp) {
net_tmp = TAILQ_NEXT(net, sctp_next);
TAILQ_FOREACH_SAFE(net, &asoc->nets, sctp_next, nnet) {
if (net->ro._l_addr.sa.sa_family != remaddr->sa_family) {
continue;
}
@ -4530,18 +4513,16 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
{
int i;
struct sctp_association *asoc;
struct sctp_nets *net, *prev;
struct sctp_laddr *laddr;
struct sctp_tmit_chunk *chk;
struct sctp_asconf_addr *aparam;
struct sctp_asconf_ack *aack;
struct sctp_stream_reset_list *liste;
struct sctp_queued_to_read *sq;
struct sctp_stream_queue_pending *sp;
sctp_sharedkey_t *shared_key;
struct sctp_nets *net, *nnet;
struct sctp_laddr *laddr, *naddr;
struct sctp_tmit_chunk *chk, *nchk;
struct sctp_asconf_addr *aparam, *naparam;
struct sctp_asconf_ack *aack, *naack;
struct sctp_stream_reset_list *strrst, *nstrrst;
struct sctp_queued_to_read *sq, *nsq;
struct sctp_stream_queue_pending *sp, *nsp;
sctp_sharedkey_t *shared_key, *nshared_key;
struct socket *so;
int ccnt = 0;
int cnt = 0;
/* first, lets purge the entry from the hash table. */
@ -4626,7 +4607,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
net->pmtu_timer.self = NULL;
}
/* Now the read queue needs to be cleaned up (only once) */
cnt = 0;
if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0) {
stcb->asoc.state |= SCTP_STATE_ABOUT_TO_BE_FREED;
SCTP_INP_READ_LOCK(inp);
@ -4665,12 +4645,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* Add an end to wake them */
sq->end_added = 1;
cnt++;
}
}
SCTP_INP_READ_UNLOCK(inp);
if (stcb->block_entry) {
cnt++;
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PCB, ECONNRESET);
stcb->block_entry->error = ECONNRESET;
stcb->block_entry = NULL;
@ -4808,7 +4786,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
asoc->strreset_timer.type = SCTP_TIMER_TYPE_NONE;
prev = NULL;
/*
* The chunk lists and such SHOULD be empty but we check them just
* in case.
@ -4819,8 +4796,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
outs = &asoc->strmout[i];
/* now clean up any chunks here */
sp = TAILQ_FIRST(&outs->outqueue);
while (sp) {
TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
TAILQ_REMOVE(&outs->outqueue, sp, next);
if (sp->data) {
if (so) {
@ -4846,18 +4822,14 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_strmoq), sp);
SCTP_DECR_STRMOQ_COUNT();
/* sa_ignore FREED_MEMORY */
sp = TAILQ_FIRST(&outs->outqueue);
}
}
/* sa_ignore FREED_MEMORY */
while ((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) {
TAILQ_REMOVE(&asoc->resetHead, liste, next_resp);
SCTP_FREE(liste, SCTP_M_STRESET);
TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) {
TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp);
SCTP_FREE(strrst, SCTP_M_STRESET);
}
sq = TAILQ_FIRST(&asoc->pending_reply_queue);
while (sq) {
TAILQ_FOREACH_SAFE(sq, &asoc->pending_reply_queue, next, nsq) {
TAILQ_REMOVE(&asoc->pending_reply_queue, sq, next);
if (sq->data) {
sctp_m_freem(sq->data);
@ -4870,11 +4842,8 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), sq);
SCTP_DECR_READQ_COUNT();
/* sa_ignore FREED_MEMORY */
sq = TAILQ_FIRST(&asoc->pending_reply_queue);
}
chk = TAILQ_FIRST(&asoc->free_chunks);
while (chk) {
TAILQ_FOREACH_SAFE(chk, &asoc->free_chunks, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->free_chunks, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
@ -4882,156 +4851,99 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
ccnt++;
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
atomic_subtract_int(&SCTP_BASE_INFO(ipi_free_chunks), 1);
asoc->free_chunk_cnt--;
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->free_chunks);
}
/* pending send queue SHOULD be empty */
if (!TAILQ_EMPTY(&asoc->send_queue)) {
chk = TAILQ_FIRST(&asoc->send_queue);
while (chk) {
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
if (chk->data) {
if (so) {
/* Still a socket? */
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
SCTP_NOTIFY_DATAGRAM_UNSENT, chk, SCTP_SO_LOCKED);
}
if (chk->data) {
if (so) {
/* Still a socket? */
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
SCTP_NOTIFY_DATAGRAM_UNSENT, chk, SCTP_SO_LOCKED);
}
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
sctp_m_freem(chk->data);
chk->data = NULL;
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
ccnt++;
if (chk->whoTo) {
sctp_free_remote_addr(chk->whoTo);
chk->whoTo = NULL;
}
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->send_queue);
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
if (chk->whoTo) {
sctp_free_remote_addr(chk->whoTo);
chk->whoTo = NULL;
}
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
}
/*
if (ccnt) {
printf("Freed %d from send_queue\n", ccnt);
ccnt = 0;
}
*/
/* sent queue SHOULD be empty */
if (!TAILQ_EMPTY(&asoc->sent_queue)) {
chk = TAILQ_FIRST(&asoc->sent_queue);
while (chk) {
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
if (chk->data) {
if (so) {
/* Still a socket? */
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
SCTP_NOTIFY_DATAGRAM_SENT, chk, SCTP_SO_LOCKED);
}
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
if (chk->data) {
if (so) {
/* Still a socket? */
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
SCTP_NOTIFY_DATAGRAM_SENT, chk, SCTP_SO_LOCKED);
}
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
ccnt++;
sctp_free_remote_addr(chk->whoTo);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->sent_queue);
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
sctp_free_remote_addr(chk->whoTo);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
}
/*
if (ccnt) {
printf("Freed %d from sent_queue\n", ccnt);
ccnt = 0;
}
*/
/* control queue MAY not be empty */
if (!TAILQ_EMPTY(&asoc->control_send_queue)) {
chk = TAILQ_FIRST(&asoc->control_send_queue);
while (chk) {
TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
ccnt++;
sctp_free_remote_addr(chk->whoTo);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->control_send_queue);
TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
sctp_free_remote_addr(chk->whoTo);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
}
/*
if (ccnt) {
printf("Freed %d from ctrl_queue\n", ccnt);
ccnt = 0;
}
*/
/* ASCONF queue MAY not be empty */
if (!TAILQ_EMPTY(&asoc->asconf_send_queue)) {
chk = TAILQ_FIRST(&asoc->asconf_send_queue);
while (chk) {
TAILQ_REMOVE(&asoc->asconf_send_queue, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
ccnt++;
sctp_free_remote_addr(chk->whoTo);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->asconf_send_queue);
TAILQ_FOREACH_SAFE(chk, &asoc->asconf_send_queue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->asconf_send_queue, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
sctp_free_remote_addr(chk->whoTo);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
}
/*
if (ccnt) {
printf("Freed %d from asconf_queue\n", ccnt);
ccnt = 0;
}
*/
if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
chk = TAILQ_FIRST(&asoc->reasmqueue);
while (chk) {
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
sctp_free_remote_addr(chk->whoTo);
ccnt++;
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->reasmqueue);
TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
if (chk->holds_key_ref)
sctp_auth_key_release(stcb, chk->auth_keyid);
sctp_free_remote_addr(chk->whoTo);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
SCTP_DECR_CHK_COUNT();
/* sa_ignore FREED_MEMORY */
}
/*
if (ccnt) {
printf("Freed %d from reasm_queue\n", ccnt);
ccnt = 0;
}
*/
if (asoc->mapping_array) {
SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
asoc->mapping_array = NULL;
@ -5047,66 +4959,50 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
asoc->strm_realoutsize = asoc->streamoutcnt = 0;
if (asoc->strmin) {
struct sctp_queued_to_read *ctl;
struct sctp_queued_to_read *ctl, *nctl;
for (i = 0; i < asoc->streamincnt; i++) {
if (!TAILQ_EMPTY(&asoc->strmin[i].inqueue)) {
/* We have somethings on the streamin queue */
ctl = TAILQ_FIRST(&asoc->strmin[i].inqueue);
while (ctl) {
TAILQ_REMOVE(&asoc->strmin[i].inqueue,
ctl, next);
sctp_free_remote_addr(ctl->whoFrom);
if (ctl->data) {
sctp_m_freem(ctl->data);
ctl->data = NULL;
}
/*
* We don't free the address here
* since all the net's were freed
* above.
*/
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl);
SCTP_DECR_READQ_COUNT();
ctl = TAILQ_FIRST(&asoc->strmin[i].inqueue);
TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) {
TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next);
sctp_free_remote_addr(ctl->whoFrom);
if (ctl->data) {
sctp_m_freem(ctl->data);
ctl->data = NULL;
}
/*
* We don't free the address here since all
* the net's were freed above.
*/
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl);
SCTP_DECR_READQ_COUNT();
}
}
SCTP_FREE(asoc->strmin, SCTP_M_STRMI);
asoc->strmin = NULL;
}
asoc->streamincnt = 0;
while (!TAILQ_EMPTY(&asoc->nets)) {
/* sa_ignore FREED_MEMORY */
net = TAILQ_FIRST(&asoc->nets);
/* pull from list */
if ((SCTP_BASE_INFO(ipi_count_raddr) == 0) || (prev == net)) {
TAILQ_FOREACH_SAFE(net, &asoc->nets, sctp_next, nnet) {
#ifdef INVARIANTS
if (SCTP_BASE_INFO(ipi_count_raddr) == 0) {
panic("no net's left alloc'ed, or list points to itself");
#endif
break;
}
prev = net;
#endif
TAILQ_REMOVE(&asoc->nets, net, sctp_next);
sctp_free_remote_addr(net);
}
while (!LIST_EMPTY(&asoc->sctp_restricted_addrs)) {
LIST_FOREACH_SAFE(laddr, &asoc->sctp_restricted_addrs, sctp_nxt_addr, naddr) {
/* sa_ignore FREED_MEMORY */
laddr = LIST_FIRST(&asoc->sctp_restricted_addrs);
sctp_remove_laddr(laddr);
}
/* pending asconf (address) parameters */
while (!TAILQ_EMPTY(&asoc->asconf_queue)) {
TAILQ_FOREACH_SAFE(aparam, &asoc->asconf_queue, next, naparam) {
/* sa_ignore FREED_MEMORY */
aparam = TAILQ_FIRST(&asoc->asconf_queue);
TAILQ_REMOVE(&asoc->asconf_queue, aparam, next);
SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
}
while (!TAILQ_EMPTY(&asoc->asconf_ack_sent)) {
TAILQ_FOREACH_SAFE(aack, &asoc->asconf_ack_sent, next, naack) {
/* sa_ignore FREED_MEMORY */
aack = TAILQ_FIRST(&asoc->asconf_ack_sent);
TAILQ_REMOVE(&asoc->asconf_ack_sent, aack, next);
if (aack->data != NULL) {
sctp_m_freem(aack->data);
@ -5126,12 +5022,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
sctp_free_authinfo(&asoc->authinfo);
shared_key = LIST_FIRST(&asoc->shared_keys);
while (shared_key) {
LIST_FOREACH_SAFE(shared_key, &asoc->shared_keys, next, nshared_key) {
LIST_REMOVE(shared_key, next);
sctp_free_sharedkey(shared_key);
/* sa_ignore FREED_MEMORY */
shared_key = LIST_FIRST(&asoc->shared_keys);
}
/* Insert new items here :> */
@ -5689,12 +5583,12 @@ void
sctp_pcb_finish(void)
{
struct sctp_vrflist *vrf_bucket;
struct sctp_vrf *vrf;
struct sctp_ifn *ifn;
struct sctp_ifa *ifa;
struct sctp_vrf *vrf, *nvrf;
struct sctp_ifn *ifn, *nifn;
struct sctp_ifa *ifa, *nifa;
struct sctpvtaghead *chain;
struct sctp_tagblock *twait_block, *prev_twait_block;
struct sctp_laddr *wi;
struct sctp_laddr *wi, *nwi;
int i;
/*
@ -5706,20 +5600,15 @@ sctp_pcb_finish(void)
struct sctp_iterator *it, *nit;
SCTP_IPI_ITERATOR_WQ_LOCK();
it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead);
while (it) {
nit = TAILQ_NEXT(it, sctp_nxt_itr);
TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
if (it->vn != curvnet) {
it = nit;
continue;
}
TAILQ_REMOVE(&sctp_it_ctl.iteratorhead,
it, sctp_nxt_itr);
TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
if (it->function_atend != NULL) {
(*it->function_atend) (it->pointer, it->val);
}
SCTP_FREE(it, SCTP_M_ITER);
it = nit;
}
SCTP_IPI_ITERATOR_WQ_UNLOCK();
SCTP_ITERATOR_LOCK();
@ -5732,7 +5621,7 @@ sctp_pcb_finish(void)
SCTP_OS_TIMER_STOP(&SCTP_BASE_INFO(addr_wq_timer.timer));
SCTP_WQ_ADDR_LOCK();
while ((wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq))) != NULL) {
LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
LIST_REMOVE(wi, sctp_nxt_addr);
SCTP_DECR_LADDR_COUNT();
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), wi);
@ -5744,9 +5633,9 @@ sctp_pcb_finish(void)
* destroyed first).
*/
vrf_bucket = &SCTP_BASE_INFO(sctp_vrfhash)[(SCTP_DEFAULT_VRFID & SCTP_BASE_INFO(hashvrfmark))];
while ((vrf = LIST_FIRST(vrf_bucket)) != NULL) {
while ((ifn = LIST_FIRST(&vrf->ifnlist)) != NULL) {
while ((ifa = LIST_FIRST(&ifn->ifalist)) != NULL) {
LIST_FOREACH_SAFE(vrf, vrf_bucket, next_vrf, nvrf) {
LIST_FOREACH_SAFE(ifn, &vrf->ifnlist, next_ifn, nifn) {
LIST_FOREACH_SAFE(ifa, &ifn->ifalist, next_ifa, nifa) {
/* free the ifa */
LIST_REMOVE(ifa, next_bucket);
LIST_REMOVE(ifa, next_ifa);
@ -5827,7 +5716,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* packet and the offset points to the beginning of the parameters.
*/
struct sctp_inpcb *inp, *l_inp;
struct sctp_nets *net, *net_tmp;
struct sctp_nets *net, *nnet, *net_tmp;
struct ip *iph;
struct sctp_paramhdr *phdr, parm_buf;
struct sctp_tcb *stcb_tmp;
@ -6373,8 +6262,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
sizeof(parm_buf));
}
/* Now check to see if we need to purge any addresses */
for (net = TAILQ_FIRST(&stcb->asoc.nets); net != NULL; net = net_tmp) {
net_tmp = TAILQ_NEXT(net, sctp_next);
TAILQ_FOREACH_SAFE(net, &stcb->asoc.nets, sctp_next, nnet) {
if ((net->dest_state & SCTP_ADDR_NOT_IN_ASSOC) ==
SCTP_ADDR_NOT_IN_ASSOC) {
/* This address has been removed from the asoc */
@ -6587,10 +6475,7 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
cumulative_tsn_p1 = asoc->cumulative_tsn + 1;
cnt = 0;
/* First look in the re-assembly queue */
chk = TAILQ_FIRST(&asoc->reasmqueue);
while (chk) {
/* Get the next one */
nchk = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
if (compare_with_wrap(chk->rec.data.TSN_seq,
cumulative_tsn_p1, MAX_TSN)) {
/* Yep it is above cum-ack */
@ -6606,13 +6491,10 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
}
sctp_free_a_chunk(stcb, chk);
}
chk = nchk;
}
/* Ok that was fun, now we will drain all the inbound streams? */
for (strmat = 0; strmat < asoc->streamincnt; strmat++) {
ctl = TAILQ_FIRST(&asoc->strmin[strmat].inqueue);
while (ctl) {
nctl = TAILQ_NEXT(ctl, next);
TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].inqueue, next, nctl) {
if (compare_with_wrap(ctl->sinfo_tsn,
cumulative_tsn_p1, MAX_TSN)) {
/* Yep it is above cum-ack */
@ -6630,7 +6512,6 @@ sctp_drain_mbufs(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl);
SCTP_DECR_READQ_COUNT();
}
ctl = nctl;
}
}
if (cnt) {

View File

@ -57,7 +57,7 @@ sctp_early_fr_timer(struct sctp_inpcb *inp,
struct sctp_tcb *stcb,
struct sctp_nets *net)
{
struct sctp_tmit_chunk *chk, *tp2;
struct sctp_tmit_chunk *chk, *pchk;
struct timeval now, min_wait, tv;
unsigned int cur_rtt, cnt = 0, cnt_resend = 0;
@ -88,9 +88,7 @@ sctp_early_fr_timer(struct sctp_inpcb *inp,
*/
min_wait.tv_sec = min_wait.tv_usec = 0;
}
chk = TAILQ_LAST(&stcb->asoc.sent_queue, sctpchunk_listhead);
for (; chk != NULL; chk = tp2) {
tp2 = TAILQ_PREV(chk, sctpchunk_listhead, sctp_next);
TAILQ_FOREACH_REVERSE_SAFE(chk, &stcb->asoc.sent_queue, sctpchunk_listhead, sctp_next, pchk) {
if (chk->whoTo != net) {
continue;
}
@ -574,20 +572,18 @@ sctp_backoff_on_timeout(struct sctp_tcb *stcb,
static void
sctp_recover_sent_list(struct sctp_tcb *stcb)
{
struct sctp_tmit_chunk *chk, *tp2;
struct sctp_tmit_chunk *chk, *nchk;
struct sctp_association *asoc;
asoc = &stcb->asoc;
chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
for (; chk != NULL; chk = tp2) {
tp2 = TAILQ_NEXT(chk, sctp_next);
if ((compare_with_wrap(stcb->asoc.last_acked_seq,
TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
if ((compare_with_wrap(asoc->last_acked_seq,
chk->rec.data.TSN_seq,
MAX_TSN)) ||
(stcb->asoc.last_acked_seq == chk->rec.data.TSN_seq)) {
(asoc->last_acked_seq == chk->rec.data.TSN_seq)) {
SCTP_PRINTF("Found chk:%p tsn:%x <= last_acked_seq:%x\n",
chk, chk->rec.data.TSN_seq, stcb->asoc.last_acked_seq);
chk, chk->rec.data.TSN_seq, asoc->last_acked_seq);
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
if (chk->pr_sctp_on) {
if (asoc->pr_sctp_cnt != 0)
@ -597,19 +593,17 @@ sctp_recover_sent_list(struct sctp_tcb *stcb)
/* sa_ignore NO_NULL_CHK */
sctp_free_bufspace(stcb, asoc, chk, 1);
sctp_m_freem(chk->data);
chk->data = NULL;
if (asoc->peer_supports_prsctp && PR_SCTP_BUF_ENABLED(chk->flags)) {
asoc->sent_queue_cnt_removeable--;
}
}
chk->data = NULL;
asoc->sent_queue_cnt--;
sctp_free_a_chunk(stcb, chk);
}
}
SCTP_PRINTF("after recover order is as follows\n");
chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
for (; chk != NULL; chk = tp2) {
tp2 = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
SCTP_PRINTF("chk:%p TSN:%x\n", chk, chk->rec.data.TSN_seq);
}
}
@ -631,7 +625,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
* We only mark chunks that have been outstanding long enough to
* have received feed-back.
*/
struct sctp_tmit_chunk *chk, *tp2;
struct sctp_tmit_chunk *chk, *nchk;
struct sctp_nets *lnets;
struct timeval now, min_wait, tv;
int cur_rtt;
@ -697,9 +691,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
#ifndef INVARIANTS
start_again:
#endif
chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
for (; chk != NULL; chk = tp2) {
tp2 = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH_SAFE(chk, &stcb->asoc.sent_queue, sctp_next, nchk) {
if ((compare_with_wrap(stcb->asoc.last_acked_seq,
chk->rec.data.TSN_seq,
MAX_TSN)) ||
@ -1369,7 +1361,7 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_nets *net)
{
struct sctp_nets *alt;
struct sctp_tmit_chunk *asconf, *chk, *nchk;
struct sctp_tmit_chunk *asconf, *chk;
/* is this a first send, or a retransmission? */
if (TAILQ_EMPTY(&stcb->asoc.asconf_send_queue)) {
@ -1427,8 +1419,7 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
atomic_add_int(&alt->ref_count, 1);
}
}
for (chk = asconf; chk; chk = nchk) {
nchk = TAILQ_NEXT(chk, sctp_next);
TAILQ_FOREACH(chk, &stcb->asoc.asconf_send_queue, sctp_next) {
if (chk->whoTo != alt) {
sctp_free_remote_addr(chk->whoTo);
chk->whoTo = alt;

View File

@ -3335,7 +3335,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if ((stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt) < addstrmcnt) {
/* Need to allocate more */
struct sctp_stream_out *oldstream;
struct sctp_stream_queue_pending *sp;
struct sctp_stream_queue_pending *sp,
*nsp;
int removed;
oldstream = stcb->asoc.strmout;
@ -3374,8 +3375,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
* now anything on those
* queues?
*/
while (TAILQ_EMPTY(&oldstream[i].outqueue) == 0) {
sp = TAILQ_FIRST(&oldstream[i].outqueue);
TAILQ_FOREACH_SAFE(sp, &oldstream[i].outqueue, next, nsp) {
TAILQ_REMOVE(&oldstream[i].outqueue, sp, next);
TAILQ_INSERT_TAIL(&stcb->asoc.strmout[i].outqueue, sp, next);
}

View File

@ -1417,13 +1417,13 @@ sctp_iterator_work(struct sctp_iterator *it)
void
sctp_iterator_worker(void)
{
struct sctp_iterator *it = NULL;
struct sctp_iterator *it, *nit;
/* This function is called with the WQ lock in place */
sctp_it_ctl.iterator_running = 1;
sctp_it_ctl.cur_it = it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead);
while (it) {
TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
sctp_it_ctl.cur_it = it;
/* now lets work on this one */
TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
SCTP_IPI_ITERATOR_WQ_UNLOCK();
@ -1437,7 +1437,6 @@ sctp_iterator_worker(void)
break;
}
/* sa_ignore FREED_MEMORY */
sctp_it_ctl.cur_it = it = TAILQ_FIRST(&sctp_it_ctl.iteratorhead);
}
sctp_it_ctl.iterator_running = 0;
return;
@ -1448,7 +1447,7 @@ static void
sctp_handle_addr_wq(void)
{
/* deal with the ADDR wq from the rtsock calls */
struct sctp_laddr *wi;
struct sctp_laddr *wi, *nwi;
struct sctp_asconf_iterator *asc;
SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
@ -1465,12 +1464,10 @@ sctp_handle_addr_wq(void)
asc->cnt = 0;
SCTP_WQ_ADDR_LOCK();
wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq));
while (wi != NULL) {
LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
LIST_REMOVE(wi, sctp_nxt_addr);
LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
asc->cnt++;
wi = LIST_FIRST(&SCTP_BASE_INFO(addr_wq));
}
SCTP_WQ_ADDR_UNLOCK();
@ -1664,8 +1661,7 @@ sctp_timeout_handler(void *t)
#endif
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)
) {
(stcb->asoc.sent_queue_cnt > 0)) {
struct sctp_tmit_chunk *chk;
/*
@ -3693,22 +3689,21 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
{
struct sctp_association *asoc;
struct sctp_stream_out *outs;
struct sctp_tmit_chunk *chk;
struct sctp_stream_queue_pending *sp;
struct sctp_tmit_chunk *chk, *nchk;
struct sctp_stream_queue_pending *sp, *nsp;
int i;
asoc = &stcb->asoc;
if (stcb == NULL) {
return;
}
if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
asoc = &stcb->asoc;
if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
/* already being freed */
return;
}
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
(asoc->state & SCTP_STATE_CLOSED_SOCKET)) {
return;
}
/* now through all the gunk freeing chunks */
@ -3716,53 +3711,44 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
SCTP_TCB_SEND_LOCK(stcb);
}
/* sent queue SHOULD be empty */
if (!TAILQ_EMPTY(&asoc->sent_queue)) {
chk = TAILQ_FIRST(&asoc->sent_queue);
while (chk) {
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
asoc->sent_queue_cnt--;
if (chk->data != NULL) {
sctp_free_bufspace(stcb, asoc, chk, 1);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
SCTP_NOTIFY_DATAGRAM_SENT, chk, so_locked);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
asoc->sent_queue_cnt--;
if (chk->data != NULL) {
sctp_free_bufspace(stcb, asoc, chk, 1);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
SCTP_NOTIFY_DATAGRAM_SENT, chk, so_locked);
if (chk->data) {
sctp_m_freem(chk->data);
chk->data = NULL;
}
sctp_free_a_chunk(stcb, chk);
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->sent_queue);
}
sctp_free_a_chunk(stcb, chk);
/* sa_ignore FREED_MEMORY */
}
/* pending send queue SHOULD be empty */
if (!TAILQ_EMPTY(&asoc->send_queue)) {
chk = TAILQ_FIRST(&asoc->send_queue);
while (chk) {
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
asoc->send_queue_cnt--;
if (chk->data != NULL) {
sctp_free_bufspace(stcb, asoc, chk, 1);
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;
}
TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
asoc->send_queue_cnt--;
if (chk->data != NULL) {
sctp_free_bufspace(stcb, asoc, chk, 1);
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;
}
sctp_free_a_chunk(stcb, chk);
/* sa_ignore FREED_MEMORY */
chk = TAILQ_FIRST(&asoc->send_queue);
}
sctp_free_a_chunk(stcb, chk);
/* sa_ignore FREED_MEMORY */
}
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
for (i = 0; i < asoc->streamoutcnt; i++) {
/* For each stream */
outs = &stcb->asoc.strmout[i];
outs = &asoc->strmout[i];
/* clean up any sends there */
stcb->asoc.locked_on_sending = NULL;
sp = TAILQ_FIRST(&outs->outqueue);
while (sp) {
stcb->asoc.stream_queue_cnt--;
asoc->locked_on_sending = NULL;
TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
asoc->stream_queue_cnt--;
TAILQ_REMOVE(&outs->outqueue, sp, next);
sctp_free_spbufspace(stcb, asoc, sp);
if (sp->data) {
@ -3780,7 +3766,6 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
/* Free the chunk */
sctp_free_a_strmoq(stcb, sp);
/* sa_ignore FREED_MEMORY */
sp = TAILQ_FIRST(&outs->outqueue);
}
}
@ -4311,10 +4296,8 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
}
/* lock the socket buffers */
SCTP_INP_READ_LOCK(old_inp);
control = TAILQ_FIRST(&old_inp->read_queue);
/* Pull off all for out target stcb */
while (control) {
nctl = TAILQ_NEXT(control, next);
TAILQ_FOREACH_SAFE(control, &old_inp->read_queue, next, nctl) {
/* Pull off all for out target stcb */
if (control->stcb == stcb) {
/* remove it we want it */
TAILQ_REMOVE(&old_inp->read_queue, control, next);
@ -4331,17 +4314,14 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
m = SCTP_BUF_NEXT(m);
}
}
control = nctl;
}
SCTP_INP_READ_UNLOCK(old_inp);
/* Remove the sb-lock on the old socket */
sbunlock(&old_so->so_rcv);
/* Now we move them over to the new socket buffer */
control = TAILQ_FIRST(&tmp_queue);
SCTP_INP_READ_LOCK(new_inp);
while (control) {
nctl = TAILQ_NEXT(control, next);
TAILQ_FOREACH_SAFE(control, &tmp_queue, next, nctl) {
TAILQ_INSERT_TAIL(&new_inp->read_queue, control, next);
m = control->data;
while (m) {
@ -4354,7 +4334,6 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
}
m = SCTP_BUF_NEXT(m);
}
control = nctl;
}
SCTP_INP_READ_UNLOCK(new_inp);
}
@ -4700,7 +4679,7 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
)
{
struct sctp_stream_out *strq;
struct sctp_tmit_chunk *chk = NULL;
struct sctp_tmit_chunk *chk = NULL, *tp2;
struct sctp_stream_queue_pending *sp;
uint16_t stream = 0, seq = 0;
uint8_t foundeom = 0;
@ -4754,15 +4733,11 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
* The multi-part message was scattered across the send and
* sent queue.
*/
next_on_sent:
tp1 = TAILQ_FIRST(&stcb->asoc.send_queue);
/*
* recurse throught the send_queue too, starting at the
* beginning.
*/
if ((tp1) &&
(tp1->rec.data.stream_number == stream) &&
(tp1->rec.data.stream_seq == seq)) {
TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) {
if ((tp1->rec.data.stream_number != stream) ||
(tp1->rec.data.stream_seq != seq)) {
break;
}
/*
* save to chk in case we have some on stream out
* queue. If so and we have an un-transmitted one we
@ -4792,7 +4767,6 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
sctp_next);
stcb->asoc.send_queue_cnt--;
stcb->asoc.sent_queue_cnt++;
goto next_on_sent;
}
}
if (foundeom == 0) {
@ -4802,8 +4776,11 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
*/
strq = &stcb->asoc.strmout[stream];
SCTP_TCB_SEND_LOCK(stcb);
sp = TAILQ_FIRST(&strq->outqueue);
while (sp->strseq <= seq) {
TAILQ_FOREACH(sp, &strq->outqueue, next) {
/* FIXME: Shouldn't this be a serial number check? */
if (sp->strseq > seq) {
break;
}
/* Check if its our SEQ */
if (sp->strseq == seq) {
sp->discard_rest = 1;
@ -4866,11 +4843,8 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
sp->tail_mbuf = NULL;
}
break;
} else {
/* Next one please */
sp = TAILQ_NEXT(sp, next);
}
} /* End while */
} /* End tailq_foreach */
SCTP_TCB_SEND_UNLOCK(stcb);
}
if (do_wakeup_routine) {