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:
parent
8ced7318a0
commit
4a9ef3f833
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
/*******************************************************/
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user