18c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
28c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
3ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
58c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
68c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Redistribution and use in source and binary forms, with or without
78c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * modification, are permitted provided that the following conditions are met:
88c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
98c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) Redistributions of source code must retain the above copyright notice,
100ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    this list of conditions and the following disclaimer.
118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * b) Redistributions in binary form must reproduce the above copyright
138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    notice, this list of conditions and the following disclaimer in
140ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    the documentation and/or other materials provided with the distribution.
158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * c) Neither the name of Cisco Systems, Inc. nor the names of its
178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    contributors may be used to endorse or promote products derived
188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    from this software without specific prior written permission.
198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE POSSIBILITY OF SUCH DAMAGE.
318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__
348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/cdefs.h>
35a8657c4fc04fb9cc82100f648810d51ec6ab155at__FBSDID("$FreeBSD: head/sys/netinet/sctp_indata.c 269448 2014-08-02 21:36:40Z tuexen $");
368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h>
398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h>
408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h>
418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h>
428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_header.h>
438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h>
448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_output.h>
458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_input.h>
468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_indata.h>
478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_uio.h>
488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_timer.h>
498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTES: On the outbound side of things I need to check the sack timer to
538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * see if I should generate a sack into the chunk queue (if I have data to
548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * send that is and will be sending it .. for bundling.
558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * The callback in sctp_usrreq.c will get called when the socket is read from.
578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This will cause sctp_service_queues() to get called on the top entry in
588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the list.
598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_set_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc)
638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->my_rwnd = sctp_calc_rwnd(stcb, asoc);
658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* Calculate what the rwnd would be */
688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc)
708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
71b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	uint32_t calc = 0;
728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * This is really set wrong with respect to a 1-2-m socket. Since
758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the sb_cc is the count that everyone as put up. When we re-write
768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * sctp_soreceive then we will fix this so that ONLY this
778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * associations data is taken into account.
788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_socket == NULL)
808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (calc);
818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.sb_cc == 0 &&
838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    asoc->size_on_reasm_queue == 0 &&
848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    asoc->size_on_all_streams == 0) {
858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Full rwnd granted */
868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		calc = max(SCTP_SB_LIMIT_RCV(stcb->sctp_socket), SCTP_MINIMAL_RWND);
878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (calc);
888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get actual space */
908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	calc = (uint32_t) sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv);
918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * take out what has NOT been put on socket queue and we yet hold
948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * for putting up.
958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	calc = sctp_sbspace_sub(calc, (uint32_t)(asoc->size_on_reasm_queue +
978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                                         asoc->cnt_on_reasm_queue * MSIZE));
988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	calc = sctp_sbspace_sub(calc, (uint32_t)(asoc->size_on_all_streams +
998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                                         asoc->cnt_on_all_streams * MSIZE));
1008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (calc == 0) {
1028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* out of space */
1038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (calc);
1048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* what is the overhead of all these rwnd's */
1078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	calc = sctp_sbspace_sub(calc, stcb->asoc.my_rwnd_control_len);
1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* If the window gets too small due to ctrl-stuff, reduce it
1098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * to 1, even it is 0. SWS engaged
1108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
1118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (calc < stcb->asoc.my_rwnd_control_len) {
1128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		calc = 1;
1138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (calc);
1158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
1208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Build out our readq entry based on the incoming packet.
1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_queued_to_read *
1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_build_readq_entry(struct sctp_tcb *stcb,
1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_nets *net,
1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint32_t tsn, uint32_t ppid,
1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint32_t context, uint16_t stream_no,
1278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint16_t stream_seq, uint8_t flags,
1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct mbuf *dm)
1298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *read_queue_e = NULL;
1318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_alloc_a_readq(stcb, read_queue_e);
1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (read_queue_e == NULL) {
1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto failed_build;
1358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_stream = stream_no;
1378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_ssn = stream_seq;
1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_flags = (flags << 8);
1398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_ppid = ppid;
1400ac02f34d6041cd0018437596a5a9a94685e6919tuexen	read_queue_e->sinfo_context = context;
1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_timetolive = 0;
1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_tsn = tsn;
1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_cumtsn = tsn;
1448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_assoc_id = sctp_get_associd(stcb);
1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->whoFrom = net;
1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->length = 0;
1478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&net->ref_count, 1);
1488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->data = dm;
1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->spec_flags = 0;
1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->tail_mbuf = NULL;
1518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->aux_data = NULL;
1528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->stcb = stcb;
1538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->port_from = stcb->rport;
1548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->do_not_ref_stcb = 0;
1558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->end_added = 0;
1568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->some_taken = 0;
1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->pdapi_aborted = 0;
1588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenfailed_build:
1598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (read_queue_e);
1608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
1648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Build out our readq entry based on the incoming packet.
1658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
1668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_queued_to_read *
1678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_build_readq_entry_chk(struct sctp_tcb *stcb,
1688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_tmit_chunk *chk)
1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *read_queue_e = NULL;
1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_alloc_a_readq(stcb, read_queue_e);
1738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (read_queue_e == NULL) {
1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto failed_build;
1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_stream = chk->rec.data.stream_number;
1778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_ssn = chk->rec.data.stream_seq;
1788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_flags = (chk->rec.data.rcv_flags << 8);
1798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_ppid = chk->rec.data.payloadtype;
1808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_context = stcb->asoc.context;
1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_timetolive = 0;
1828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_tsn = chk->rec.data.TSN_seq;
1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_cumtsn = chk->rec.data.TSN_seq;
1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->sinfo_assoc_id = sctp_get_associd(stcb);
1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->whoFrom = chk->whoTo;
1868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->aux_data = NULL;
1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->length = 0;
1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&chk->whoTo->ref_count, 1);
1898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->data = chk->data;
1908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->tail_mbuf = NULL;
1918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->stcb = stcb;
1928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->port_from = stcb->rport;
1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->spec_flags = 0;
1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->do_not_ref_stcb = 0;
1958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->end_added = 0;
1968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->some_taken = 0;
1978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	read_queue_e->pdapi_aborted = 0;
1988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenfailed_build:
1998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (read_queue_e);
2008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct mbuf *
2048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo)
2058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_extrcvinfo *seinfo;
2078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_sndrcvinfo *outinfo;
2088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_rcvinfo *rcvinfo;
2098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nxtinfo *nxtinfo;
21009c18a940b9e5520f869d4f187988ab748484b25t#if defined(__Userspace_os_Windows)
21109c18a940b9e5520f869d4f187988ab748484b25t	WSACMSGHDR *cmh;
21209c18a940b9e5520f869d4f187988ab748484b25t#else
2138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct cmsghdr *cmh;
21409c18a940b9e5520f869d4f187988ab748484b25t#endif
2158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *ret;
2168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int len;
2178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int use_extended;
2188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int provide_nxt;
2198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) &&
2218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
2228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) {
2238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* user does not want any ancillary data */
2248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
2258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	len = 0;
2288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) {
2298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		len += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
2308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	seinfo = (struct sctp_extrcvinfo *)sinfo;
2328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) &&
2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL)) {
2348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		provide_nxt = 1;
2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		len += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
2368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
2378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		provide_nxt = 0;
2388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) {
2408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO)) {
2418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			use_extended = 1;
2428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			len += CMSG_SPACE(sizeof(struct sctp_extrcvinfo));
2438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
2448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			use_extended = 0;
2458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			len += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
2468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		use_extended = 0;
2498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25168beeca578347438d9c434680197647ed551935ft	ret = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
2528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ret == NULL) {
2538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* No space */
2548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ret);
2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(ret) = 0;
2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* We need a CMSG header followed by the struct */
25909c18a940b9e5520f869d4f187988ab748484b25t#if defined(__Userspace_os_Windows)
26009c18a940b9e5520f869d4f187988ab748484b25t	cmh = mtod(ret, WSACMSGHDR *);
26109c18a940b9e5520f869d4f187988ab748484b25t#else
2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cmh = mtod(ret, struct cmsghdr *);
26309c18a940b9e5520f869d4f187988ab748484b25t#endif
264f496fe99adbad377f85add3a45e17f21a4702b41t	/*
265f496fe99adbad377f85add3a45e17f21a4702b41t	 * Make sure that there is no un-initialized padding between
266f496fe99adbad377f85add3a45e17f21a4702b41t	 * the cmsg header and cmsg data and after the cmsg data.
267f496fe99adbad377f85add3a45e17f21a4702b41t	 */
268f496fe99adbad377f85add3a45e17f21a4702b41t	memset(cmh, 0, len);
2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) {
2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cmh->cmsg_level = IPPROTO_SCTP;
2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_rcvinfo));
2728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cmh->cmsg_type = SCTP_RCVINFO;
2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmh);
2748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rcvinfo->rcv_sid = sinfo->sinfo_stream;
2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rcvinfo->rcv_ssn = sinfo->sinfo_ssn;
2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rcvinfo->rcv_flags = sinfo->sinfo_flags;
2778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rcvinfo->rcv_ppid = sinfo->sinfo_ppid;
2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rcvinfo->rcv_tsn = sinfo->sinfo_tsn;
2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rcvinfo->rcv_cumtsn = sinfo->sinfo_cumtsn;
2808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rcvinfo->rcv_context = sinfo->sinfo_context;
2818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rcvinfo->rcv_assoc_id = sinfo->sinfo_assoc_id;
28209c18a940b9e5520f869d4f187988ab748484b25t#if defined(__Userspace_os_Windows)
28309c18a940b9e5520f869d4f187988ab748484b25t		cmh = (WSACMSGHDR *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_rcvinfo)));
28409c18a940b9e5520f869d4f187988ab748484b25t#else
2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cmh = (struct cmsghdr *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_rcvinfo)));
28609c18a940b9e5520f869d4f187988ab748484b25t#endif
2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (provide_nxt) {
2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cmh->cmsg_level = IPPROTO_SCTP;
2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_nxtinfo));
2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cmh->cmsg_type = SCTP_NXTINFO;
2938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmh);
2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		nxtinfo->nxt_sid = seinfo->sreinfo_next_stream;
2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		nxtinfo->nxt_flags = 0;
2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) {
2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			nxtinfo->nxt_flags |= SCTP_UNORDERED;
2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) {
3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			nxtinfo->nxt_flags |= SCTP_NOTIFICATION;
3018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) {
3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			nxtinfo->nxt_flags |= SCTP_COMPLETE;
3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		nxtinfo->nxt_ppid = seinfo->sreinfo_next_ppid;
3068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		nxtinfo->nxt_length = seinfo->sreinfo_next_length;
3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		nxtinfo->nxt_assoc_id = seinfo->sreinfo_next_aid;
30809c18a940b9e5520f869d4f187988ab748484b25t#if defined(__Userspace_os_Windows)
30909c18a940b9e5520f869d4f187988ab748484b25t		cmh = (WSACMSGHDR *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_nxtinfo)));
31009c18a940b9e5520f869d4f187988ab748484b25t#else
3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cmh = (struct cmsghdr *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_nxtinfo)));
31209c18a940b9e5520f869d4f187988ab748484b25t#endif
3138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_nxtinfo));
3148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) {
3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cmh->cmsg_level = IPPROTO_SCTP;
3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		outinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmh);
3188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (use_extended) {
3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_extrcvinfo));
3208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cmh->cmsg_type = SCTP_EXTRCV;
3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(outinfo, sinfo, sizeof(struct sctp_extrcvinfo));
3228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_extrcvinfo));
3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cmh->cmsg_type = SCTP_SNDRCV;
3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*outinfo = *sinfo;
3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (ret);
3318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn)
3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t gap, i, cumackp1;
3388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int fnd = 0;
3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) {
3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cumackp1 = asoc->cumulative_tsn + 1;
3448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(cumackp1, tsn)) {
3458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* this tsn is behind the cum ack and thus we don't
3468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * need to worry about it being moved from one to the other.
3478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
3488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
3498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn);
3518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
35247a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("gap:%x tsn:%x\n", gap, tsn);
3538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_print_mapping_array(asoc);
3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
3558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		panic("Things are really messed up now!!");
3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
3598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
3608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
3618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->highest_tsn_inside_nr_map = tsn;
3628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (tsn == asoc->highest_tsn_inside_map) {
3648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We must back down to see what the new highest is */
3658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = tsn - 1; SCTP_TSN_GE(i, asoc->mapping_array_base_tsn); i--) {
3668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn);
3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) {
3688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->highest_tsn_inside_map = i;
3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				fnd = 1;
3708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
3728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!fnd) {
3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1;
3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
3818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We are delivering currently from the reassembly queue. We must continue to
3828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * deliver until we either: 1) run out of space. 2) run out of sequential
3838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * TSN's 3) hit the SCTP_DATA_LAST_FRAG flag.
3848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
3858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
3868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_service_reassembly(struct sctp_tcb *stcb, struct sctp_association *asoc)
3878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
3888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk, *nchk;
3898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t nxt_todel;
3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t stream_no;
3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int end = 0;
3928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int cntDel;
3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control, *ctl, *nctl;
3948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL)
3968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
3978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cntDel = stream_no = 0;
3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
4008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) ||
4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* socket above is long gone or going.. */
4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	abandon:
4048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->fragmented_delivery_inprogress = 0;
4058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
4078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->size_on_reasm_queue -= chk->send_size;
4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ucount_decr(asoc->cnt_on_reasm_queue);
4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Lose the data pointer, since its in the socket
4118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * buffer
4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
4138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->data) {
4148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(chk->data);
4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				chk->data = NULL;
4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Now free the address and data */
4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
419e2828360ea9cf8951730d46f5c14626c9425cb30t			/*sa_ignore FREED_MEMORY*/
4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
4228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_LOCK_ASSERT(stcb);
4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->rec.data.TSN_seq != (asoc->tsn_last_delivered + 1)) {
4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't deliver more :< */
4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
4288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stream_no = chk->rec.data.stream_number;
4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		nxt_todel = asoc->strmin[stream_no].last_sequence_delivered + 1;
4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (nxt_todel != chk->rec.data.stream_seq &&
4328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0) {
4338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Not the next sequence to deliver in its stream OR
4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * unordered
4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
4378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) {
4408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control = sctp_build_readq_entry_chk(stcb, chk);
4428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (control == NULL) {
4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* out of memory? */
4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
4468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* save it off for our future deliveries */
4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.control_pdapi = control;
4488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG)
4498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				end = 1;
4508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
4518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				end = 0;
4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq);
4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_add_to_readq(stcb->sctp_ep,
4548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                  stcb, control, &stcb->sctp_socket->so_rcv, end,
4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                  SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cntDel++;
4578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG)
4598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				end = 1;
4608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
4618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				end = 0;
4628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_mark_non_revokable(asoc, chk->rec.data.TSN_seq);
4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_append_to_readq(stcb->sctp_ep, stcb,
4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    stcb->asoc.control_pdapi,
4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    chk->data, end, chk->rec.data.TSN_seq,
4668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    &stcb->sctp_socket->so_rcv)) {
4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
4688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * something is very wrong, either
4698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * control_pdapi is NULL, or the tail_mbuf
4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * is corrupt, or there is a EOM already on
4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * the mbuf chain.
4728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
4748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto abandon;
4758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((stcb->asoc.control_pdapi == NULL)  || (stcb->asoc.control_pdapi->tail_mbuf == NULL)) {
4788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						panic("This should not happen control_pdapi NULL?");
4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* if we did not panic, it was a EOM */
4818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					panic("Bad chunking ??");
4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
4838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((stcb->asoc.control_pdapi == NULL)  || (stcb->asoc.control_pdapi->tail_mbuf == NULL)) {
4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  SCTP_PRINTF("This should not happen control_pdapi NULL?\n");
4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_PRINTF("Bad chunking ??\n");
4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_PRINTF("Dumping re-assembly queue this will probably hose the association\n");
488000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
489000a5bac556b28e74e4e98c540f66b1743e9312dtuexen#endif
4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto abandon;
4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
4928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
4938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cntDel++;
4948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* pull it we did it */
4968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
4978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
4988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->fragmented_delivery_inprogress = 0;
4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0) {
5008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->strmin[stream_no].last_sequence_delivered++;
5018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == 0) {
5038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
5048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) {
5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
5078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * turn the flag back on since we just  delivered
5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * yet another one.
5098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
5108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->fragmented_delivery_inprogress = 1;
5118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->tsn_of_pdapi_last_delivered = chk->rec.data.TSN_seq;
5138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->last_flags_delivered = chk->rec.data.rcv_flags;
5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->last_strm_seq_delivered = chk->rec.data.stream_seq;
5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->last_strm_no_delivered = chk->rec.data.stream_number;
5168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->tsn_last_delivered = chk->rec.data.TSN_seq;
5188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->size_on_reasm_queue -= chk->send_size;
5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_ucount_decr(asoc->cnt_on_reasm_queue);
5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* free up the chk */
5218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->data = NULL;
5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->fragmented_delivery_inprogress == 0) {
5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Now lets see if we can deliver the next one on
5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * the stream
5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_stream_in *strm;
5308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			strm = &asoc->strmin[stream_no];
5328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			nxt_todel = strm->last_sequence_delivered + 1;
5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH_SAFE(ctl, &strm->inqueue, next, nctl) {
5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Deliver more if we can. */
5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (nxt_todel == ctl->sinfo_ssn) {
5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_REMOVE(&strm->inqueue, ctl, next);
5378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->size_on_all_streams -= ctl->length;
5388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_ucount_decr(asoc->cnt_on_all_streams);
5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					strm->last_sequence_delivered++;
5408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
5418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_add_to_readq(stcb->sctp_ep, stcb,
5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                  ctl,
5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                  &stcb->sctp_socket->so_rcv, 1,
5448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                  SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
5458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
5468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
5478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				nxt_todel = strm->last_sequence_delivered + 1;
5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
5518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
5568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Queue the chunk either right into the socket buffer if it is the next one
5578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to go OR put it in the correct place in the delivery queue.  If we do
5588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * append to the so_buf, keep doing so until we are out of order. One big
5598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * question still remains, what to do when the socket buffer is FULL??
5608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
5618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc,
5638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_queued_to_read *control, int *abort_flag)
5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * FIX-ME maybe? What happens when the ssn wraps? If we are getting
5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * all the data in one stream this could happen quite rapidly. One
5688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * could use the TSN to keep track of things, but this scheme breaks
5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * down in the other type of stream useage that could occur. Send a
5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * single msg to stream 0, send 4Billion messages to stream 1, now
5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * send a message to stream 0. You have a situation where the TSN
5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * has wrapped but not in the stream. Is this worth worrying about
5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * or should we just change our queue sort at the bottom to be by
5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * TSN.
5758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
5768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Could it also be legal for a peer to send ssn 1 with TSN 2 and ssn 2
5778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * with TSN 1? If the peer is doing some sort of funky TSN/SSN
5788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * assignment this could happen... and I don't see how this would be
5798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * a violation. So for now I am undecided an will leave the sort by
5808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * SSN alone. Maybe a hybred approach is the answer
5818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
5828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
5838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_stream_in *strm;
5848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *at;
5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int queue_needed;
5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t nxt_todel;
5878f9e45fea288542b24a6bda01269c6fc184d991at	struct mbuf *op_err;
5888f9e45fea288542b24a6bda01269c6fc184d991at	char msg[SCTP_DIAG_INFO_LEN];
589000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	queue_needed = 1;
5918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->size_on_all_streams += control->length;
5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_ucount_incr(asoc->cnt_on_all_streams);
5938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strm = &asoc->strmin[control->sinfo_stream];
5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	nxt_todel = strm->last_sequence_delivered + 1;
5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
5968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INTO_STRD);
5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_INDATA1,
5998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		"queue to stream called for ssn:%u lastdel:%u nxt:%u\n",
6008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(uint32_t) control->sinfo_stream,
6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(uint32_t) strm->last_sequence_delivered,
6028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(uint32_t) nxt_todel);
6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_SSN_GE(strm->last_sequence_delivered, control->sinfo_ssn)) {
6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* The incoming sseq is behind where we last delivered? */
6058f9e45fea288542b24a6bda01269c6fc184d991at		SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort association\n",
6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control->sinfo_ssn, strm->last_sequence_delivered);
6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	protocol_error:
6088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
6098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * throw it in the stream so it gets cleaned up in
6108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * association destruction
6118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
6128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_INSERT_HEAD(&strm->inqueue, control, next);
6138f9e45fea288542b24a6bda01269c6fc184d991at		snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
6148f9e45fea288542b24a6bda01269c6fc184d991at		         strm->last_sequence_delivered, control->sinfo_tsn,
6158f9e45fea288542b24a6bda01269c6fc184d991at			 control->sinfo_stream, control->sinfo_ssn);
6168f9e45fea288542b24a6bda01269c6fc184d991at		op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
6178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_1;
6188f9e45fea288542b24a6bda01269c6fc184d991at		sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*abort_flag = 1;
6208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (nxt_todel == control->sinfo_ssn) {
6248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* can be delivered right away? */
6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
6268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_IMMED_DEL);
6278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* EY it wont be queued if it could be delivered directly*/
6298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		queue_needed = 0;
6308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->size_on_all_streams -= control->length;
6318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_ucount_decr(asoc->cnt_on_all_streams);
6328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		strm->last_sequence_delivered++;
633000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_mark_non_revokable(asoc, control->sinfo_tsn);
6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_add_to_readq(stcb->sctp_ep, stcb,
6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                  control,
6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                  &stcb->sctp_socket->so_rcv, 1,
6388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                  SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
6398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH_SAFE(control, &strm->inqueue, next, at) {
6408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* all delivered */
6418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			nxt_todel = strm->last_sequence_delivered + 1;
6428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (nxt_todel == control->sinfo_ssn) {
6438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				TAILQ_REMOVE(&strm->inqueue, control, next);
6448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->size_on_all_streams -= control->length;
6458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_ucount_decr(asoc->cnt_on_all_streams);
6468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				strm->last_sequence_delivered++;
6478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
6488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * We ignore the return of deliver_data here
6498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * since we always can hold the chunk on the
6508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * d-queue. And we have a finite number that
6518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * can be delivered from the strq.
6528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_log_strm_del(control, NULL,
6558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							  SCTP_STR_LOG_FROM_IMMED_DEL);
6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_mark_non_revokable(asoc, control->sinfo_tsn);
6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_add_to_readq(stcb->sctp_ep, stcb,
6598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                  control,
6608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                  &stcb->sctp_socket->so_rcv, 1,
6618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                  SCTP_READ_LOCK_NOT_HELD,
6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                  SCTP_SO_NOT_LOCKED);
6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
6648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
6668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (queue_needed) {
6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
6708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Ok, we did not deliver this guy, find the correct place
6718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * to put it on the queue.
6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
673e2828360ea9cf8951730d46f5c14626c9425cb30t		if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) {
674e2828360ea9cf8951730d46f5c14626c9425cb30t			goto protocol_error;
6758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (TAILQ_EMPTY(&strm->inqueue)) {
6778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Empty queue */
6788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
6798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INSERT_HD);
6808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
6818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_INSERT_HEAD(&strm->inqueue, control, next);
6828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
6838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(at, &strm->inqueue, next) {
6848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_SSN_GT(at->sinfo_ssn, control->sinfo_ssn)) {
6858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
6868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * one in queue is bigger than the
6878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * new one, insert before this one
6888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
6898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
6908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_strm_del(control, at,
6918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								  SCTP_STR_LOG_FROM_INSERT_MD);
6928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
6938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_INSERT_BEFORE(at, control, next);
6948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
6958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if (at->sinfo_ssn == control->sinfo_ssn) {
6968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
6978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * Gak, He sent me a duplicate str
6988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * seq number
6998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
7008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
7018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * foo bar, I guess I will just free
7028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * this new guy, should we abort
7038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * too? FIX ME MAYBE? Or it COULD be
7048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * that the SSN's have wrapped.
7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * Maybe I should compare to TSN
7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * somehow... sigh for now just blow
7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * away the chunk!
7088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
7098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (control->data)
7118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_m_freem(control->data);
7128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control->data = NULL;
7138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->size_on_all_streams -= control->length;
7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_ucount_decr(asoc->cnt_on_all_streams);
7158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (control->whoFrom) {
7168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_free_remote_addr(control->whoFrom);
7178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						control->whoFrom = NULL;
7188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
7198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_free_a_readq(stcb, control);
7208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
7218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
7228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (TAILQ_NEXT(at, next) == NULL) {
7238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*
7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * We are at the end, insert
7258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * it after this one
7268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
7278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
7288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_log_strm_del(control, at,
7298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									  SCTP_STR_LOG_FROM_INSERT_TL);
7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
7318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						TAILQ_INSERT_AFTER(&strm->inqueue,
7328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    at, control, next);
7338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
7348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
7358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
7368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
7378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
7428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Returns two things: You get the total size of the deliverable parts of the
7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * first fragmented message on the reassembly queue. And you get a 1 back if
7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * all of the message is ready or a 0 back if the message is still incomplete
7458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
7468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
7478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_all_msg_on_reasm(struct sctp_association *asoc, uint32_t *t_size)
7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk;
7508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t tsn;
7518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*t_size = 0;
7538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	chk = TAILQ_FIRST(&asoc->reasmqueue);
7548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (chk == NULL) {
7558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* nothing on the queue */
7568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == 0) {
7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Not a first on the queue */
7608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tsn = chk->rec.data.TSN_seq;
7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(chk, &asoc->reasmqueue, sctp_next) {
7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tsn != chk->rec.data.TSN_seq) {
7658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*t_size += chk->send_size;
7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
7698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tsn++;
7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
7778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_deliver_reasm_check(struct sctp_tcb *stcb, struct sctp_association *asoc)
7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk;
7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t nxt_todel;
7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t tsize, pd_point;
7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen doit_again:
7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	chk = TAILQ_FIRST(&asoc->reasmqueue);
7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (chk == NULL) {
7868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Huh? */
7878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->size_on_reasm_queue = 0;
7888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->cnt_on_reasm_queue = 0;
7898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
7908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->fragmented_delivery_inprogress == 0) {
7928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		nxt_todel =
7938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered + 1;
7948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) &&
7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (nxt_todel == chk->rec.data.stream_seq ||
7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED))) {
7978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
7988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Yep the first one is here and its ok to deliver
7998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * but should we?
8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->sctp_socket) {
802cdc78af866f2b29865707afee7ea65e1706b4ff8t				pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
8038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				               stcb->sctp_ep->partial_delivery_point);
8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
8058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				pd_point = stcb->sctp_ep->partial_delivery_point;
8068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
8078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) {
8088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
8098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Yes, we setup to start reception, by
8108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * backing down the TSN just in case we
8118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * can't deliver. If we
8128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
8138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->fragmented_delivery_inprogress = 1;
8148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->tsn_last_delivered =
8158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    chk->rec.data.TSN_seq - 1;
8168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->str_of_pdapi =
8178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    chk->rec.data.stream_number;
8188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->ssn_of_pdapi = chk->rec.data.stream_seq;
8198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->pdapi_ppid = chk->rec.data.payloadtype;
8208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->fragment_flags = chk->rec.data.rcv_flags;
8218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_service_reassembly(stcb, asoc);
8228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
8238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
8258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Service re-assembly will deliver stream data queued
8268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * at the end of fragmented delivery.. but it wont know
8278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * to go back and call itself again... we do that here
8288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * with the got doit_again
8298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
8308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_service_reassembly(stcb, asoc);
8318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->fragmented_delivery_inprogress == 0) {
8328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* finished our Fragmented delivery, could be
8338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * more waiting?
8348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
8358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto doit_again;
8368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
8418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Dump onto the re-assembly queue, in its proper place. After dumping on the
8428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queue, see if anthing can be delivered. If so pull it off (or as much as
8438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we can. If we run out of space then we must dump what we can and set the
8448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * appropriate flag to say we queued what we could.
8458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
8468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
8478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_queue_data_for_reasm(struct sctp_tcb *stcb, struct sctp_association *asoc,
8488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_tmit_chunk *chk, int *abort_flag)
8498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8508f9e45fea288542b24a6bda01269c6fc184d991at	struct mbuf *op_err;
8518f9e45fea288542b24a6bda01269c6fc184d991at	char msg[SCTP_DIAG_INFO_LEN];
852b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	uint32_t cum_ackp1, prev_tsn, post_tsn;
8538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *at, *prev, *next;
8548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	prev = next = NULL;
8568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cum_ackp1 = asoc->tsn_last_delivered + 1;
8578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (TAILQ_EMPTY(&asoc->reasmqueue)) {
8588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* This is the first one on the queue */
8598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_INSERT_HEAD(&asoc->reasmqueue, chk, sctp_next);
8608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
8618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * we do not check for delivery of anything when only one
8628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * fragment is here
8638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
8648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->size_on_reasm_queue = chk->send_size;
8658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_ucount_incr(asoc->cnt_on_reasm_queue);
8668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->rec.data.TSN_seq == cum_ackp1) {
8678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->fragmented_delivery_inprogress == 0 &&
8688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) !=
8698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_DATA_FIRST_FRAG) {
8708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
8718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * An empty queue, no delivery inprogress,
8728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * we hit the next one and it does NOT have
8738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * a FIRST fragment mark.
8748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
8758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, its not first, no fragmented delivery in progress\n");
8768f9e45fea288542b24a6bda01269c6fc184d991at				snprintf(msg, sizeof(msg),
8778f9e45fea288542b24a6bda01269c6fc184d991at				         "Expected B-bit for TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
8788f9e45fea288542b24a6bda01269c6fc184d991at				         chk->rec.data.TSN_seq,
879e2828360ea9cf8951730d46f5c14626c9425cb30t				         chk->rec.data.stream_number,
8808f9e45fea288542b24a6bda01269c6fc184d991at				         chk->rec.data.stream_seq);
8818f9e45fea288542b24a6bda01269c6fc184d991at				op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
8828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_2;
8838f9e45fea288542b24a6bda01269c6fc184d991at				sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
8848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*abort_flag = 1;
8858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (asoc->fragmented_delivery_inprogress &&
8868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) {
8878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
8888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * We are doing a partial delivery and the
8898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * NEXT chunk MUST be either the LAST or
8908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * MIDDLE fragment NOT a FIRST
8918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
8928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS a first and fragmented delivery in progress\n");
8938f9e45fea288542b24a6bda01269c6fc184d991at				snprintf(msg, sizeof(msg),
8948f9e45fea288542b24a6bda01269c6fc184d991at				         "Didn't expect B-bit for TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
8958f9e45fea288542b24a6bda01269c6fc184d991at				         chk->rec.data.TSN_seq,
896e2828360ea9cf8951730d46f5c14626c9425cb30t				         chk->rec.data.stream_number,
8978f9e45fea288542b24a6bda01269c6fc184d991at				         chk->rec.data.stream_seq);
8988f9e45fea288542b24a6bda01269c6fc184d991at				op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
8998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_3;
9008f9e45fea288542b24a6bda01269c6fc184d991at				sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
9018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*abort_flag = 1;
9028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (asoc->fragmented_delivery_inprogress) {
9038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
9048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Here we are ok with a MIDDLE or LAST
9058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * piece
9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (chk->rec.data.stream_number !=
9088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    asoc->str_of_pdapi) {
9098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Got to be the right STR No */
9108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream number %d vs %d\n",
9118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						chk->rec.data.stream_number,
9128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						asoc->str_of_pdapi);
9138f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg),
9148f9e45fea288542b24a6bda01269c6fc184d991at					         "Expected SID=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
9158f9e45fea288542b24a6bda01269c6fc184d991at					         asoc->str_of_pdapi,
9168f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.TSN_seq,
9178f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_number,
9188f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_seq);
9198f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
9208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_4;
9218f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
9228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if ((asoc->fragment_flags & SCTP_DATA_UNORDERED) !=
9248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    SCTP_DATA_UNORDERED &&
9258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    chk->rec.data.stream_seq != asoc->ssn_of_pdapi) {
9268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Got to be the right STR Seq */
9278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it IS not same stream seq %d vs %d\n",
9288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						chk->rec.data.stream_seq,
9298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						asoc->ssn_of_pdapi);
9308f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg),
9318f9e45fea288542b24a6bda01269c6fc184d991at					         "Expected SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
9328f9e45fea288542b24a6bda01269c6fc184d991at					         asoc->ssn_of_pdapi,
9338f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.TSN_seq,
9348f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_number,
9358f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_seq);
9368f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
9378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_5;
9388f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
9398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
9408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
9418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
9428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
9438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
9448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Find its place */
9468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(at, &asoc->reasmqueue, sctp_next) {
9478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(at->rec.data.TSN_seq, chk->rec.data.TSN_seq)) {
9488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
9498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * one in queue is bigger than the new one, insert
9508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * before this one
9518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
9528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* A check */
9538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->size_on_reasm_queue += chk->send_size;
9548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ucount_incr(asoc->cnt_on_reasm_queue);
9558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			next = at;
9568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_INSERT_BEFORE(at, chk, sctp_next);
9578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
9588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (at->rec.data.TSN_seq == chk->rec.data.TSN_seq) {
9598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Gak, He sent me a duplicate str seq number */
9608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
9618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * foo bar, I guess I will just free this new guy,
9628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * should we abort too? FIX ME MAYBE? Or it COULD be
9638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * that the SSN's have wrapped. Maybe I should
9648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * compare to TSN somehow... sigh for now just blow
9658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * away the chunk!
9668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
9678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->data) {
9688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(chk->data);
9698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				chk->data = NULL;
9708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
9718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
9728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
9738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
9748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			prev = at;
9758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (TAILQ_NEXT(at, sctp_next) == NULL) {
9768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
9778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * We are at the end, insert it after this
9788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * one
9798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
9808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* check it first */
9818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->size_on_reasm_queue += chk->send_size;
9828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_ucount_incr(asoc->cnt_on_reasm_queue);
9838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				TAILQ_INSERT_AFTER(&asoc->reasmqueue, at, chk, sctp_next);
9848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
9858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
9868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
9878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now the audits */
9898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (prev) {
9908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		prev_tsn = chk->rec.data.TSN_seq - 1;
9918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (prev_tsn == prev->rec.data.TSN_seq) {
9928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
9938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Ok the one I am dropping onto the end is the
9948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * NEXT. A bit of valdiation here.
9958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
9968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((prev->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
9978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_DATA_FIRST_FRAG ||
9988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (prev->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
9998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_DATA_MIDDLE_FRAG) {
10008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
10018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Insert chk MUST be a MIDDLE or LAST
10028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * fragment
10038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
10048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
10058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_DATA_FIRST_FRAG) {
10068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - It can be a midlle or last but not a first\n");
10078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, it's a FIRST!\n");
10088f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg),
10098f9e45fea288542b24a6bda01269c6fc184d991at					         "Can't handle B-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
10108f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.TSN_seq,
10118f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_number,
10128f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_seq);
10138f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
10148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_6;
10158f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
10168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
10178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
10188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
10198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (chk->rec.data.stream_number !=
10208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    prev->rec.data.stream_number) {
10218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
10228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * Huh, need the correct STR here,
10238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * they must be the same.
10248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
102520adfbc28f6151511c1cf170c99a64e98ff6c0eet					SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, sid:%d not the same as at:%d\n",
102633c1af7ee7b7958f1e60412f26cd07d199cc7531t					        chk->rec.data.stream_number,
102733c1af7ee7b7958f1e60412f26cd07d199cc7531t					        prev->rec.data.stream_number);
10288f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg),
10298f9e45fea288542b24a6bda01269c6fc184d991at					         "Expect SID=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
10308f9e45fea288542b24a6bda01269c6fc184d991at					         prev->rec.data.stream_number,
10318f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.TSN_seq,
10328f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_number,
10338f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_seq);
10348f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
10358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_7;
10368f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
10378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
10388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
10398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
104033c1af7ee7b7958f1e60412f26cd07d199cc7531t				if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
104133c1af7ee7b7958f1e60412f26cd07d199cc7531t				    (prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) {
104233c1af7ee7b7958f1e60412f26cd07d199cc7531t					/*
104333c1af7ee7b7958f1e60412f26cd07d199cc7531t					 * Huh, need the same ordering here,
104433c1af7ee7b7958f1e60412f26cd07d199cc7531t					 * they must be the same.
104533c1af7ee7b7958f1e60412f26cd07d199cc7531t					 */
104633c1af7ee7b7958f1e60412f26cd07d199cc7531t					SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, U-bit not constant\n");
104733c1af7ee7b7958f1e60412f26cd07d199cc7531t					snprintf(msg, sizeof(msg),
104833c1af7ee7b7958f1e60412f26cd07d199cc7531t					         "Expect U-bit=%d for TSN=%8.8x, got U-bit=%d",
104933c1af7ee7b7958f1e60412f26cd07d199cc7531t					         (prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0,
105033c1af7ee7b7958f1e60412f26cd07d199cc7531t					         chk->rec.data.TSN_seq,
105133c1af7ee7b7958f1e60412f26cd07d199cc7531t					         (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0);
105233c1af7ee7b7958f1e60412f26cd07d199cc7531t					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
105333c1af7ee7b7958f1e60412f26cd07d199cc7531t					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_7;
105433c1af7ee7b7958f1e60412f26cd07d199cc7531t					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
105533c1af7ee7b7958f1e60412f26cd07d199cc7531t					*abort_flag = 1;
105633c1af7ee7b7958f1e60412f26cd07d199cc7531t					return;
105733c1af7ee7b7958f1e60412f26cd07d199cc7531t				}
10588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((prev->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0 &&
10598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    chk->rec.data.stream_seq !=
10608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    prev->rec.data.stream_seq) {
10618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
10628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * Huh, need the correct STR here,
10638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * they must be the same.
10648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
10658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, Evil plot, sseq:%d not the same as at:%d\n",
10668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						chk->rec.data.stream_seq,
10678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						prev->rec.data.stream_seq);
10688f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg),
10698f9e45fea288542b24a6bda01269c6fc184d991at					         "Expect SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
10708f9e45fea288542b24a6bda01269c6fc184d991at					         prev->rec.data.stream_seq,
10718f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.TSN_seq,
10728f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_number,
10738f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_seq);
10748f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
10758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_8;
10768f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
10778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
10788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
10798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
10808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if ((prev->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
10818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_DATA_LAST_FRAG) {
10828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Insert chk MUST be a FIRST */
10838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) !=
10848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_DATA_FIRST_FRAG) {
10858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Prev check - Gak, evil plot, its not FIRST and it must be!\n");
10868f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg),
10878f9e45fea288542b24a6bda01269c6fc184d991at					         "Expect B-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
10888f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.TSN_seq,
10898f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_number,
10908f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_seq);
10918f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
10928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_9;
10938f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
10948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
10958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
10968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
10978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
10988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (next) {
11018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		post_tsn = chk->rec.data.TSN_seq + 1;
11028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (post_tsn == next->rec.data.TSN_seq) {
11038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
11048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Ok the one I am inserting ahead of is my NEXT
11058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * one. A bit of valdiation here.
11068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
11078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (next->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) {
11088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Insert chk MUST be a last fragment */
11098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK)
11108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    != SCTP_DATA_LAST_FRAG) {
11118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Next is FIRST, we must be LAST\n");
11128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, its not a last!\n");
11138f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg),
11148f9e45fea288542b24a6bda01269c6fc184d991at					         "Expect only E-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
11158f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.TSN_seq,
11168f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_number,
11178f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_seq);
11188f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
11198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_10;
11208f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
11218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
11228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
11238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
11248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if ((next->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
11258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_DATA_MIDDLE_FRAG ||
11268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (next->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
11278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_DATA_LAST_FRAG) {
11288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
11298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Insert chk CAN be MIDDLE or FIRST NOT
11308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * LAST
11318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
11328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((chk->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) ==
11338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_DATA_LAST_FRAG) {
11348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Next is a MIDDLE/LAST\n");
11358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Gak, Evil plot, new prev chunk is a LAST\n");
11368f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg),
11378f9e45fea288542b24a6bda01269c6fc184d991at					         "Didn't expect E-bit, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
11388f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.TSN_seq,
11398f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_number,
11408f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_seq);
11418f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
11428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_11;
11438f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
11448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
11458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
11468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
11478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (chk->rec.data.stream_number !=
11488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    next->rec.data.stream_number) {
11498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
11508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * Huh, need the correct STR here,
11518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * they must be the same.
11528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
11538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Gak, Evil plot, ssn:%d not the same as at:%d\n",
11548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						chk->rec.data.stream_number,
11558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						next->rec.data.stream_number);
11568f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg),
11578f9e45fea288542b24a6bda01269c6fc184d991at					         "Required SID %4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
11588f9e45fea288542b24a6bda01269c6fc184d991at					         next->rec.data.stream_number,
11598f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.TSN_seq,
11608f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_number,
11618f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_seq);
11628f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
11638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_12;
11648f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
11658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
11668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
11678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
116833c1af7ee7b7958f1e60412f26cd07d199cc7531t				if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
116933c1af7ee7b7958f1e60412f26cd07d199cc7531t				    (next->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) {
117033c1af7ee7b7958f1e60412f26cd07d199cc7531t					/*
117133c1af7ee7b7958f1e60412f26cd07d199cc7531t					 * Huh, need the same ordering here,
117233c1af7ee7b7958f1e60412f26cd07d199cc7531t					 * they must be the same.
117333c1af7ee7b7958f1e60412f26cd07d199cc7531t					 */
117433c1af7ee7b7958f1e60412f26cd07d199cc7531t					SCTPDBG(SCTP_DEBUG_INDATA1, "Next check - Gak, Evil plot, U-bit not constant\n");
117533c1af7ee7b7958f1e60412f26cd07d199cc7531t					snprintf(msg, sizeof(msg),
117633c1af7ee7b7958f1e60412f26cd07d199cc7531t					         "Expect U-bit=%d for TSN=%8.8x, got U-bit=%d",
117733c1af7ee7b7958f1e60412f26cd07d199cc7531t					         (next->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0,
117833c1af7ee7b7958f1e60412f26cd07d199cc7531t					         chk->rec.data.TSN_seq,
117933c1af7ee7b7958f1e60412f26cd07d199cc7531t					         (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) ? 1 : 0);
118033c1af7ee7b7958f1e60412f26cd07d199cc7531t					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
118133c1af7ee7b7958f1e60412f26cd07d199cc7531t					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_12;
118233c1af7ee7b7958f1e60412f26cd07d199cc7531t					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
118333c1af7ee7b7958f1e60412f26cd07d199cc7531t					*abort_flag = 1;
118433c1af7ee7b7958f1e60412f26cd07d199cc7531t					return;
118533c1af7ee7b7958f1e60412f26cd07d199cc7531t				}
11868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((next->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == 0 &&
11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    chk->rec.data.stream_seq !=
11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    next->rec.data.stream_seq) {
11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
11908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * Huh, need the correct STR here,
11918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * they must be the same.
11928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
11938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Next chk - Gak, Evil plot, sseq:%d not the same as at:%d\n",
11948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						chk->rec.data.stream_seq,
11958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						next->rec.data.stream_seq);
11968f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg),
11978f9e45fea288542b24a6bda01269c6fc184d991at					         "Required SSN %4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
11988f9e45fea288542b24a6bda01269c6fc184d991at					         next->rec.data.stream_seq,
11998f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.TSN_seq,
12008f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_number,
12018f9e45fea288542b24a6bda01269c6fc184d991at					         chk->rec.data.stream_seq);
12028f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
12038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_13;
12048f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
12068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
12078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
12088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
12098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Do we need to do some delivery? check */
12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_deliver_reasm_check(stcb, asoc);
12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
12168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This is an unfortunate routine. It checks to make sure a evil guy is not
12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * stuffing us full of bad packet fragments. A broken peer could also do this
12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * but this is doubtful. It is to bad I must worry about evil crackers sigh
12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * :< more cycles.
12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
12228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_does_tsn_belong_to_reasm(struct sctp_association *asoc,
12238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint32_t TSN_seq)
12248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *at;
12268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t tsn_est;
12278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(at, &asoc->reasmqueue, sctp_next) {
12298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(TSN_seq, at->rec.data.TSN_seq)) {
12308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* is it one bigger? */
12318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tsn_est = at->rec.data.TSN_seq + 1;
12328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tsn_est == TSN_seq) {
12338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* yep. It better be a last then */
12348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((at->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) !=
12358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_DATA_LAST_FRAG) {
12368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
12378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * Ok this guy belongs next to a guy
12388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * that is NOT last, it should be a
12398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * middle/last, not a complete
12408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * chunk.
12418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
12428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (1);
12438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
12448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
12458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * This guy is ok since its a LAST
12468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * and the new chunk is a fully
12478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * self- contained one.
12488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
12498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (0);
12508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
12518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
12528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (TSN_seq == at->rec.data.TSN_seq) {
12538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Software error since I have a dup? */
12548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
12558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
12568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
12578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Ok, 'at' is larger than new chunk but does it
12588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * need to be right before it.
12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tsn_est = TSN_seq + 1;
12618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tsn_est == at->rec.data.TSN_seq) {
12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Yep, It better be a first */
12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((at->rec.data.rcv_flags & SCTP_DATA_FRAG_MASK) !=
12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_DATA_FIRST_FRAG) {
12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (1);
12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (0);
12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct mbuf **m, int offset, struct sctp_data_chunk *ch, int chk_length,
12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_nets *net, uint32_t *high_tsn, int *abort_flag,
12798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int *break_flag, int last_chunk)
12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Process a data chunk */
12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* struct sctp_tmit_chunk *chk; */
12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk;
12848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t tsn, gap;
12858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *dmbuf;
12860ac02f34d6041cd0018437596a5a9a94685e6919tuexen	int the_len;
12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int need_reasm_check = 0;
12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t strmno, strmseq;
12898f9e45fea288542b24a6bda01269c6fc184d991at	struct mbuf *op_err;
12908f9e45fea288542b24a6bda01269c6fc184d991at	char msg[SCTP_DIAG_INFO_LEN];
12918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int ordered;
12938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t protocol_id;
12948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t chunk_flags;
12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_stream_reset_list *liste;
12968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	chk = NULL;
12988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tsn = ntohl(ch->dp.tsn);
12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	chunk_flags = ch->ch.chunk_flags;
13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((chunk_flags & SCTP_DATA_SACK_IMMEDIATELY) == SCTP_DATA_SACK_IMMEDIATELY) {
13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->send_sack = 1;
13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	protocol_id = ch->dp.protocol_id;
13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ordered = ((chunk_flags & SCTP_DATA_UNORDERED) == 0);
13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_map(tsn, asoc->cumulative_tsn, asoc->highest_tsn_inside_map, SCTP_MAP_TSN_ENTERS);
13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_LTRACE_CHK(stcb->sctp_ep, stcb, ch->ch.chunk_type, tsn);
13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) {
13138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* It is a duplicate */
13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_recvdupdata);
13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->numduptsns < SCTP_MAX_DUP_TSNS) {
13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Record a dup for the next outbound sack */
13178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->dup_tsns[asoc->numduptsns] = tsn;
13188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->numduptsns++;
13198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->send_sack = 1;
13218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
13228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Calculate the number of TSN's between the base and this TSN */
13248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CALC_TSN_TO_GAP(gap, tsn, asoc->mapping_array_base_tsn);
13258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (gap >= (SCTP_MAPPING_ARRAY << 3)) {
13268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Can't hold the bit in the mapping at max array, toss it */
13278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
13288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (gap >= (uint32_t) (asoc->mapping_array_size << 3)) {
13308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK_ASSERT(stcb);
13318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_expand_mapping_array(asoc, gap)) {
13328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't expand, drop it */
13338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
13348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(tsn, *high_tsn)) {
13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*high_tsn = tsn;
13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* See if we have received this one already */
13408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap) ||
13418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_IS_TSN_PRESENT(asoc->nr_mapping_array, gap)) {
13428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_recvdupdata);
13438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->numduptsns < SCTP_MAX_DUP_TSNS) {
13448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Record a dup for the next outbound sack */
13458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->dup_tsns[asoc->numduptsns] = tsn;
13468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->numduptsns++;
13478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->send_sack = 1;
13498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
13508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
13528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Check to see about the GONE flag, duplicates would cause a sack
13538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * to be sent up above
13548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
13558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
13568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
13578f9e45fea288542b24a6bda01269c6fc184d991at	     (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET))) {
13588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
13598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * wait a minute, this guy is gone, there is no longer a
13608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * receiver. Send peer an ABORT!
13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
13628f9e45fea288542b24a6bda01269c6fc184d991at		op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
136347674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*abort_flag = 1;
13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
13668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
13688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now before going further we see if there is room. If NOT then we
13698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * MAY let one through only IF this TSN is the one we are waiting
13708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * for on a partial delivery API.
13718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
13728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now do the tests */
13748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((asoc->cnt_on_all_streams +
13758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	      asoc->cnt_on_reasm_queue +
13768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	      asoc->cnt_msg_on_sb) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue)) ||
13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (((int)asoc->my_rwnd) <= 0)) {
13788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
13798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * When we have NO room in the rwnd we check to make sure
13808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the reader is doing its job...
13818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
13828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->sctp_socket->so_rcv.sb_cc) {
13838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* some to read, wake-up */
13840612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct socket *so;
1386000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			so = SCTP_INP_SO(stcb->sctp_ep);
13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_add_int(&stcb->asoc.refcnt, 1);
13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
13908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_LOCK(so, 1);
13918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(stcb);
13928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_subtract_int(&stcb->asoc.refcnt, 1);
13938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
13948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* assoc was freed while we were unlocked */
13958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SOCKET_UNLOCK(so, 1);
13968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (0);
13978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
13988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
13998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
14000612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
14018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_UNLOCK(so, 1);
14028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* now is it in the mapping array of what we have accepted? */
14058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_map) &&
14068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
14078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Nope not in the valid range dump it */
14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_set_rwnd(stcb, asoc);
14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((asoc->cnt_on_all_streams +
14108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			     asoc->cnt_on_reasm_queue +
14118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			     asoc->cnt_msg_on_sb) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue)) {
14128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_STAT_INCR(sctps_datadropchklmt);
14138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
14148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_STAT_INCR(sctps_datadroprwnd);
14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
14168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*break_flag = 1;
14178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
14188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strmno = ntohs(ch->dp.stream_id);
14218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (strmno >= asoc->streamincnt) {
14228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paramhdr *phdr;
14238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct mbuf *mb;
14248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		mb = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) * 2),
142668beeca578347438d9c434680197647ed551935ft					   0, M_NOWAIT, 1, MT_DATA);
14278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (mb != NULL) {
14288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* add some space up front so prepend will work well */
14298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_RESV_UF(mb, sizeof(struct sctp_chunkhdr));
14308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr = mtod(mb, struct sctp_paramhdr *);
14318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
14328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Error causes are just param's and this one has
14338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * two back to back phdr, one with the error type
14348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * and size, the other with the streamid and a rsvd
14358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
14368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_LEN(mb) = (sizeof(struct sctp_paramhdr) * 2);
14378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr->param_type = htons(SCTP_CAUSE_INVALID_STREAM);
14388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr->param_length =
14398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    htons(sizeof(struct sctp_paramhdr) * 2);
14408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr++;
14418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We insert the stream in the type field */
14428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr->param_type = ch->dp.stream_id;
14438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* And set the length to 0 for the rsvd field */
14448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			phdr->param_length = 0;
14458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_queue_op_err(stcb, mb);
14468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_badsid);
14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK_ASSERT(stcb);
14498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
14508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
14518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->highest_tsn_inside_nr_map = tsn;
14528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tsn == (asoc->cumulative_tsn + 1)) {
14548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Update cum-ack */
14558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->cumulative_tsn = tsn;
14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
14588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
14608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Before we continue lets validate that we are not being fooled by
14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * an evil attacker. We can only have 4k chunks based on our TSN
14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * spread allowed by the mapping array 512 * 8 bits, so there is no
14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * way our stream sequence numbers could have wrapped. We of course
14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * only validate the FIRST fragment so the bit must be set.
14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strmseq = ntohs(ch->dp.stream_sequence);
14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS
14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_LOCK_ASSERT(stcb);
14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->tsn_in_at >= SCTP_TSN_LOG_SIZE) {
14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->tsn_in_at = 0;
14718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->tsn_in_wrapped = 1;
14728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->in_tsnlog[asoc->tsn_in_at].tsn = tsn;
14748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->in_tsnlog[asoc->tsn_in_at].strm = strmno;
14758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->in_tsnlog[asoc->tsn_in_at].seq = strmseq;
14768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->in_tsnlog[asoc->tsn_in_at].sz = chk_length;
14778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->in_tsnlog[asoc->tsn_in_at].flgs = chunk_flags;
14788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->in_tsnlog[asoc->tsn_in_at].stcb = (void *)stcb;
14798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->in_tsnlog[asoc->tsn_in_at].in_pos = asoc->tsn_in_at;
14808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->in_tsnlog[asoc->tsn_in_at].in_out = 1;
14818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->tsn_in_at++;
14828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
14838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((chunk_flags & SCTP_DATA_FIRST_FRAG) &&
14848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (TAILQ_EMPTY(&asoc->resetHead)) &&
14858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (chunk_flags & SCTP_DATA_UNORDERED) == 0 &&
14868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_SSN_GE(asoc->strmin[strmno].last_sequence_delivered, strmseq)) {
14878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* The incoming sseq is behind where we last delivered? */
14888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_INDATA1, "EVIL/Broken-Dup S-SEQ:%d delivered:%d from peer, Abort!\n",
14898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			strmseq, asoc->strmin[strmno].last_sequence_delivered);
14908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14918f9e45fea288542b24a6bda01269c6fc184d991at		snprintf(msg, sizeof(msg), "Delivered SSN=%4.4x, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
14928f9e45fea288542b24a6bda01269c6fc184d991at		         asoc->strmin[strmno].last_sequence_delivered,
14938f9e45fea288542b24a6bda01269c6fc184d991at		         tsn, strmno, strmseq);
14948f9e45fea288542b24a6bda01269c6fc184d991at		op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
14958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_14;
14968f9e45fea288542b24a6bda01269c6fc184d991at		sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
14978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*abort_flag = 1;
14988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
14998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/************************************
15018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * From here down we may find ch-> invalid
15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * so its a good idea NOT to use it.
15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *************************************/
15048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	the_len = (chk_length - sizeof(struct sctp_data_chunk));
15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (last_chunk == 0) {
15078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		dmbuf = SCTP_M_COPYM(*m,
15088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     (offset + sizeof(struct sctp_data_chunk)),
150968beeca578347438d9c434680197647ed551935ft				     the_len, M_NOWAIT);
15108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MBUF_LOGGING
15118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
15128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct mbuf *mat;
1513b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen
1514b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			for (mat = dmbuf; mat; mat = SCTP_BUF_NEXT(mat)) {
15158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BUF_IS_EXTENDED(mat)) {
15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_log_mb(mat, SCTP_MBUF_ICOPY);
15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We can steal the last chunk */
15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int l_len;
15248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		dmbuf = *m;
15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* lop off the top part */
15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_adj(dmbuf, (offset + sizeof(struct sctp_data_chunk)));
15278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BUF_NEXT(dmbuf) == NULL) {
15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			l_len = SCTP_BUF_LEN(dmbuf);
15298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
15308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* need to count up the size hopefully
15318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * does not hit this to often :-0
15328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
15338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct mbuf *lat;
1534b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen
15358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			l_len = 0;
1536b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			for (lat = dmbuf; lat; lat = SCTP_BUF_NEXT(lat)) {
15378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				l_len += SCTP_BUF_LEN(lat);
15388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (l_len > the_len) {
15418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Trim the end round bytes off  too */
15428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m_adj(dmbuf, -(l_len - the_len));
15438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (dmbuf == NULL) {
15468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_nomem);
15478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
15488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((chunk_flags & SCTP_DATA_NOT_FRAG) == SCTP_DATA_NOT_FRAG &&
15508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    asoc->fragmented_delivery_inprogress == 0 &&
15518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    TAILQ_EMPTY(&asoc->resetHead) &&
15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    ((ordered == 0) ||
15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    ((uint16_t)(asoc->strmin[strmno].last_sequence_delivered + 1) == strmseq &&
15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    TAILQ_EMPTY(&asoc->strmin[strmno].inqueue)))) {
15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Candidate for express delivery */
15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Its not fragmented, No PD-API is up, Nothing in the
15588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * delivery queue, Its un-ordered OR ordered and the next to
15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * deliver AND nothing else is stuck on the stream queue,
15608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * And there is room for it in the socket buffer. Lets just
15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * stuff it up the buffer....
15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* It would be nice to avoid this copy if we could :< */
15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_alloc_a_readq(stcb, control);
15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn,
15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					   protocol_id,
15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					   strmno, strmseq,
15698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					   chunk_flags,
15708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					   dmbuf);
15718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control == NULL) {
15728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto failed_express_del;
15738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
15758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
15768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->highest_tsn_inside_nr_map = tsn;
15778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_add_to_readq(stcb->sctp_ep, stcb,
15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                  control, &stcb->sctp_socket->so_rcv,
15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                  1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) {
15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* for ordered, bump what we delivered */
15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->strmin[strmno].last_sequence_delivered++;
15858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_recvexpress);
15878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
15888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_strm_del_alt(stcb, tsn, strmseq, strmno,
15898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					      SCTP_STR_LOG_FROM_EXPRS_DEL);
15908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control = NULL;
15928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto finish_express_del;
15948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenfailed_express_del:
15968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* If we reach here this is a new chunk */
15978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	chk = NULL;
15988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = NULL;
15998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Express for fragmented delivery? */
16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((asoc->fragmented_delivery_inprogress) &&
16018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.control_pdapi) &&
16028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (asoc->str_of_pdapi == strmno) &&
16038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (asoc->ssn_of_pdapi == strmseq)
16048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		) {
16058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control = stcb->asoc.control_pdapi;
16068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((chunk_flags & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) {
16078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't be another first? */
16088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto failed_pdapi_express_del;
16098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tsn == (control->sinfo_tsn + 1)) {
16118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Yep, we can add it on */
16128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int end = 0;
1613b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen
16148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chunk_flags & SCTP_DATA_LAST_FRAG) {
16158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				end = 1;
16168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
16178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_append_to_readq(stcb->sctp_ep, stcb, control, dmbuf, end,
16188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                         tsn,
16198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                         &stcb->sctp_socket->so_rcv)) {
16208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_PRINTF("Append fails end:%d\n", end);
16218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto failed_pdapi_express_del;
16228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
16238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
16258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
16268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->highest_tsn_inside_nr_map = tsn;
16278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
16288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_INCR(sctps_recvexpressm);
16298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->tsn_last_delivered = tsn;
16308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->fragment_flags = chunk_flags;
16318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->tsn_of_pdapi_last_delivered = tsn;
16328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->last_flags_delivered = chunk_flags;
16338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->last_strm_seq_delivered = strmseq;
16348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->last_strm_no_delivered = strmno;
16358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (end) {
16368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* clean up the flags and such */
16378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->fragmented_delivery_inprogress = 0;
16388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((chunk_flags & SCTP_DATA_UNORDERED) == 0) {
16398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->strmin[strmno].last_sequence_delivered++;
16408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
16418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.control_pdapi = NULL;
16428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (TAILQ_EMPTY(&asoc->reasmqueue) == 0) {
16438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* There could be another message ready */
16448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					need_reasm_check = 1;
16458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
16468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
16478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control = NULL;
16488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto finish_express_del;
16498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen failed_pdapi_express_del:
16528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = NULL;
16538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) {
16548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
16558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_nr_map)) {
16568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->highest_tsn_inside_nr_map = tsn;
16578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
16598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap);
16608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(tsn, asoc->highest_tsn_inside_map)) {
16618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->highest_tsn_inside_map = tsn;
16628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((chunk_flags & SCTP_DATA_NOT_FRAG) != SCTP_DATA_NOT_FRAG) {
16658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_alloc_a_chunk(stcb, chk);
16668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk == NULL) {
16678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* No memory so we drop the chunk */
16688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_INCR(sctps_nomem);
16698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (last_chunk == 0) {
16708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* we copied it, free the copy */
16718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(dmbuf);
16728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
16738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
16748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->rec.data.TSN_seq = tsn;
16768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->no_fr_allowed = 0;
16778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->rec.data.stream_seq = strmseq;
16788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->rec.data.stream_number = strmno;
16798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->rec.data.payloadtype = protocol_id;
16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->rec.data.context = stcb->asoc.context;
16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->rec.data.doing_fast_retransmit = 0;
16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->rec.data.rcv_flags = chunk_flags;
16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->asoc = asoc;
16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->send_size = the_len;
16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->whoTo = net;
16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&net->ref_count, 1);
16878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk->data = dmbuf;
16888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
16898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_alloc_a_readq(stcb, control);
16908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn,
16918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    protocol_id,
16928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    strmno, strmseq,
16938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    chunk_flags,
16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    dmbuf);
16958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control == NULL) {
16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* No memory so we drop the chunk */
16978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_INCR(sctps_nomem);
16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (last_chunk == 0) {
16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* we copied it, free the copy */
17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(dmbuf);
17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->length = the_len;
17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Mark it as received */
17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now queue it where it belongs */
17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control != NULL) {
17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* First a sanity check */
17118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->fragmented_delivery_inprogress) {
17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Ok, we have a fragmented delivery in progress if
17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * this chunk is next to deliver OR belongs in our
17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * view to the reassembly, the peer is evil or
17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * broken.
17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint32_t estimate_tsn;
17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			estimate_tsn = asoc->tsn_last_delivered + 1;
17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (TAILQ_EMPTY(&asoc->reasmqueue) &&
17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (estimate_tsn == control->sinfo_tsn)) {
17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Evil/Broke peer */
17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(control->data);
17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				control->data = NULL;
17268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (control->whoFrom) {
17278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_free_remote_addr(control->whoFrom);
17288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control->whoFrom = NULL;
17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
17308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_a_readq(stcb, control);
17318f9e45fea288542b24a6bda01269c6fc184d991at				snprintf(msg, sizeof(msg), "Reas. queue emtpy, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
17328f9e45fea288542b24a6bda01269c6fc184d991at				         tsn, strmno, strmseq);
17338f9e45fea288542b24a6bda01269c6fc184d991at				op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
17348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_15;
17358f9e45fea288542b24a6bda01269c6fc184d991at				sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
17368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*abort_flag = 1;
1737a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt				if (last_chunk) {
1738a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt					*m = NULL;
1739a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt				}
17408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (0);
17418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_does_tsn_belong_to_reasm(asoc, control->sinfo_tsn)) {
17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_m_freem(control->data);
17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control->data = NULL;
17458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (control->whoFrom) {
17468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_free_remote_addr(control->whoFrom);
17478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						control->whoFrom = NULL;
17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
17498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_free_a_readq(stcb, control);
17508f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg), "PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
17518f9e45fea288542b24a6bda01269c6fc184d991at					         tsn, strmno, strmseq);
17528f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
17538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_16;
17548f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
1756a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt					if (last_chunk) {
1757a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt						*m = NULL;
1758a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt					}
17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (0);
17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* No PDAPI running */
17648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Reassembly queue is NOT empty validate
17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * that this tsn does not need to be in
17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * reasembly queue. If it does then our peer
17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * is broken or evil.
17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
17718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_does_tsn_belong_to_reasm(asoc, control->sinfo_tsn)) {
17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_m_freem(control->data);
17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control->data = NULL;
17748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (control->whoFrom) {
17758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_free_remote_addr(control->whoFrom);
17768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						control->whoFrom = NULL;
17778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
17788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_free_a_readq(stcb, control);
17798f9e45fea288542b24a6bda01269c6fc184d991at					snprintf(msg, sizeof(msg), "No PD ongoing, got TSN=%8.8x, SID=%4.4x, SSN=%4.4x",
17808f9e45fea288542b24a6bda01269c6fc184d991at					         tsn, strmno, strmseq);
17818f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
17828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_17;
17838f9e45fea288542b24a6bda01269c6fc184d991at					sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
17848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*abort_flag = 1;
1785a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt					if (last_chunk) {
1786a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt						*m = NULL;
1787a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt					}
17888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (0);
17898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
17908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
17918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* ok, if we reach here we have passed the sanity checks */
17938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chunk_flags & SCTP_DATA_UNORDERED) {
17948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* queue directly into socket buffer */
17958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_mark_non_revokable(asoc, control->sinfo_tsn);
17968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_add_to_readq(stcb->sctp_ep, stcb,
17978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                  control,
17988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                  &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
17998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
18008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
18018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Special check for when streams are resetting. We
18028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * could be more smart about this and check the
18038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * actual stream to see if it is not being reset..
18048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * that way we would not create a HOLB when amongst
18058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * streams being reset and those not being reset.
18068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 *
18078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * We take complete messages that have a stream reset
18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * intervening (aka the TSN is after where our
18098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * cum-ack needs to be) off and put them on a
18108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * pending_reply_queue. The reassembly ones we do
18118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * not have to worry about since they are all sorted
18128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * and proceessed by TSN order. It is only the
18138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * singletons I must worry about.
18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
18158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) &&
18168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_TSN_GT(tsn, liste->tsn)) {
18178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
18188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * yep its past where we need to reset... go
18198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * ahead and queue it.
18208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
18218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (TAILQ_EMPTY(&asoc->pending_reply_queue)) {
18228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* first one on */
18238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_INSERT_TAIL(&asoc->pending_reply_queue, control, next);
18248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
18258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					struct sctp_queued_to_read *ctlOn, *nctlOn;
18268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					unsigned char inserted = 0;
18278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH_SAFE(ctlOn, &asoc->pending_reply_queue, next, nctlOn) {
18298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_TSN_GT(control->sinfo_tsn, ctlOn->sinfo_tsn)) {
18308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
18318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else {
18328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							/* found it */
18338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							TAILQ_INSERT_BEFORE(ctlOn, control, next);
18348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							inserted = 1;
18358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							break;
18368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
18378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
18388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (inserted == 0) {
18398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*
18408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * must be put at end, use
18418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * prevP (all setup from
18428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * loop) to setup nextP.
18438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
18448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						TAILQ_INSERT_TAIL(&asoc->pending_reply_queue, control, next);
18458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
18468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
18478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
18488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_queue_data_to_stream(stcb, asoc, control, abort_flag);
18498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (*abort_flag) {
1850a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt					if (last_chunk) {
1851a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt						*m = NULL;
1852a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt					}
18538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (0);
18548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
18558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
18588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Into the re-assembly queue */
18598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_queue_data_for_reasm(stcb, asoc, chk, abort_flag);
18608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*abort_flag) {
18618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
18628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * the assoc is now gone and chk was put onto the
18638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * reasm queue, which has all been freed.
18648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
1865a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt			if (last_chunk) {
1866a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt				*m = NULL;
1867a056414a1e3cf1aadf9cf5bcd2c60277a6fd911dt			}
18688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
18698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenfinish_express_del:
1872000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	if (tsn == (asoc->cumulative_tsn + 1)) {
1873000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		/* Update cum-ack */
1874000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		asoc->cumulative_tsn = tsn;
18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (last_chunk) {
18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*m = NULL;
18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ordered) {
18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR_COUNTER64(sctps_inorderchunks);
18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR_COUNTER64(sctps_inunorderchunks);
18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_STAT_INCR(sctps_recvdata);
18858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Set it present please */
18868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
18878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_strm_del_alt(stcb, tsn, strmseq, strmno, SCTP_STR_LOG_FROM_MARK_TSN);
18888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_map(asoc->mapping_array_base_tsn, asoc->cumulative_tsn,
18918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			     asoc->highest_tsn_inside_map, SCTP_MAP_PREPARE_SLIDE);
18928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* check the special flag for stream resets */
18948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) &&
18958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_TSN_GE(asoc->cumulative_tsn, liste->tsn)) {
18968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
18978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * we have finished working through the backlogged TSN's now
18988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * time to reset streams. 1: call reset function. 2: free
18998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * pending_reply space 3: distribute any chunks in
19008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * pending_reply_queue.
19018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
19028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_queued_to_read *ctl, *nctl;
19038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1904c1f5477d96c0c5178c74caad234035e534c37bdct		sctp_reset_in_stream(stcb, liste->number_entries, liste->list_of_streams);
19058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_REMOVE(&asoc->resetHead, liste, next_resp);
19068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(liste, SCTP_M_STRESET);
19078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*sa_ignore FREED_MEMORY*/
19088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		liste = TAILQ_FIRST(&asoc->resetHead);
19098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (TAILQ_EMPTY(&asoc->resetHead)) {
19108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* All can be removed */
19118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, next, nctl) {
19128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				TAILQ_REMOVE(&asoc->pending_reply_queue, ctl, next);
19138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_queue_data_to_stream(stcb, asoc, ctl, abort_flag);
19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (*abort_flag) {
1915b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen					return (0);
19168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH_SAFE(ctl, &asoc->pending_reply_queue, next, nctl) {
19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_TSN_GT(ctl->sinfo_tsn, liste->tsn)) {
19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
19238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
19248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * if ctl->sinfo_tsn is <= liste->tsn we can
19258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * process it which is the NOT of
19268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * ctl->sinfo_tsn > liste->tsn
19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				TAILQ_REMOVE(&asoc->pending_reply_queue, ctl, next);
19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_queue_data_to_stream(stcb, asoc, ctl, abort_flag);
19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (*abort_flag) {
1931b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen					return (0);
19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Now service re-assembly to pick up anything that has been
19378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * held on reassembly queue?
19388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
19398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_deliver_reasm_check(stcb, asoc);
19408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		need_reasm_check = 0;
19418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (need_reasm_check) {
19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Another one waits ? */
19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_deliver_reasm_check(stcb, asoc);
19468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (1);
19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint8_t sctp_map_lookup_tab[256] = {
19518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 4,
19538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 5,
19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 4,
19578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 6,
19598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 4,
19618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 5,
19638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 4,
19658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 7,
19678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 4,
19698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 5,
19718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 4,
19738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 6,
19758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 4,
19778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 5,
19798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 4,
19818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 3,
19828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  0, 1, 0, 2, 0, 1, 0, 8
19838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen};
19848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
19878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_slide_mapping_arrays(struct sctp_tcb *stcb)
19888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
19908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now we also need to check the mapping array in a couple of ways.
19918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * 1) Did we move the cum-ack point?
19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
19938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * When you first glance at this you might think
19948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * that all entries that make up the postion
19958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * of the cum-ack would be in the nr-mapping array
19968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * only.. i.e. things up to the cum-ack are always
19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * deliverable. Thats true with one exception, when
19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * its a fragmented message we may not deliver the data
19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * until some threshold (or all of it) is in place. So
20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * we must OR the nr_mapping_array and mapping_array to
20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * get a true picture of the cum-ack.
20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int at;
20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t val;
20068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int slide_from, slide_end, lgap, distance;
20078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t old_cumack, old_base, old_highest, highest_tsn;
20088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
20108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	old_cumack = asoc->cumulative_tsn;
20128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	old_base = asoc->mapping_array_base_tsn;
20138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	old_highest = asoc->highest_tsn_inside_map;
20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
20158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * We could probably improve this a small bit by calculating the
20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * offset of the current cum-ack as the starting point.
20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	at = 0;
20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (slide_from = 0; slide_from < stcb->asoc.mapping_array_size; slide_from++) {
20208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		val = asoc->nr_mapping_array[slide_from] | asoc->mapping_array[slide_from];
20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (val == 0xff) {
20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			at += 8;
20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* there is a 0 bit */
20258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			at += sctp_map_lookup_tab[val];
20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
20278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->cumulative_tsn = asoc->mapping_array_base_tsn + (at-1);
20308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(asoc->cumulative_tsn, asoc->highest_tsn_inside_map) &&
20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen            SCTP_TSN_GT(asoc->cumulative_tsn, asoc->highest_tsn_inside_nr_map)) {
20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
20348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		panic("huh, cumack 0x%x greater than high-tsn 0x%x in map",
20358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		      asoc->cumulative_tsn, asoc->highest_tsn_inside_map);
20368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
20378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("huh, cumack 0x%x greater than high-tsn 0x%x in map - should panic?\n",
20388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    asoc->cumulative_tsn, asoc->highest_tsn_inside_map);
20398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_print_mapping_array(asoc);
20408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_map(0, 6, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
20428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->highest_tsn_inside_map = asoc->cumulative_tsn;
20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->highest_tsn_inside_nr_map = asoc->cumulative_tsn;
20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(asoc->highest_tsn_inside_nr_map, asoc->highest_tsn_inside_map)) {
20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		highest_tsn = asoc->highest_tsn_inside_nr_map;
20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		highest_tsn = asoc->highest_tsn_inside_map;
20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((asoc->cumulative_tsn == highest_tsn) && (at >= 8)) {
20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* The complete array was completed by a single FR */
20548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* highest becomes the cum-ack */
20558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int clr;
20568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		unsigned int i;
20588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* clear the array */
20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		clr = ((at+7) >> 3);
20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (clr > asoc->mapping_array_size) {
20638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			clr = asoc->mapping_array_size;
20648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memset(asoc->mapping_array, 0, clr);
20668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memset(asoc->nr_mapping_array, 0, clr);
20678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
20688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < asoc->mapping_array_size; i++) {
20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((asoc->mapping_array[i]) || (asoc->nr_mapping_array[i])) {
207047a306d634abf33223ef347472c4b1cd441d139ftuexen				SCTP_PRINTF("Error Mapping array's not clean at clear\n");
20718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_print_mapping_array(asoc);
20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->mapping_array_base_tsn = asoc->cumulative_tsn + 1;
20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map = asoc->cumulative_tsn;
20778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (at >= 8) {
20788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we can slide the mapping array down */
20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* slide_from holds where we hit the first NON 0xff byte */
20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * now calculate the ceiling of the move using our highest
20838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * TSN value
20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CALC_TSN_TO_GAP(lgap, highest_tsn, asoc->mapping_array_base_tsn);
20868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		slide_end = (lgap >> 3);
20878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (slide_end < slide_from) {
20888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_print_mapping_array(asoc);
20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
20908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			panic("impossible slide");
20918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
209247a306d634abf33223ef347472c4b1cd441d139ftuexen			SCTP_PRINTF("impossible slide lgap:%x slide_end:%x slide_from:%x? at:%d\n",
209347a306d634abf33223ef347472c4b1cd441d139ftuexen			            lgap, slide_end, slide_from, at);
20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
20968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (slide_end > asoc->mapping_array_size) {
20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			panic("would overrun buffer");
21008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
210147a306d634abf33223ef347472c4b1cd441d139ftuexen			SCTP_PRINTF("Gak, would have overrun map end:%d slide_end:%d\n",
210247a306d634abf33223ef347472c4b1cd441d139ftuexen			            asoc->mapping_array_size, slide_end);
21038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			slide_end = asoc->mapping_array_size;
21048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
21058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		distance = (slide_end - slide_from) + 1;
21078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_map(old_base, old_cumack, old_highest,
21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     SCTP_MAP_PREPARE_SLIDE);
21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_map((uint32_t) slide_from, (uint32_t) slide_end,
21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     (uint32_t) lgap, SCTP_MAP_SLIDE_FROM);
21128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (distance + slide_from > asoc->mapping_array_size ||
21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    distance < 0) {
21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Here we do NOT slide forward the array so that
21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * hopefully when more data comes in to fill it up
21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * we will be able to slide it forward. Really I
21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * don't think this should happen :-0
21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_map((uint32_t) distance, (uint32_t) slide_from,
21248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     (uint32_t) asoc->mapping_array_size,
21258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     SCTP_MAP_SLIDE_NONE);
21268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
21288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int ii;
21298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			for (ii = 0; ii < distance; ii++) {
21318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->mapping_array[ii] = asoc->mapping_array[slide_from + ii];
21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->nr_mapping_array[ii] = asoc->nr_mapping_array[slide_from + ii];
21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			for (ii = distance; ii < asoc->mapping_array_size; ii++) {
21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->mapping_array[ii] = 0;
21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->nr_mapping_array[ii] = 0;
21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->highest_tsn_inside_map + 1 == asoc->mapping_array_base_tsn) {
21408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->highest_tsn_inside_map += (slide_from << 3);
21418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->highest_tsn_inside_nr_map + 1 == asoc->mapping_array_base_tsn) {
21438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->highest_tsn_inside_nr_map += (slide_from << 3);
21448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->mapping_array_base_tsn += (slide_from << 3);
21468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_map(asoc->mapping_array_base_tsn,
21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     asoc->cumulative_tsn, asoc->highest_tsn_inside_map,
21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     SCTP_MAP_SLIDE_RESULT);
21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
21560ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_sack_check(struct sctp_tcb *stcb, int was_a_gap)
21578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
21588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
21598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t highest_tsn;
21600ac02f34d6041cd0018437596a5a9a94685e6919tuexen
21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(asoc->highest_tsn_inside_nr_map, asoc->highest_tsn_inside_map)) {
21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		highest_tsn = asoc->highest_tsn_inside_nr_map;
21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		highest_tsn = asoc->highest_tsn_inside_map;
21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
21698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now we need to see if we need to queue a sack or just start the
21708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * timer (if allowed).
21718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
21738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
21748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Ok special case, in SHUTDOWN-SENT case. here we
21758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * maker sure SACK timer is off and instead send a
21768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * SHUTDOWN and a SACK
21778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
21788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
21798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
21808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA+SCTP_LOC_18);
21818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2182000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		sctp_send_shutdown(stcb,
21838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				   ((stcb->asoc.alternate) ? stcb->asoc.alternate : stcb->asoc.primary_destination));
21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int is_a_gap;
21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* is there a gap now ? */
21898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		is_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn);
21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
21928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT DAC algorithm: increase number of packets
21938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * received since last ack
21948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
21958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.cmt_dac_pkts_rcvd++;
2196000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb->asoc.send_sack == 1) ||      /* We need to send a SACK */
21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((was_a_gap) && (is_a_gap == 0)) ||	/* was a gap, but no
21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                                         * longer is one */
22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (stcb->asoc.numduptsns) ||          /* we have dup's */
22018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (is_a_gap) ||                       /* is still a gap */
22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (stcb->asoc.delayed_ack == 0) ||    /* Delayed sack disabled */
22038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (stcb->asoc.data_pkts_seen >= stcb->asoc.sack_freq)	/* hit limit of pkts */
22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			) {
22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2206b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			if ((stcb->asoc.sctp_cmt_on_off > 0) &&
22078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) &&
22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (stcb->asoc.send_sack == 0) &&
22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (stcb->asoc.numduptsns == 0) &&
22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (stcb->asoc.delayed_ack) &&
22118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer))) {
22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
22148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * CMT DAC algorithm: With CMT,
22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * delay acks even in the face of
22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * reordering. Therefore, if acks
22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * that do not have to be sent
22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * because of the above reasons,
22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * will be delayed. That is, acks
22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * that would have been sent due to
22228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * gap reports will be delayed with
22238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * DAC. Start the delayed ack timer.
22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_RECV,
22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                 stcb->sctp_ep, stcb, NULL);
22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
22288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Ok we must build a SACK since the
22308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * timer is pending, we got our
22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * first packet OR there are gaps or
22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * duplicates.
22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
22348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer);
22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
22388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (!SCTP_OS_TIMER_PENDING(&stcb->asoc.dack_timer.timer)) {
22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_RECV,
22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                 stcb->sctp_ep, stcb, NULL);
22418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
22428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
22458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc)
22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
22498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk;
22508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t tsize, pd_point;
22518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t nxt_todel;
22528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->fragmented_delivery_inprogress) {
22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_service_reassembly(stcb, asoc);
22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Can we proceed further, i.e. the PD-API is complete */
22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->fragmented_delivery_inprogress) {
22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no */
22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now is there some other chunk I can deliver from the reassembly
22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * queue.
22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
22658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen doit_again:
22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	chk = TAILQ_FIRST(&asoc->reasmqueue);
22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (chk == NULL) {
22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->size_on_reasm_queue = 0;
22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->cnt_on_reasm_queue = 0;
22708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
22718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	nxt_todel = asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered + 1;
22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) &&
22748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    ((nxt_todel == chk->rec.data.stream_seq) ||
22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED))) {
22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Yep the first one is here. We setup to start reception,
22788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * by backing down the TSN just in case we can't deliver.
22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
22808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
22828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Before we start though either all of the message should
22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * be here or the socket buffer max or nothing on the
22848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * delivery queue and something can be delivered.
22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->sctp_socket) {
2287cdc78af866f2b29865707afee7ea65e1706b4ff8t			pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
22888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       stcb->sctp_ep->partial_delivery_point);
22898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
22908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			pd_point = stcb->sctp_ep->partial_delivery_point;
22918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_all_msg_on_reasm(asoc, &tsize) || (tsize >= pd_point)) {
22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->fragmented_delivery_inprogress = 1;
22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->tsn_last_delivered = chk->rec.data.TSN_seq - 1;
22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->str_of_pdapi = chk->rec.data.stream_number;
22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->ssn_of_pdapi = chk->rec.data.stream_seq;
22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->pdapi_ppid = chk->rec.data.payloadtype;
22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->fragment_flags = chk->rec.data.rcv_flags;
22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_service_reassembly(stcb, asoc);
23008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->fragmented_delivery_inprogress == 0) {
23018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto doit_again;
23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
23068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
23088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
2309e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen                  struct sockaddr *src, struct sockaddr *dst,
231051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen                  struct sctphdr *sh, struct sctp_inpcb *inp,
231151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen                  struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t *high_tsn,
231251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__)
231351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen                  uint8_t use_mflowid, uint32_t mflowid,
231451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif
231551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen		  uint32_t vrf_id, uint16_t port)
23168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
23178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_data_chunk *ch, chunk_buf;
23188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
23198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int num_chunks = 0;	/* number of control chunks processed */
23208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int stop_proc = 0;
23218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int chk_length, break_flag, last_chunk;
23228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int abort_flag = 0, was_a_gap;
23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m;
23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t highest_tsn;
23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* set the rwnd */
23278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_set_rwnd(stcb, &stcb->asoc);
23288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m = *mm;
23308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_LOCK_ASSERT(stcb);
23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
23328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(asoc->highest_tsn_inside_nr_map, asoc->highest_tsn_inside_map)) {
23338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		highest_tsn = asoc->highest_tsn_inside_nr_map;
23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		highest_tsn = asoc->highest_tsn_inside_map;
23368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn);
23388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
23398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * setup where we got the last DATA packet from for any SACK that
23408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * may need to go out. Don't bump the net. This is done ONLY when a
23418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * chunk is assigned.
23428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
23438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->last_data_chunk_from = net;
23448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __Panda__
23468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
23478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now before we proceed we must figure out if this is a wasted
23488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * cluster... i.e. it is a small packet sent in and yet the driver
23498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * underneath allocated a full cluster for it. If so we must copy it
23508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * to a smaller mbuf and free up the cluster mbuf. This will help
23518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * with cluster starvation. Note for __Panda__ we don't do this
23528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * since it has clusters all the way down to 64 bytes.
23538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
23548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BUF_LEN(m) < (long)MLEN && SCTP_BUF_NEXT(m) == NULL) {
23558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we only handle mbufs that are singletons.. not chains */
235668beeca578347438d9c434680197647ed551935ft		m = sctp_get_mbuf_for_msg(SCTP_BUF_LEN(m), 0, M_NOWAIT, 1, MT_DATA);
23578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (m) {
23588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* ok lets see if we can copy the data up */
23598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			caddr_t *from, *to;
23608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* get the pointers and copy */
23618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to = mtod(m, caddr_t *);
23628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			from = mtod((*mm), caddr_t *);
23638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(to, from, SCTP_BUF_LEN((*mm)));
23648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* copy the length and free up the old */
23658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_LEN(m) = SCTP_BUF_LEN((*mm));
23668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(*mm);
23678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* sucess, back copy */
23688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*mm = m;
23698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
23708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We are in trouble in the mbuf world .. yikes */
23718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m = *mm;
23728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
23758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get pointer to the first chunk header */
23768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ch = (struct sctp_data_chunk *)sctp_m_getptr(m, *offset,
23778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						     sizeof(struct sctp_data_chunk), (uint8_t *) & chunk_buf);
23788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ch == NULL) {
23798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (1);
23808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
23828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * process all DATA chunks...
23838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
23848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*high_tsn = asoc->cumulative_tsn;
23858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	break_flag = 0;
23868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->data_pkts_seen++;
23878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (stop_proc == 0) {
23888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* validate chunk length */
23898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk_length = ntohs(ch->ch.chunk_length);
23908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (length - *offset < chk_length) {
23918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* all done, mutulated chunk */
23928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stop_proc = 1;
2393b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			continue;
23948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ch->ch.chunk_type == SCTP_DATA) {
2396a06ca64c1ea60031147a135d015c66e4803beb1ct			if ((size_t)chk_length < sizeof(struct sctp_data_chunk)) {
23978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
23988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Need to send an abort since we had a
23998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * invalid data chunk.
24008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
24018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct mbuf *op_err;
24028f9e45fea288542b24a6bda01269c6fc184d991at				char msg[SCTP_DIAG_INFO_LEN];
24038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24048f9e45fea288542b24a6bda01269c6fc184d991at				snprintf(msg, sizeof(msg), "DATA chunk of length %d",
24058f9e45fea288542b24a6bda01269c6fc184d991at				         chk_length);
24068f9e45fea288542b24a6bda01269c6fc184d991at				op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
24078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_19;
2408e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen				sctp_abort_association(inp, stcb, m, iphlen,
2409e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen				                       src, dst, sh, op_err,
241051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__)
241151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen				                       use_mflowid, mflowid,
241251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif
241351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen				                       vrf_id, port);
24148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (2);
24158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
2416a06ca64c1ea60031147a135d015c66e4803beb1ct			if ((size_t)chk_length == sizeof(struct sctp_data_chunk)) {
2417a06ca64c1ea60031147a135d015c66e4803beb1ct				/*
2418a06ca64c1ea60031147a135d015c66e4803beb1ct				 * Need to send an abort since we had an
2419a06ca64c1ea60031147a135d015c66e4803beb1ct				 * empty data chunk.
2420a06ca64c1ea60031147a135d015c66e4803beb1ct				 */
2421a06ca64c1ea60031147a135d015c66e4803beb1ct				struct mbuf *op_err;
2422a06ca64c1ea60031147a135d015c66e4803beb1ct
2423a06ca64c1ea60031147a135d015c66e4803beb1ct				op_err = sctp_generate_no_user_data_cause(ch->dp.tsn);
2424a06ca64c1ea60031147a135d015c66e4803beb1ct				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_19;
2425a06ca64c1ea60031147a135d015c66e4803beb1ct				sctp_abort_association(inp, stcb, m, iphlen,
2426a06ca64c1ea60031147a135d015c66e4803beb1ct				                       src, dst, sh, op_err,
2427a06ca64c1ea60031147a135d015c66e4803beb1ct#if defined(__FreeBSD__)
2428a06ca64c1ea60031147a135d015c66e4803beb1ct				                       use_mflowid, mflowid,
2429a06ca64c1ea60031147a135d015c66e4803beb1ct#endif
2430a06ca64c1ea60031147a135d015c66e4803beb1ct				                       vrf_id, port);
2431a06ca64c1ea60031147a135d015c66e4803beb1ct				return (2);
2432a06ca64c1ea60031147a135d015c66e4803beb1ct			}
24338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
24348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_audit_log(0xB1, 0);
24358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
24368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_SIZE32(chk_length) == (length - *offset)) {
24378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				last_chunk = 1;
24388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
24398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				last_chunk = 0;
24408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_process_a_data_chunk(stcb, asoc, mm, *offset, ch,
24428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      chk_length, net, high_tsn, &abort_flag, &break_flag,
24438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      last_chunk)) {
24448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				num_chunks++;
24458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (abort_flag)
24478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (2);
24488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (break_flag) {
24508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
24518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Set because of out of rwnd space and no
24528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * drop rep space left.
24538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
24548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stop_proc = 1;
2455b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				continue;
24568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
24588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* not a data chunk in the data region */
24598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			switch (ch->ch.chunk_type) {
24608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_INITIATION:
24618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_INITIATION_ACK:
24628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_SELECTIVE_ACK:
2463b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			case SCTP_NR_SELECTIVE_ACK:
24648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_HEARTBEAT_REQUEST:
24658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_HEARTBEAT_ACK:
24668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_ABORT_ASSOCIATION:
24678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_SHUTDOWN:
24688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_SHUTDOWN_ACK:
24698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_OPERATION_ERROR:
24708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_COOKIE_ECHO:
24718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_COOKIE_ACK:
24728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_ECN_ECHO:
24738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_ECN_CWR:
24748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_SHUTDOWN_COMPLETE:
24758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_AUTHENTICATION:
24768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_ASCONF_ACK:
24778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_PACKET_DROPPED:
24788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_STREAM_RESET:
24798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_FORWARD_CUM_TSN:
24808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case SCTP_ASCONF:
24818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
24828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Now, what do we do with KNOWN chunks that
24838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * are NOT in the right place?
24848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 *
24858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * For now, I do nothing but ignore them. We
24868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * may later want to add sysctl stuff to
24878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * switch out and do either an ABORT() or
24888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * possibly process them.
24898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
24908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_strict_data_order)) {
24918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					struct mbuf *op_err;
24928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24938f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, "");
249451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen					sctp_abort_association(inp, stcb,
249551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen					                       m, iphlen,
2496e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen					                       src, dst,
249751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen					                       sh, op_err,
249851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__)
249951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen					                       use_mflowid, mflowid,
250051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif
250151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen					                       vrf_id, port);
25028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (2);
25038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
25048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
25058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			default:
25068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* unknown chunk type, use bit rules */
25078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (ch->ch.chunk_type & 0x40) {
25088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Add a error report to the queue */
25098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					struct mbuf *merr;
25108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					struct sctp_paramhdr *phd;
25118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
251268beeca578347438d9c434680197647ed551935ft					merr = sctp_get_mbuf_for_msg(sizeof(*phd), 0, M_NOWAIT, 1, MT_DATA);
25138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (merr) {
25148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						phd = mtod(merr, struct sctp_paramhdr *);
25158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*
25168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * We cheat and use param
25178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * type since we did not
25188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * bother to define a error
25198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * cause struct. They are
25208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * the same basic format
25218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * with different names.
25228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
25238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						phd->param_type =
25248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							htons(SCTP_CAUSE_UNRECOG_CHUNK);
25258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						phd->param_length =
25268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							htons(chk_length + sizeof(*phd));
25278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_BUF_LEN(merr) = sizeof(*phd);
252868beeca578347438d9c434680197647ed551935ft						SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
25298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_BUF_NEXT(merr)) {
2530290e3870bdc4b436f18bfe30e6c243205fc29702t							if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) {
25314df11f5004bbb4c768851ee41149ba6982c60f29tuexen								sctp_m_freem(merr);
25324df11f5004bbb4c768851ee41149ba6982c60f29tuexen							} else {
25334df11f5004bbb4c768851ee41149ba6982c60f29tuexen								sctp_queue_op_err(stcb, merr);
25344df11f5004bbb4c768851ee41149ba6982c60f29tuexen							}
25358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else {
25368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_m_freem(merr);
25378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
25388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
25398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
25408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((ch->ch.chunk_type & 0x80) == 0) {
25418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* discard the rest of this packet */
25428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stop_proc = 1;
25438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}	/* else skip this bad chunk and
25448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * continue... */
25458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
2546b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			}	/* switch of chunk type */
25478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*offset += SCTP_SIZE32(chk_length);
25498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((*offset >= length) || stop_proc) {
25508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no more data left in the mbuf chain */
25518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stop_proc = 1;
25528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
25538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ch = (struct sctp_data_chunk *)sctp_m_getptr(m, *offset,
25558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							     sizeof(struct sctp_data_chunk), (uint8_t *) & chunk_buf);
25568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ch == NULL) {
25578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*offset = length;
25588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stop_proc = 1;
2559b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			continue;
25608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2561b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	}
25628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (break_flag) {
25638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
25648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * we need to report rwnd overrun drops.
25658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
256638bf75f6cfcdbd22c0e22e82f236c2b7634591f1tuexen		sctp_send_packet_dropped(stcb, net, *mm, length, iphlen, 0);
25678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (num_chunks) {
25698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
25708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Did we get data, if so update the time for auto-close and
25718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * give peer credit for being alive.
25728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
25738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_recvpktwithdata);
25748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
25758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
25768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       stcb->asoc.overall_error_count,
25778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       0,
25788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       SCTP_FROM_SCTP_INDATA,
25798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       __LINE__);
25808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.overall_error_count = 0;
25828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_last_rcvd);
25838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now service all of the reassm queue if needed */
25858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!(TAILQ_EMPTY(&asoc->reasmqueue)))
25868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_service_queues(stcb, asoc);
25878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
25898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Assure that we ack right away */
25908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.send_sack = 1;
25918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Start a sack timer or QUEUE a SACK for sending */
25930ac02f34d6041cd0018437596a5a9a94685e6919tuexen	sctp_sack_check(stcb, was_a_gap);
25948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
25958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
25968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
25988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1, uint32_t last_tsn,
25998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   uint16_t frag_strt, uint16_t frag_end, int nr_sacking,
26008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   int *num_frs,
26018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   uint32_t *biggest_newly_acked_tsn,
26028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   uint32_t  *this_sack_lowest_newack,
26030ac02f34d6041cd0018437596a5a9a94685e6919tuexen			   int *rto_ok)
26048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
26058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *tp1;
26068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	unsigned int theTSN;
26078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int j, wake_him = 0, circled = 0;
26088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Recover the tp1 we last saw */
26108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tp1 = *p_tp1;
26118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (tp1 == NULL) {
26128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
26138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (j = frag_strt; j <= frag_end; j++) {
26158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		theTSN = j + last_tsn;
26168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		while (tp1) {
26178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->rec.data.doing_fast_retransmit)
26188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(*num_frs) += 1;
26198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*-
26218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * CMT: CUCv2 algorithm. For each TSN being
26228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * processed from the sent queue, track the
26238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * next expected pseudo-cumack, or
26248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * rtx_pseudo_cumack, if required. Separate
26258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * cumack trackers for first transmissions,
26268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * and retransmissions.
26278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
26288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((tp1->whoTo->find_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) &&
26298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (tp1->snd_count == 1)) {
26308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->whoTo->pseudo_cumack = tp1->rec.data.TSN_seq;
26318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->whoTo->find_pseudo_cumack = 0;
26328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
26338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((tp1->whoTo->find_rtx_pseudo_cumack == 1) && (tp1->sent < SCTP_DATAGRAM_RESEND) &&
26348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (tp1->snd_count > 1)) {
26358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->whoTo->rtx_pseudo_cumack = tp1->rec.data.TSN_seq;
26368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->whoTo->find_rtx_pseudo_cumack = 0;
26378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
26388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->rec.data.TSN_seq == theTSN) {
26398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
26408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*-
26418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * must be held until
26428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * cum-ack passes
26438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
26448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (tp1->sent < SCTP_DATAGRAM_RESEND) {
26458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*-
26468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * If it is less than RESEND, it is
26478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * now no-longer in flight.
26488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * Higher values may already be set
26498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * via previous Gap Ack Blocks...
26508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * i.e. ACKED or RESEND.
26518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
26528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_TSN_GT(tp1->rec.data.TSN_seq,
26538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                *biggest_newly_acked_tsn)) {
26548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							*biggest_newly_acked_tsn = tp1->rec.data.TSN_seq;
26558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
26568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*-
26578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * CMT: SFR algo (and HTNA) - set
26588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * saw_newack to 1 for dest being
26598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * newly acked. update
26608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * this_sack_highest_newack if
26618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * appropriate.
26628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
26638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (tp1->rec.data.chunk_was_revoked == 0)
26648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							tp1->whoTo->saw_newack = 1;
26658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_TSN_GT(tp1->rec.data.TSN_seq,
26678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                tp1->whoTo->this_sack_highest_newack)) {
26688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							tp1->whoTo->this_sack_highest_newack =
26698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								tp1->rec.data.TSN_seq;
26708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
26718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*-
26728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * CMT DAC algo: also update
26738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * this_sack_lowest_newack
26748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
26758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (*this_sack_lowest_newack == 0) {
26768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
26778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sctp_log_sack(*this_sack_lowest_newack,
26788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									      last_tsn,
26798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									      tp1->rec.data.TSN_seq,
26808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									      0,
26818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									      0,
26828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									      SCTP_LOG_TSN_ACKED);
26838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
26848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							*this_sack_lowest_newack = tp1->rec.data.TSN_seq;
26858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
26868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*-
26878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * CMT: CUCv2 algorithm. If (rtx-)pseudo-cumack for corresp
26888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * dest is being acked, then we have a new (rtx-)pseudo-cumack. Set
26898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * new_(rtx_)pseudo_cumack to TRUE so that the cwnd for this dest can be
26908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * updated. Also trigger search for the next expected (rtx-)pseudo-cumack.
26918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * Separate pseudo_cumack trackers for first transmissions and
26928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * retransmissions.
26938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
26948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (tp1->rec.data.TSN_seq == tp1->whoTo->pseudo_cumack) {
26958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (tp1->rec.data.chunk_was_revoked == 0) {
26968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								tp1->whoTo->new_pseudo_cumack = 1;
26978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
26988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							tp1->whoTo->find_pseudo_cumack = 1;
26998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
27008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
27018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK);
27028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
27038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (tp1->rec.data.TSN_seq == tp1->whoTo->rtx_pseudo_cumack) {
27048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (tp1->rec.data.chunk_was_revoked == 0) {
27058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								tp1->whoTo->new_pseudo_cumack = 1;
27068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
27078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							tp1->whoTo->find_rtx_pseudo_cumack = 1;
27088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
27098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
27108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_log_sack(*biggest_newly_acked_tsn,
27118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								      last_tsn,
27128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								      tp1->rec.data.TSN_seq,
27138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								      frag_strt,
27148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								      frag_end,
27158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								      SCTP_LOG_TSN_ACKED);
27168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
27178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
27188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP,
27198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								       tp1->whoTo->flight_size,
27208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								       tp1->book_size,
27218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								       (uintptr_t)tp1->whoTo,
27228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								       tp1->rec.data.TSN_seq);
27238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
27248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_flight_size_decrease(tp1);
27258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
27268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							(*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo,
27278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen														     tp1);
27288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
27298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_total_flight_decrease(stcb, tp1);
27308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						tp1->whoTo->net_ack += tp1->send_size;
27328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (tp1->snd_count < 2) {
27338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							/*-
27348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * True non-retransmited chunk
27358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 */
27368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							tp1->whoTo->net_ack2 += tp1->send_size;
27378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							/*-
27398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * update RTO too ?
27408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 */
27418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (tp1->do_rtt) {
27428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								if (*rto_ok) {
27438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									tp1->whoTo->RTO =
27448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen										sctp_calculate_rto(stcb,
27458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen												   &stcb->asoc,
27468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen												   tp1->whoTo,
27478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen												   &tp1->sent_rcv_time,
27488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen												   sctp_align_safe_nocopy,
27498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen												   SCTP_RTT_FROM_DATA);
27508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									*rto_ok = 0;
27518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								}
27528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								if (tp1->whoTo->rto_needed == 0) {
27538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									tp1->whoTo->rto_needed = 1;
27548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								}
27558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								tp1->do_rtt = 0;
27568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
27578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
27588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
27608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (tp1->sent <= SCTP_DATAGRAM_RESEND) {
27618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_TSN_GT(tp1->rec.data.TSN_seq,
27628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                stcb->asoc.this_sack_highest_gap)) {
27638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							stcb->asoc.this_sack_highest_gap =
27648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								tp1->rec.data.TSN_seq;
27658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
27668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (tp1->sent == SCTP_DATAGRAM_RESEND) {
27678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_ucount_decr(stcb->asoc.sent_queue_retran_cnt);
27688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
27698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_audit_log(0xB2,
27708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								       (stcb->asoc.sent_queue_retran_cnt & 0x000000ff));
27718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
27728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
27738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
27748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*-
27758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * All chunks NOT UNSENT fall through here and are marked
27768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * (leave PR-SCTP ones that are to skip alone though)
27778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
2778446be8e8a472f6e688885674d2430118fc4be5d7t					if ((tp1->sent != SCTP_FORWARD_TSN_SKIP) &&
277960db5740d3bcc26fd4ebc19b6b0652506994fd14t					    (tp1->sent != SCTP_DATAGRAM_NR_ACKED)) {
27808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						tp1->sent = SCTP_DATAGRAM_MARKED;
2781446be8e8a472f6e688885674d2430118fc4be5d7t					}
27828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (tp1->rec.data.chunk_was_revoked) {
27838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* deflate the cwnd */
27848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						tp1->whoTo->cwnd -= tp1->book_size;
27858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						tp1->rec.data.chunk_was_revoked = 0;
27868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
27878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* NR Sack code here */
278860db5740d3bcc26fd4ebc19b6b0652506994fd14t					if (nr_sacking &&
278960db5740d3bcc26fd4ebc19b6b0652506994fd14t					    (tp1->sent != SCTP_DATAGRAM_NR_ACKED)) {
279060db5740d3bcc26fd4ebc19b6b0652506994fd14t						if (stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) {
279160db5740d3bcc26fd4ebc19b6b0652506994fd14t							stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues--;
279260db5740d3bcc26fd4ebc19b6b0652506994fd14t#ifdef INVARIANTS
279360db5740d3bcc26fd4ebc19b6b0652506994fd14t						} else {
279460db5740d3bcc26fd4ebc19b6b0652506994fd14t							panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number);
279560db5740d3bcc26fd4ebc19b6b0652506994fd14t#endif
279660db5740d3bcc26fd4ebc19b6b0652506994fd14t						}
279760db5740d3bcc26fd4ebc19b6b0652506994fd14t						tp1->sent = SCTP_DATAGRAM_NR_ACKED;
27988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (tp1->data) {
27998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							/* sa_ignore NO_NULL_CHK */
28008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
28018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_m_freem(tp1->data);
28028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							tp1->data = NULL;
28038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
28048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						wake_him++;
28058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
28068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
28078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
28088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}	/* if (tp1->TSN_seq == theTSN) */
28098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, theTSN)) {
28108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
28118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
28128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1 = TAILQ_NEXT(tp1, sctp_next);
28138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((tp1 == NULL) && (circled == 0)) {
28148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				circled++;
28158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
28168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
28178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}	/* end while (tp1) */
28188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tp1 == NULL) {
28198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			circled = 0;
28208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
28218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* In case the fragments were not in order we must reset */
28238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end for (j = fragStart */
28248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*p_tp1 = tp1;
28258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (wake_him);	/* Return value only used for nr-sack */
28268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
28278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
28308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct sctp_association *asoc,
28318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t last_tsn, uint32_t *biggest_tsn_acked,
28328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *biggest_newly_acked_tsn, uint32_t *this_sack_lowest_newack,
28330ac02f34d6041cd0018437596a5a9a94685e6919tuexen		int num_seg, int num_nr_seg, int *rto_ok)
28348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
28358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_gap_ack_block *frag, block;
28368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *tp1;
28378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
28388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int num_frs = 0;
28398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int chunk_freed;
28408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int non_revocable;
28418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t frag_strt, frag_end, prev_frag_end;
28428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tp1 = TAILQ_FIRST(&asoc->sent_queue);
28448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	prev_frag_end = 0;
28458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	chunk_freed = 0;
28468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < (num_seg + num_nr_seg); i++) {
28488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (i == num_seg) {
28498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			prev_frag_end = 0;
28508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1 = TAILQ_FIRST(&asoc->sent_queue);
28518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		frag = (struct sctp_gap_ack_block *)sctp_m_getptr(m, *offset,
28538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                                                  sizeof(struct sctp_gap_ack_block), (uint8_t *) &block);
28548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*offset += sizeof(block);
28558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (frag == NULL) {
28568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (chunk_freed);
28578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		frag_strt = ntohs(frag->start);
28598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		frag_end = ntohs(frag->end);
28608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (frag_strt > frag_end) {
28628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* This gap report is malformed, skip it. */
28638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
28648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (frag_strt <= prev_frag_end) {
28668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* This gap report is not in order, so restart. */
28678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 tp1 = TAILQ_FIRST(&asoc->sent_queue);
28688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT((last_tsn + frag_end), *biggest_tsn_acked)) {
28708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*biggest_tsn_acked = last_tsn + frag_end;
28718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (i < num_seg) {
28738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			non_revocable = 0;
28748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
28758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			non_revocable = 1;
28768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_process_segment_range(stcb, &tp1, last_tsn, frag_strt, frag_end,
28788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                               non_revocable, &num_frs, biggest_newly_acked_tsn,
28790ac02f34d6041cd0018437596a5a9a94685e6919tuexen		                               this_sack_lowest_newack, rto_ok)) {
28808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chunk_freed = 1;
28818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		prev_frag_end = frag_end;
28838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
28858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (num_frs)
28868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_fr(*biggest_tsn_acked,
28878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			            *biggest_newly_acked_tsn,
28888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			            last_tsn, SCTP_FR_LOG_BIGGEST_TSNS);
28898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (chunk_freed);
28918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
28928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
28948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_check_for_revoked(struct sctp_tcb *stcb,
28958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       struct sctp_association *asoc, uint32_t cumack,
28968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       uint32_t biggest_tsn_acked)
28978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
28988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *tp1;
28998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
29018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, cumack)) {
29028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
29038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * ok this guy is either ACK or MARKED. If it is
29048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * ACKED it has been previously acked but not this
29058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * time i.e. revoked.  If it is MARKED it was ACK'ed
29068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * again.
29078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
29088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, biggest_tsn_acked)) {
29098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
29108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
29118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->sent == SCTP_DATAGRAM_ACKED) {
29128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* it has been revoked */
29138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->sent = SCTP_DATAGRAM_SENT;
29148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->rec.data.chunk_was_revoked = 1;
29158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* We must add this stuff back in to
29168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * assure timers and such get started.
29178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
29188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
29198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
29208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						       tp1->whoTo->flight_size,
29218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						       tp1->book_size,
29228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						       (uintptr_t)tp1->whoTo,
29238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						       tp1->rec.data.TSN_seq);
29248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_flight_size_increase(tp1);
29268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_total_flight_increase(stcb, tp1);
29278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* We inflate the cwnd to compensate for our
29288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * artificial inflation of the flight_size.
29298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
29308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->whoTo->cwnd += tp1->book_size;
29318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
29328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_log_sack(asoc->last_acked_seq,
29338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      cumack,
29348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      tp1->rec.data.TSN_seq,
29358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      0,
29368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      0,
29378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      SCTP_LOG_TSN_REVOKED);
29388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (tp1->sent == SCTP_DATAGRAM_MARKED) {
29408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* it has been re-acked in this SACK */
29418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->sent = SCTP_DATAGRAM_ACKED;
29428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
29438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tp1->sent == SCTP_DATAGRAM_UNSENT)
29458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
29468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
29488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
29518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
29528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   uint32_t biggest_tsn_acked, uint32_t biggest_tsn_newly_acked, uint32_t this_sack_lowest_newack, int accum_moved)
29538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
29548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *tp1;
29558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int strike_flag = 0;
29568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct timeval now;
29578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int tot_retrans = 0;
29588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t sending_seq;
29598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
29608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int num_dests_sacked = 0;
29618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
29638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * select the sending_seq, this is either the next thing ready to be
29648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * sent but not transmitted, OR, the next seq we assign.
29658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
29668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tp1 = TAILQ_FIRST(&stcb->asoc.send_queue);
29678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (tp1 == NULL) {
29688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sending_seq = asoc->sending_seq;
29698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
29708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sending_seq = tp1->rec.data.TSN_seq;
29718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* CMT DAC algo: finding out if SACK is a mixed SACK */
29748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((asoc->sctp_cmt_on_off > 0) &&
29758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
29768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
29778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->saw_newack)
29788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				num_dests_sacked++;
29798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2981a8657c4fc04fb9cc82100f648810d51ec6ab155at	if (stcb->asoc.prsctp_supported) {
29828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)SCTP_GETTIME_TIMEVAL(&now);
29838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
29858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		strike_flag = 0;
29868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tp1->no_fr_allowed) {
29878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* this one had a timeout or something */
29888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
29898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
29918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->sent < SCTP_DATAGRAM_RESEND)
29928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_fr(biggest_tsn_newly_acked,
29938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    tp1->rec.data.TSN_seq,
29948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    tp1->sent,
29958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    SCTP_FR_LOG_CHECK_STRIKE);
29968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, biggest_tsn_acked) ||
29988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    tp1->sent == SCTP_DATAGRAM_UNSENT) {
29998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* done */
30008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
30018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3002a8657c4fc04fb9cc82100f648810d51ec6ab155at		if (stcb->asoc.prsctp_supported) {
30038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((PR_SCTP_TTL_ENABLED(tp1->flags)) && tp1->sent < SCTP_DATAGRAM_ACKED) {
30048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Is it expired? */
30058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __FreeBSD__
30068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (timercmp(&now, &tp1->rec.data.timetodrop, >)) {
30078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
30088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (timevalcmp(&now, &tp1->rec.data.timetodrop, >)) {
30098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
30108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Yes so drop it */
30118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (tp1->data != NULL) {
301247674b651417d493ff4e0318113fd7beeef119dbtuexen						(void)sctp_release_pr_sctp_chunk(stcb, tp1, 1,
30138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen										 SCTP_SO_NOT_LOCKED);
30148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
30158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
30168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
30188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, asoc->this_sack_highest_gap)) {
30218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* we are beyond the tsn in the sack  */
30228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
30238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tp1->sent >= SCTP_DATAGRAM_RESEND) {
30258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* either a RESEND, ACKED, or MARKED */
30268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* skip */
30278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->sent == SCTP_FORWARD_TSN_SKIP) {
30288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Continue strikin FWD-TSN chunks */
30298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->rec.data.fwd_tsn_cnt++;
30308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
30318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
30328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
30348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT : SFR algo (covers part of DAC and HTNA as well)
30358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
30368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tp1->whoTo && tp1->whoTo->saw_newack == 0) {
30378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
30388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * No new acks were receieved for data sent to this
30398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * dest. Therefore, according to the SFR algo for
30408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * CMT, no data sent to this dest can be marked for
30418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * FR using this SACK.
30428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
30438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
30448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (tp1->whoTo && SCTP_TSN_GT(tp1->rec.data.TSN_seq,
30458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                                     tp1->whoTo->this_sack_highest_newack)) {
30468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
30478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * CMT: New acks were receieved for data sent to
30488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * this dest. But no new acks were seen for data
30498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * sent after tp1. Therefore, according to the SFR
30508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * algo for CMT, tp1 cannot be marked for FR using
30518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * this SACK. This step covers part of the DAC algo
30528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * and the HTNA algo as well.
30538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
30548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
30558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
30578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Here we check to see if we were have already done a FR
30588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * and if so we see if the biggest TSN we saw in the sack is
30598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * smaller than the recovery point. If so we don't strike
30608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the tsn... otherwise we CAN strike the TSN.
30618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
30628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
30638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * @@@ JRI: Check for CMT
30648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * if (accum_moved && asoc->fast_retran_loss_recovery && (sctp_cmt_on_off == 0)) {
30658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
30668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (accum_moved && asoc->fast_retran_loss_recovery) {
30678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
30688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Strike the TSN if in fast-recovery and cum-ack
30698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * moved.
30708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
30718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
30728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_fr(biggest_tsn_newly_acked,
30738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    tp1->rec.data.TSN_seq,
30748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    tp1->sent,
30758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    SCTP_FR_LOG_STRIKE_CHUNK);
30768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
30778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->sent < SCTP_DATAGRAM_RESEND) {
30788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->sent++;
30798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
30808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((asoc->sctp_cmt_on_off > 0) &&
30818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
30828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
30838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * CMT DAC algorithm: If SACK flag is set to
30848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * 0, then lowest_newack test will not pass
30858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * because it would have been set to the
30868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * cumack earlier. If not already to be
30878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * rtx'd, If not a mixed sack and if tp1 is
30888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * not between two sacked TSNs, then mark by
30898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * one more.
30908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * NOTE that we are marking by one additional time since the SACK DAC flag indicates that
30918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * two packets have been received after this missing TSN.
30928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
30938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) &&
30948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_TSN_GT(this_sack_lowest_newack, tp1->rec.data.TSN_seq)) {
30958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
30968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_fr(16 + num_dests_sacked,
30978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    tp1->rec.data.TSN_seq,
30988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    tp1->sent,
30998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    SCTP_FR_LOG_STRIKE_CHUNK);
31008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
31018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->sent++;
31028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if ((tp1->rec.data.doing_fast_retransmit) &&
31058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		           (asoc->sctp_cmt_on_off == 0)) {
31068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
31078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * For those that have done a FR we must take
31088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * special consideration if we strike. I.e the
31098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * biggest_newly_acked must be higher than the
31108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * sending_seq at the time we did the FR.
31118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
31128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (
31138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_FR_TO_ALTERNATE
31148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
31158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * If FR's go to new networks, then we must only do
31168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * this for singly homed asoc's. However if the FR's
31178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * go to the same network (Armando's work) then its
31188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * ok to FR multiple times.
31198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
31208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(asoc->numnets < 2)
31218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
31228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(1)
31238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
31248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				) {
31258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_TSN_GE(biggest_tsn_newly_acked,
31278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                tp1->rec.data.fast_retran_tsn)) {
31288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
31298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * Strike the TSN, since this ack is
31308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * beyond where things were when we
31318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * did a FR.
31328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
31338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
31348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_fr(biggest_tsn_newly_acked,
31358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    tp1->rec.data.TSN_seq,
31368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    tp1->sent,
31378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    SCTP_FR_LOG_STRIKE_CHUNK);
31388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
31398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (tp1->sent < SCTP_DATAGRAM_RESEND) {
31408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						tp1->sent++;
31418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
31428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					strike_flag = 1;
31438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((asoc->sctp_cmt_on_off > 0) &&
31448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
31458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*
31468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * CMT DAC algorithm: If
31478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * SACK flag is set to 0,
31488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * then lowest_newack test
31498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * will not pass because it
31508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * would have been set to
31518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * the cumack earlier. If
31528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * not already to be rtx'd,
31538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * If not a mixed sack and
31548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * if tp1 is not between two
31558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * sacked TSNs, then mark by
31568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * one more.
31578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * NOTE that we are marking by one additional time since the SACK DAC flag indicates that
31588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * two packets have been received after this missing TSN.
31598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
31608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((tp1->sent < SCTP_DATAGRAM_RESEND) &&
31618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (num_dests_sacked == 1) &&
31628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    SCTP_TSN_GT(this_sack_lowest_newack,
31638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						                tp1->rec.data.TSN_seq)) {
31648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
31658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sctp_log_fr(32 + num_dests_sacked,
31668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									    tp1->rec.data.TSN_seq,
31678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									    tp1->sent,
31688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									    SCTP_FR_LOG_STRIKE_CHUNK);
31698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
31708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (tp1->sent < SCTP_DATAGRAM_RESEND) {
31718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								tp1->sent++;
31728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
31738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
31748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
31758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
31788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * JRI: TODO: remove code for HTNA algo. CMT's
31798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * SFR algo covers HTNA.
31808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
31818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (SCTP_TSN_GT(tp1->rec.data.TSN_seq,
31828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                       biggest_tsn_newly_acked)) {
31838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
31848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * We don't strike these: This is the  HTNA
31858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * algorithm i.e. we don't strike If our TSN is
31868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * larger than the Highest TSN Newly Acked.
31878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
31888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			;
31898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
31908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Strike the TSN */
31918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
31928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_fr(biggest_tsn_newly_acked,
31938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    tp1->rec.data.TSN_seq,
31948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    tp1->sent,
31958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    SCTP_FR_LOG_STRIKE_CHUNK);
31968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->sent < SCTP_DATAGRAM_RESEND) {
31988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->sent++;
31998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((asoc->sctp_cmt_on_off > 0) &&
32018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_BASE_SYSCTL(sctp_cmt_use_dac)) {
32028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
32038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * CMT DAC algorithm: If SACK flag is set to
32048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * 0, then lowest_newack test will not pass
32058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * because it would have been set to the
32068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * cumack earlier. If not already to be
32078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * rtx'd, If not a mixed sack and if tp1 is
32088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * not between two sacked TSNs, then mark by
32098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * one more.
32108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * NOTE that we are marking by one additional time since the SACK DAC flag indicates that
32118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * two packets have been received after this missing TSN.
32128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
32138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((tp1->sent < SCTP_DATAGRAM_RESEND) && (num_dests_sacked == 1) &&
32148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_TSN_GT(this_sack_lowest_newack, tp1->rec.data.TSN_seq)) {
32158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
32168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_fr(48 + num_dests_sacked,
32178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    tp1->rec.data.TSN_seq,
32188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    tp1->sent,
32198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    SCTP_FR_LOG_STRIKE_CHUNK);
32208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
32218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->sent++;
32228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
32238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tp1->sent == SCTP_DATAGRAM_RESEND) {
32268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_nets *alt;
32278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* fix counts and things */
32298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
32308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND,
32318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       (tp1->whoTo ? (tp1->whoTo->flight_size) : 0),
32328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       tp1->book_size,
32338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       (uintptr_t)tp1->whoTo,
32348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       tp1->rec.data.TSN_seq);
32358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->whoTo) {
32378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->whoTo->net_ack++;
32388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_flight_size_decrease(tp1);
32398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
32408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo,
32418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen												     tp1);
32428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
32438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
3244000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
32458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) {
32468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_rwnd(SCTP_INCREASE_PEER_RWND,
32478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					      asoc->peers_rwnd, tp1->send_size, SCTP_BASE_SYSCTL(sctp_peer_chunk_oh));
32488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* add back to the rwnd */
32508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->peers_rwnd += (tp1->send_size + SCTP_BASE_SYSCTL(sctp_peer_chunk_oh));
3251000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
32528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* remove from the total flight */
32538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_total_flight_decrease(stcb, tp1);
32548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3255a8657c4fc04fb9cc82100f648810d51ec6ab155at			if ((stcb->asoc.prsctp_supported) &&
32568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (PR_SCTP_RTX_ENABLED(tp1->flags))) {
32578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Has it been retransmitted tv_sec times? - we store the retran count there. */
32588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->snd_count > tp1->rec.data.timetodrop.tv_sec) {
32598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Yes, so drop it */
32608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (tp1->data != NULL) {
326147674b651417d493ff4e0318113fd7beeef119dbtuexen						(void)sctp_release_pr_sctp_chunk(stcb, tp1, 1,
32628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen										 SCTP_SO_NOT_LOCKED);
32638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
32648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Make sure to flag we had a FR */
32658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->net_ack++;
32668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
32678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
3268000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			}
326947a306d634abf33223ef347472c4b1cd441d139ftuexen			/* SCTP_PRINTF("OK, we are now ready to FR this guy\n"); */
32708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
32718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_log_fr(tp1->rec.data.TSN_seq, tp1->snd_count,
32728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    0, SCTP_FR_MARKED);
32738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (strike_flag) {
32758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* This is a subsequent FR */
32768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_STAT_INCR(sctps_sendmultfastretrans);
32778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
32798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->sctp_cmt_on_off > 0) {
32808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
32818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * CMT: Using RTX_SSTHRESH policy for CMT.
32828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * If CMT is being used, then pick dest with
32838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * largest ssthresh for any retransmission.
32848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
32858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->no_fr_allowed = 1;
32868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				alt = tp1->whoTo;
32878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*sa_ignore NO_NULL_CHK*/
32888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (asoc->sctp_cmt_pf > 0) {
32898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* JRS 5/18/07 - If CMT PF is on, use the PF version of find_alt_net() */
32908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					alt = sctp_find_alternate_net(stcb, alt, 2);
32918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
32928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* JRS 5/18/07 - If only CMT is on, use the CMT version of find_alt_net() */
32938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                                        /*sa_ignore NO_NULL_CHK*/
32948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					alt = sctp_find_alternate_net(stcb, alt, 1);
32958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
32968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (alt == NULL) {
32978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					alt = tp1->whoTo;
32988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
32998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
33008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * CUCv2: If a different dest is picked for
33018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * the retransmission, then new
33028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * (rtx-)pseudo_cumack needs to be tracked
33038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * for orig dest. Let CUCv2 track new (rtx-)
33048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * pseudo-cumack always.
33058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
33068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->whoTo) {
33078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->find_pseudo_cumack = 1;
33088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->find_rtx_pseudo_cumack = 1;
33098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
33108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {/* CMT is OFF */
33128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_FR_TO_ALTERNATE
33148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Can we find an alternate? */
33158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				alt = sctp_find_alternate_net(stcb, tp1->whoTo, 0);
33168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
33178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
33188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * default behavior is to NOT retransmit
33198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * FR's to an alternate. Armando Caro's
33208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * paper details why.
33218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
33228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				alt = tp1->whoTo;
33238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
33248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
33258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1->rec.data.doing_fast_retransmit = 1;
33278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tot_retrans++;
33288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* mark the sending seq for possible subsequent FR's */
33298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
333047a306d634abf33223ef347472c4b1cd441d139ftuexen			 * SCTP_PRINTF("Marking TSN for FR new value %x\n",
33318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * (uint32_t)tpi->rec.data.TSN_seq);
33328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
33338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (TAILQ_EMPTY(&asoc->send_queue)) {
33348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
33358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * If the queue of send is empty then its
33368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * the next sequence number that will be
33378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * assigned so we subtract one from this to
33388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * get the one we last sent.
33398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
33408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->rec.data.fast_retran_tsn = sending_seq;
33418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
33428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
33438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * If there are chunks on the send queue
33448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * (unsent data that has made it from the
33458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * stream queues but not out the door, we
33468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * take the first one (which will have the
33478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * lowest TSN) and subtract one to get the
33488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * one we last sent.
33498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
33508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_tmit_chunk *ttt;
33518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				ttt = TAILQ_FIRST(&asoc->send_queue);
33538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->rec.data.fast_retran_tsn =
33548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ttt->rec.data.TSN_seq;
33558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
33568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->do_rtt) {
33588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
33598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * this guy had a RTO calculation pending on
33608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * it, cancel it
33618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
3362b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				if ((tp1->whoTo != NULL) &&
3363b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				    (tp1->whoTo->rto_needed == 0)) {
33648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->rto_needed = 1;
33658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
33668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->do_rtt = 0;
33678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
33688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (alt != tp1->whoTo) {
33698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* yes, there is an alternate. */
33708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_remote_addr(tp1->whoTo);
33718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*sa_ignore FREED_MEMORY*/
33728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->whoTo = alt;
33738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				atomic_add_int(&alt->ref_count, 1);
33748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
33758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
33788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_tmit_chunk *
33808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
33818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_association *asoc)
33828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
33838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *tp1, *tp2, *a_adv = NULL;
33848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct timeval now;
33858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int now_filled = 0;
33868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3387a8657c4fc04fb9cc82100f648810d51ec6ab155at	if (asoc->prsctp_supported == 0) {
33888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
33898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
33918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tp1->sent != SCTP_FORWARD_TSN_SKIP &&
3392bd461585c67bdbabcad5414912c2528605350344t		    tp1->sent != SCTP_DATAGRAM_RESEND &&
339360db5740d3bcc26fd4ebc19b6b0652506994fd14t		    tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
33948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no chance to advance, out of here */
33958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
33968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
3398446be8e8a472f6e688885674d2430118fc4be5d7t			if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) ||
339960db5740d3bcc26fd4ebc19b6b0652506994fd14t			    (tp1->sent == SCTP_DATAGRAM_NR_ACKED)) {
34008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_misc_ints(SCTP_FWD_TSN_CHECK,
34018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       asoc->advanced_peer_ack_point,
34028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       tp1->rec.data.TSN_seq, 0, 0);
34038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
34048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!PR_SCTP_ENABLED(tp1->flags)) {
34068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
34078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * We can't fwd-tsn past any that are reliable aka
34088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * retransmitted until the asoc fails.
34098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
34108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
34118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!now_filled) {
34138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(void)SCTP_GETTIME_TIMEVAL(&now);
34148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			now_filled = 1;
34158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
34178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * now we got a chunk which is marked for another
34188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * retransmission to a PR-stream but has run out its chances
34198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * already maybe OR has been marked to skip now. Can we skip
34208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * it if its a resend?
34218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
34228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tp1->sent == SCTP_DATAGRAM_RESEND &&
34238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (PR_SCTP_TTL_ENABLED(tp1->flags))) {
34248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
34258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Now is this one marked for resend and its time is
34268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * now up?
34278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
34288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __FreeBSD__
34298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (timercmp(&now, &tp1->rec.data.timetodrop, >)) {
34308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
34318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (timevalcmp(&now, &tp1->rec.data.timetodrop, >)) {
34328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
34338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Yes so drop it */
34348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->data) {
34358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(void)sctp_release_pr_sctp_chunk(stcb, tp1,
343647674b651417d493ff4e0318113fd7beeef119dbtuexen					    1, SCTP_SO_NOT_LOCKED);
34378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
34388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
34398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
34408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * No, we are done when hit one for resend
34418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * whos time as not expired.
34428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
34438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
34448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
34458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
34478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Ok now if this chunk is marked to drop it we can clean up
34488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the chunk, advance our peer ack point and we can check
34498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the next chunk.
34508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
3451bd461585c67bdbabcad5414912c2528605350344t		if ((tp1->sent == SCTP_FORWARD_TSN_SKIP) ||
345260db5740d3bcc26fd4ebc19b6b0652506994fd14t		    (tp1->sent == SCTP_DATAGRAM_NR_ACKED)) {
34538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* advance PeerAckPoint goes forward */
34548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, asoc->advanced_peer_ack_point)) {
34558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->advanced_peer_ack_point = tp1->rec.data.TSN_seq;
34568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				a_adv = tp1;
34578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (tp1->rec.data.TSN_seq == asoc->advanced_peer_ack_point) {
34588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* No update but we do save the chk */
34598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				a_adv = tp1;
34608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
34618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
34628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
34638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * If it is still in RESEND we can advance no
34648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * further
34658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
34668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
34678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (a_adv);
34708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
34718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
34738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_fs_audit(struct sctp_association *asoc)
34748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
34758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk;
3476b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0;
34778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int entry_flight, entry_cnt, ret;
3478b2fe8b34ee35fbfe6e9379ae37579f047f79b4f7t
34798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	entry_flight = asoc->total_flight;
34808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	entry_cnt = asoc->total_flight_count;
34818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ret = 0;
3482000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
34838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->pr_sctp_cnt >= asoc->sent_queue_cnt)
34848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
34858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
34878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->sent < SCTP_DATAGRAM_RESEND) {
348847a306d634abf33223ef347472c4b1cd441d139ftuexen			SCTP_PRINTF("Chk TSN:%u size:%d inflight cnt:%d\n",
348947a306d634abf33223ef347472c4b1cd441d139ftuexen			            chk->rec.data.TSN_seq,
349047a306d634abf33223ef347472c4b1cd441d139ftuexen			            chk->send_size,
349147a306d634abf33223ef347472c4b1cd441d139ftuexen			            chk->snd_count);
34928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inflight++;
34938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (chk->sent == SCTP_DATAGRAM_RESEND) {
34948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			resend++;
34958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (chk->sent < SCTP_DATAGRAM_ACKED) {
34968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inbetween++;
34978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (chk->sent > SCTP_DATAGRAM_ACKED) {
34988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			above++;
34998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
35008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			acked++;
35018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inflight > 0) || (inbetween > 0)) {
35058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
35068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		panic("Flight size-express incorrect? \n");
35078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
350847a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("asoc->total_flight:%d cnt:%d\n",
350947a306d634abf33223ef347472c4b1cd441d139ftuexen		            entry_flight, entry_cnt);
35108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("Flight size-express incorrect F:%d I:%d R:%d Ab:%d ACK:%d\n",
35128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    inflight, inbetween, resend, above, acked);
35138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ret = 1;
35148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
35158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (ret);
35178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
35188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
35218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_window_probe_recovery(struct sctp_tcb *stcb,
35228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                   struct sctp_association *asoc,
35238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   struct sctp_tmit_chunk *tp1)
35248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
35258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tp1->window_probe = 0;
35268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((tp1->sent >= SCTP_DATAGRAM_ACKED) || (tp1->data == NULL)) {
35278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* TSN's skipped we do NOT move back. */
35288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_FLIGHT_LOG_DWN_WP_FWD,
35298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       tp1->whoTo->flight_size,
35308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       tp1->book_size,
35318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       (uintptr_t)tp1->whoTo,
35328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       tp1->rec.data.TSN_seq);
35338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
35348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* First setup this by shrinking flight */
35368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
35378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo,
35388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									     tp1);
35398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_flight_size_decrease(tp1);
35418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_total_flight_decrease(stcb, tp1);
35428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now mark for resend */
35438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tp1->sent = SCTP_DATAGRAM_RESEND;
35448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_ucount_incr(asoc->sent_queue_retran_cnt);
3545000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
35468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
35478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_WP,
35488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       tp1->whoTo->flight_size,
35498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       tp1->book_size,
35508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       (uintptr_t)tp1->whoTo,
35518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       tp1->rec.data.TSN_seq);
35528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
35548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
35568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
35578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                         uint32_t rwnd, int *abort_now, int ecne_seen)
35588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
35598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
35608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
35618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *tp1, *tp2;
35628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t old_rwnd;
35638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int win_probe_recovery = 0;
35648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int win_probe_recovered = 0;
35658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int j, done_once = 0;
3566b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int rto_ok = 1;
35678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_SACK_ARRIVALS_ENABLE) {
35698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_SACK_LOG_EXPRESS, cumack,
35708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		               rwnd, stcb->asoc.last_acked_seq, stcb->asoc.peers_rwnd);
35718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_LOCK_ASSERT(stcb);
35738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS
35748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.cumack_log[stcb->asoc.cumack_log_at] = cumack;
35758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.cumack_log_at++;
35768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.cumack_log_at > SCTP_TSN_LOG_SIZE) {
35778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.cumack_log_at = 0;
35788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
35808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
35818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	old_rwnd = asoc->peers_rwnd;
35828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(asoc->last_acked_seq, cumack)) {
35838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* old ack */
35848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
35858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (asoc->last_acked_seq == cumack) {
35868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Window update sack */
35878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->peers_rwnd = sctp_sbspace_sub(rwnd,
35888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh))));
35898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
35908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* SWS sender side engages */
35918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->peers_rwnd = 0;
35928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->peers_rwnd > old_rwnd) {
35948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto again;
35958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
35978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* First setup for CC stuff */
36008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
36018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(cumack, net->cwr_window_tsn)) {
36028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Drag along the window_tsn for cwr's */
36038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwr_window_tsn = cumack;
36048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->prev_cwnd = net->cwnd;
36068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->net_ack = 0;
36078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->net_ack2 = 0;
36088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
36108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT: Reset CUC and Fast recovery algo variables before
36118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * SACK processing
36128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
36138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->new_pseudo_cumack = 0;
36148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->will_exit_fast_recovery = 0;
36158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) {
36168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(*stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack)(stcb, net);
36178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) {
36208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t send_s;
36218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!TAILQ_EMPTY(&asoc->sent_queue)) {
36238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1 = TAILQ_LAST(&asoc->sent_queue,
36248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 sctpchunk_listhead);
36258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			send_s = tp1->rec.data.TSN_seq + 1;
36268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
36278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			send_s = asoc->sending_seq;
36288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GE(cumack, send_s)) {
36308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef INVARIANTS
36318f9e45fea288542b24a6bda01269c6fc184d991at			struct mbuf *op_err;
36328f9e45fea288542b24a6bda01269c6fc184d991at			char msg[SCTP_DIAG_INFO_LEN];
36338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
36358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
36368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			panic("Impossible sack 1");
36378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
363881616c6a3e184f46276632dd15aa489cd06d94dftuexen
36398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*abort_now = 1;
36408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* XXX */
36418f9e45fea288542b24a6bda01269c6fc184d991at			snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal then TSN %8.8x",
36428f9e45fea288542b24a6bda01269c6fc184d991at			         cumack, send_s);
36438f9e45fea288542b24a6bda01269c6fc184d991at			op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
36448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25;
36458f9e45fea288542b24a6bda01269c6fc184d991at			sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
36468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
36478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
36488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->this_sack_highest_gap = cumack;
36518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
36528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
36538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       stcb->asoc.overall_error_count,
36548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       0,
36558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       SCTP_FROM_SCTP_INDATA,
36568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       __LINE__);
36578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.overall_error_count = 0;
36598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(cumack, asoc->last_acked_seq)) {
36608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* process the new consecutive TSN first */
36618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
36628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GE(cumack, tp1->rec.data.TSN_seq)) {
36638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->sent == SCTP_DATAGRAM_UNSENT) {
366447a306d634abf33223ef347472c4b1cd441d139ftuexen					SCTP_PRINTF("Warning, an unsent is now acked?\n");
36658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
36668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->sent < SCTP_DATAGRAM_ACKED) {
36678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
36688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * If it is less than ACKED, it is
36698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * now no-longer in flight. Higher
36708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * values may occur during marking
36718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
36728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (tp1->sent < SCTP_DATAGRAM_RESEND) {
36738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
36748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA,
36758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								       tp1->whoTo->flight_size,
36768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								       tp1->book_size,
36778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								       (uintptr_t)tp1->whoTo,
36788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								       tp1->rec.data.TSN_seq);
36798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
36808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_flight_size_decrease(tp1);
36818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
36828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							(*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo,
36838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen														     tp1);
36848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
36858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* sa_ignore NO_NULL_CHK */
36868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_total_flight_decrease(stcb, tp1);
36878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
36888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->net_ack += tp1->send_size;
36898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (tp1->snd_count < 2) {
36908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*
36918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * True non-retransmited
36928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * chunk
36938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
36948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						tp1->whoTo->net_ack2 +=
36958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							tp1->send_size;
36968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* update RTO too? */
36988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (tp1->do_rtt) {
36998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (rto_ok) {
37008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								tp1->whoTo->RTO =
37018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									/*
37028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * sa_ignore
37038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * NO_NULL_CHK
37048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 */
37058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									sctp_calculate_rto(stcb,
37068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   asoc, tp1->whoTo,
37078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   &tp1->sent_rcv_time,
37088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   sctp_align_safe_nocopy,
37098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   SCTP_RTT_FROM_DATA);
37108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								rto_ok = 0;
37118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
37128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (tp1->whoTo->rto_needed == 0) {
37138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								tp1->whoTo->rto_needed = 1;
37148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
37158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							tp1->do_rtt = 0;
37168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
37178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
37188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
37198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * CMT: CUCv2 algorithm. From the
37208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * cumack'd TSNs, for each TSN being
37218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * acked for the first time, set the
37228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * following variables for the
37238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * corresp destination.
37248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * new_pseudo_cumack will trigger a
37258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * cwnd update.
37268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * find_(rtx_)pseudo_cumack will
37278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * trigger search for the next
37288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * expected (rtx-)pseudo-cumack.
37298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
37308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->new_pseudo_cumack = 1;
37318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->find_pseudo_cumack = 1;
37328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->find_rtx_pseudo_cumack = 1;
37338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
37358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* sa_ignore NO_NULL_CHK */
37368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK);
37378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
37388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
37398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->sent == SCTP_DATAGRAM_RESEND) {
37408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_ucount_decr(asoc->sent_queue_retran_cnt);
37418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
37428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->rec.data.chunk_was_revoked) {
37438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* deflate the cwnd */
37448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->cwnd -= tp1->book_size;
37458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->rec.data.chunk_was_revoked = 0;
37468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
374760db5740d3bcc26fd4ebc19b6b0652506994fd14t				if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
3748446be8e8a472f6e688885674d2430118fc4be5d7t					if (asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) {
3749446be8e8a472f6e688885674d2430118fc4be5d7t						asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--;
3750446be8e8a472f6e688885674d2430118fc4be5d7t#ifdef INVARIANTS
3751446be8e8a472f6e688885674d2430118fc4be5d7t					} else {
3752446be8e8a472f6e688885674d2430118fc4be5d7t						panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number);
3753446be8e8a472f6e688885674d2430118fc4be5d7t#endif
3754446be8e8a472f6e688885674d2430118fc4be5d7t					}
3755446be8e8a472f6e688885674d2430118fc4be5d7t				}
37568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
37578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->data) {
37588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* sa_ignore NO_NULL_CHK */
37598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_free_bufspace(stcb, asoc, tp1, 1);
37608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_m_freem(tp1->data);
37618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->data = NULL;
37628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
37638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
37648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_log_sack(asoc->last_acked_seq,
37658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      cumack,
37668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      tp1->rec.data.TSN_seq,
37678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      0,
37688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      0,
37698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      SCTP_LOG_FREE_SENT);
37708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
37718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->sent_queue_cnt--;
37728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_a_chunk(stcb, tp1, SCTP_SO_NOT_LOCKED);
37738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
37748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
37758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
37768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
37790612043f643c9b26245564c05defca64d472060etuexen#if defined(__Userspace__)
37800ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen	if (stcb->sctp_ep->recv_callback) {
37810ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen		if (stcb->sctp_socket) {
37820ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			uint32_t inqueue_bytes, sb_free_now;
37830ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			struct sctp_inpcb *inp;
37840ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen
37850ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			inp = stcb->sctp_ep;
3786fbf619a4618811e6651f5a78cbacc6530797fd7etuexen			inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
37870ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			sb_free_now = SCTP_SB_LIMIT_SND(stcb->sctp_socket) - (inqueue_bytes + stcb->asoc.sb_send_resv);
37880ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen
37890ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			/* check if the amount free in the send socket buffer crossed the threshold */
37900ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			if (inp->send_callback &&
37910ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			    (((inp->send_sb_threshold > 0) &&
37920ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			      (sb_free_now >= inp->send_sb_threshold) &&
37930ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			      (stcb->asoc.chunks_on_out_queue <= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) ||
37940ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			     (inp->send_sb_threshold == 0))) {
37950ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				atomic_add_int(&stcb->asoc.refcnt, 1);
37960ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				SCTP_TCB_UNLOCK(stcb);
37970ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				inp->send_callback(stcb->sctp_socket, sb_free_now);
37980ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				SCTP_TCB_LOCK(stcb);
37990ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				atomic_subtract_int(&stcb->asoc.refcnt, 1);
38000ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			}
3801fbf619a4618811e6651f5a78cbacc6530797fd7etuexen		}
38020ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen	} else if (stcb->sctp_socket) {
3803fbf619a4618811e6651f5a78cbacc6530797fd7etuexen#else
38048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sa_ignore NO_NULL_CHK */
38058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_socket) {
38060ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#endif
38070612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
38088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct socket *so;
38098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
38118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_LOCK(&stcb->sctp_socket->so_snd);
38128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) {
38138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* sa_ignore NO_NULL_CHK */
38140ac02f34d6041cd0018437596a5a9a94685e6919tuexen			sctp_wakeup_log(stcb, 1, SCTP_WAKESND_FROM_SACK);
38158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38160612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
38178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so = SCTP_INP_SO(stcb->sctp_ep);
38188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
38198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
38208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_LOCK(so, 1);
38218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
38228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
38238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
38248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* assoc was freed while we were unlocked */
38258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_UNLOCK(so, 1);
38268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
38278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
38298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_sowwakeup_locked(stcb->sctp_ep, stcb->sctp_socket);
38300612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
38318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_UNLOCK(so, 1);
38328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
38338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
38348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) {
38350ac02f34d6041cd0018437596a5a9a94685e6919tuexen			sctp_wakeup_log(stcb, 1, SCTP_NOWAKE_FROM_SACK);
38368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
38388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* JRS - Use the congestion control given in the CC module */
38408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((asoc->last_acked_seq != cumack) && (ecne_seen == 0)) {
38418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
38428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->net_ack2 > 0) {
38438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
38448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Karn's rule applies to clearing error count, this
38458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * is optional.
38468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
38478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->error_count = 0;
38488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
38498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* addr came good */
38508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state |= SCTP_ADDR_REACHABLE;
38518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
385247674b651417d493ff4e0318113fd7beeef119dbtuexen					                0, (void *)net, SCTP_SO_NOT_LOCKED);
38538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
38548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net == stcb->asoc.primary_destination) {
38558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (stcb->asoc.alternate) {
38568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* release the alternate, primary is good */
38578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_free_remote_addr(stcb->asoc.alternate);
38588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.alternate = NULL;
38598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
38608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
38618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dest_state & SCTP_ADDR_PF) {
38628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state &= ~SCTP_ADDR_PF;
38638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
38648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
38658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
38668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Done with this net */
38678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->net_ack = 0;
38688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
38698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* restore any doubled timers */
38708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
38718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->RTO < stcb->asoc.minrto) {
38728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->RTO = stcb->asoc.minrto;
38738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
38748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->RTO > stcb->asoc.maxrto) {
38758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->RTO = stcb->asoc.maxrto;
38768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
38778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
38788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, 1, 0, 0);
38808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
38818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->last_acked_seq = cumack;
38828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (TAILQ_EMPTY(&asoc->sent_queue)) {
38848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* nothing left in-flight */
38858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
38868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->flight_size = 0;
38878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->partial_bytes_acked = 0;
38888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->total_flight = 0;
38908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->total_flight_count = 0;
38918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
38928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* RWND update */
38948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->peers_rwnd = sctp_sbspace_sub(rwnd,
38958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh))));
38968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
38978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* SWS sender side engages */
38988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->peers_rwnd = 0;
38998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->peers_rwnd > old_rwnd) {
39018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		win_probe_recovery = 1;
39028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now assure a timer where data is queued at */
39048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenagain:
39058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	j = 0;
39068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
39078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int to_ticks;
39088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (win_probe_recovery && (net->window_probe)) {
39098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			win_probe_recovered = 1;
39108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
39118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Find first chunk that was used with window probe
39128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * and clear the sent
39138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
39148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* sa_ignore FREED_MEMORY */
39158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
39168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->window_probe) {
39178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* move back to data send queue */
39180ac02f34d6041cd0018437596a5a9a94685e6919tuexen					sctp_window_probe_recovery(stcb, asoc, tp1);
39198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
39208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
39218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
39228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
39238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->RTO == 0) {
39248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
39258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
39268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(net->RTO);
39278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
39288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->flight_size) {
39298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			j++;
39308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(void)SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks,
39318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  sctp_timeout_handler, &net->rxt_timer);
39328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->window_probe) {
39338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->window_probe = 0;
39348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
39358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
39368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->window_probe) {
39378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* In window probes we must assure a timer is still running there */
39388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->window_probe = 0;
39398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
39408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_OS_TIMER_START(&net->rxt_timer.timer, to_ticks,
39418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                    sctp_timeout_handler, &net->rxt_timer);
39428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
39438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
39448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
39458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                stcb, net,
39468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                SCTP_FROM_SCTP_INDATA + SCTP_LOC_22);
39478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
39488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
39498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((j == 0) &&
39518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (!TAILQ_EMPTY(&asoc->sent_queue)) &&
39528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (asoc->sent_queue_retran_cnt == 0) &&
39538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (win_probe_recovered == 0) &&
39548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (done_once == 0)) {
39558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* huh, this should not happen unless all packets
39568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * are PR-SCTP and marked to skip of course.
39578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
39588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_fs_audit(asoc)) {
39598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
39608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->flight_size = 0;
39618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
39628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->total_flight = 0;
39638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->total_flight_count = 0;
39648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->sent_queue_retran_cnt = 0;
39658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
39668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->sent < SCTP_DATAGRAM_RESEND) {
39678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_flight_size_increase(tp1);
39688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_total_flight_increase(stcb, tp1);
39698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
39708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_ucount_incr(asoc->sent_queue_retran_cnt);
39718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
39728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
39738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
39748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		done_once = 1;
39758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto again;
39768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/**********************************/
39788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now what about shutdown issues */
39798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/**********************************/
39808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue)) {
39818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* nothing left on sendqueue.. consider done */
39828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* clean up */
39838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((asoc->stream_queue_cnt == 1) &&
39848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
39858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED)) &&
39868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (asoc->locked_on_sending)
39878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			) {
39888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_stream_queue_pending *sp;
39898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* I may be in a state where we got
39908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * all across.. but cannot write more due
39918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * to a shutdown... we abort since the
39928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * user did not indicate EOR in this case. The
39938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * sp will be cleaned during free of the asoc.
39948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
39958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sp = TAILQ_LAST(&((asoc->locked_on_sending)->outqueue),
39968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_streamhead);
39978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((sp) && (sp->length == 0)) {
39988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Let cleanup code purge it */
39998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sp->msg_is_complete) {
40008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->stream_queue_cnt--;
40018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
40028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
40038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->locked_on_sending = NULL;
40048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->stream_queue_cnt--;
40058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
40068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
40078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
40088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) &&
40098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (asoc->stream_queue_cnt == 0)) {
40108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
40118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Need to abort here */
40128f9e45fea288542b24a6bda01269c6fc184d991at				struct mbuf *op_err;
40138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
40148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			abort_out_now:
40158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*abort_now = 1;
40168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* XXX */
40178f9e45fea288542b24a6bda01269c6fc184d991at				op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
40188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
40198f9e45fea288542b24a6bda01269c6fc184d991at				sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
40208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
40218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_nets *netp;
40227988ea8f0c067cf3757e798b473b1ae4d34b6dfdt
40238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
40248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
40258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
40268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
40278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
40288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
40298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stop_timers_for_shutdown(stcb);
40308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (asoc->alternate) {
40318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					netp = asoc->alternate;
40328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
40338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					netp = asoc->primary_destination;
40348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
40358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_send_shutdown(stcb, netp);
40368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
40378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 stcb->sctp_ep, stcb, netp);
40388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
40398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 stcb->sctp_ep, stcb, netp);
40408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
40418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
40428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   (asoc->stream_queue_cnt == 0)) {
40438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_nets *netp;
40447988ea8f0c067cf3757e798b473b1ae4d34b6dfdt
40458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
40468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto abort_out_now;
40478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
40488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_DECR_GAUGE32(sctps_currestab);
40498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
40508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
40518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_stop_timers_for_shutdown(stcb);
40527988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			if (asoc->alternate) {
40537988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				netp = asoc->alternate;
40547988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			} else {
40557988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				netp = asoc->primary_destination;
40567988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			}
40577988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			sctp_send_shutdown_ack(stcb, netp);
40588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK,
40598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 stcb->sctp_ep, stcb, netp);
40608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
40618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*********************************************/
40638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Here we perform PR-SCTP procedures        */
40648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* (section 4.2)                             */
40658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*********************************************/
40668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* C1. update advancedPeerAckPoint */
40678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(cumack, asoc->advanced_peer_ack_point)) {
40688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->advanced_peer_ack_point = cumack;
40698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* PR-Sctp issues need to be addressed too */
4071a8657c4fc04fb9cc82100f648810d51ec6ab155at	if ((asoc->prsctp_supported) && (asoc->pr_sctp_cnt > 0)) {
40728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_tmit_chunk *lchk;
40738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t old_adv_peer_ack_point;
4074000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
40758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		old_adv_peer_ack_point = asoc->advanced_peer_ack_point;
40768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		lchk = sctp_try_advance_peer_ack_point(stcb, asoc);
40778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* C3. See if we need to send a Fwd-TSN */
40788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, cumack)) {
40798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
40808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * ISSUE with ECN, see FWD-TSN processing.
40818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
40828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, old_adv_peer_ack_point)) {
40838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				send_forward_tsn(stcb, asoc);
40848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (lchk) {
40858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* try to FR fwd-tsn's that get lost too */
40868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (lchk->rec.data.fwd_tsn_cnt >= 3) {
40878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					send_forward_tsn(stcb, asoc);
40888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
40898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
40908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
40918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (lchk) {
40928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Assure a timer is up */
40938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_start(SCTP_TIMER_TYPE_SEND,
40948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 stcb->sctp_ep, stcb, lchk->whoTo);
40958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
40968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_RWND_LOGGING_ENABLE) {
40988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_SACK_RWND_UPDATE,
40998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       rwnd,
41008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       stcb->asoc.peers_rwnd,
41018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       stcb->asoc.total_flight,
41028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       stcb->asoc.total_output_queue_size);
41038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
41058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
41078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
41080ac02f34d6041cd0018437596a5a9a94685e6919tuexen                 struct sctp_tcb *stcb,
41098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                 uint16_t num_seg, uint16_t num_nr_seg, uint16_t num_dup,
41108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                 int *abort_now, uint8_t flags,
41118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                 uint32_t cum_ack, uint32_t rwnd, int ecne_seen)
41128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
41138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
41148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *tp1, *tp2;
41158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t last_tsn, biggest_tsn_acked, biggest_tsn_newly_acked, this_sack_lowest_newack;
41168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t wake_him = 0;
41178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t send_s = 0;
41188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	long j;
41198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int accum_moved = 0;
41208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int will_exit_fast_recovery = 0;
41218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t a_rwnd, old_rwnd;
41228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int win_probe_recovery = 0;
41238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int win_probe_recovered = 0;
41248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net = NULL;
41258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int done_once;
4126b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int rto_ok = 1;
41278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t reneged_all = 0;
41288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t cmt_dac_flag;
41298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
41308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * we take any chance we can to service our queues since we cannot
41318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * get awoken when the socket is read from :<
41328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
41338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
41348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now perform the actual SACK handling: 1) Verify that it is not an
41358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * old sack, if so discard. 2) If there is nothing left in the send
41368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * queue (cum-ack is equal to last acked) then you have a duplicate
41378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * too, update any rwnd change and verify no timers are running.
41388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * then return. 3) Process any new consequtive data i.e. cum-ack
41398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * moved process these first and note that it moved. 4) Process any
41408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * sack blocks. 5) Drop any acked from the queue. 6) Check for any
41418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * revoked blocks and mark. 7) Update the cwnd. 8) Nothing left,
41428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * sync up flightsizes and things, stop all timers and also check
41438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * for shutdown_pending state. If so then go ahead and send off the
41448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * shutdown. If in shutdown recv, send off the shutdown-ack and
41458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * start that timer, Ret. 9) Strike any non-acked things and do FR
41468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * procedure if needed being sure to set the FR flag. 10) Do pr-sctp
41478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * procedures. 11) Apply any FR penalties. 12) Assure we will SACK
41488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * if in shutdown_recv state.
41498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
41508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_LOCK_ASSERT(stcb);
41518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* CMT DAC algo */
41528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	this_sack_lowest_newack = 0;
41538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_STAT_INCR(sctps_slowpath_sack);
41548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	last_tsn = cum_ack;
41558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cmt_dac_flag = flags & SCTP_SACK_CMT_DAC;
41568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS
41578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.cumack_log[stcb->asoc.cumack_log_at] = cum_ack;
41588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.cumack_log_at++;
41598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.cumack_log_at > SCTP_TSN_LOG_SIZE) {
41608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.cumack_log_at = 0;
41618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
41638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	a_rwnd = rwnd;
41648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_SACK_ARRIVALS_ENABLE) {
41668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_SACK_LOG_NORMAL, cum_ack,
41678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		               rwnd, stcb->asoc.last_acked_seq, stcb->asoc.peers_rwnd);
41688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	old_rwnd = stcb->asoc.peers_rwnd;
41718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
41728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
41738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		               stcb->asoc.overall_error_count,
41748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		               0,
41758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		               SCTP_FROM_SCTP_INDATA,
41768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		               __LINE__);
41778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.overall_error_count = 0;
41798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
41808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
41818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_sack(asoc->last_acked_seq,
41828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		              cum_ack,
41838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		              0,
41848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		              num_seg,
41858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		              num_dup,
41868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		              SCTP_LOG_NEW_SACK);
41878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((num_dup) && (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE)) {
41898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint16_t i;
41908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *dupdata, dblock;
41918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < num_dup; i++) {
41938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			dupdata = (uint32_t *)sctp_m_getptr(m, offset_dup + i * sizeof(uint32_t),
41948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                                    sizeof(uint32_t), (uint8_t *)&dblock);
41958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (dupdata == NULL) {
41968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
41978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
41988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_fr(*dupdata, 0, 0, SCTP_FR_DUPED);
41998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
42018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) {
42028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* reality check */
42038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!TAILQ_EMPTY(&asoc->sent_queue)) {
42048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1 = TAILQ_LAST(&asoc->sent_queue,
42058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                 sctpchunk_listhead);
42068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			send_s = tp1->rec.data.TSN_seq + 1;
42078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
42088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1 = NULL;
42098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			send_s = asoc->sending_seq;
42108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GE(cum_ack, send_s)) {
42128f9e45fea288542b24a6bda01269c6fc184d991at			struct mbuf *op_err;
42138f9e45fea288542b24a6bda01269c6fc184d991at			char msg[SCTP_DIAG_INFO_LEN];
42148f9e45fea288542b24a6bda01269c6fc184d991at
42158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
42168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * no way, we have not even sent this TSN out yet.
42178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Peer is hopelessly messed up with us.
42188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
421947a306d634abf33223ef347472c4b1cd441d139ftuexen			SCTP_PRINTF("NEW cum_ack:%x send_s:%x is smaller or equal\n",
422047a306d634abf33223ef347472c4b1cd441d139ftuexen			            cum_ack, send_s);
42218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1) {
422247a306d634abf33223ef347472c4b1cd441d139ftuexen				SCTP_PRINTF("Got send_s from tsn:%x + 1 of tp1:%p\n",
4223ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t				            tp1->rec.data.TSN_seq, (void *)tp1);
42248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
42258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hopeless_peer:
42268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*abort_now = 1;
42278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* XXX */
42288f9e45fea288542b24a6bda01269c6fc184d991at			snprintf(msg, sizeof(msg), "Cum ack %8.8x greater or equal then TSN %8.8x",
42298f9e45fea288542b24a6bda01269c6fc184d991at			         cum_ack, send_s);
42308f9e45fea288542b24a6bda01269c6fc184d991at			op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
42318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_25;
42328f9e45fea288542b24a6bda01269c6fc184d991at			sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
42338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
42348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
42368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/**********************/
42378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* 1) check the range */
42388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/**********************/
42398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(asoc->last_acked_seq, last_tsn)) {
42408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* acking something behind */
42418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
42428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
42438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
42448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* update the Rwnd of the peer */
42458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (TAILQ_EMPTY(&asoc->sent_queue) &&
42468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    TAILQ_EMPTY(&asoc->send_queue) &&
42478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (asoc->stream_queue_cnt == 0)) {
42488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* nothing left on send/sent and strmq */
42498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) {
42508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_rwnd_set(SCTP_SET_PEER_RWND_VIA_SACK,
42518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                  asoc->peers_rwnd, 0, 0, a_rwnd);
42528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->peers_rwnd = a_rwnd;
42548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->sent_queue_retran_cnt) {
42558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->sent_queue_retran_cnt = 0;
42568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
42588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* SWS sender side engages */
42598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->peers_rwnd = 0;
42608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* stop any timers */
42628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
42638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
42648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_26);
42658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->partial_bytes_acked = 0;
42668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->flight_size = 0;
42678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->total_flight = 0;
42698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->total_flight_count = 0;
42708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
42718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
42728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
42738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * We init netAckSz and netAckSz2 to 0. These are used to track 2
42748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * things. The total byte count acked is tracked in netAckSz AND
42758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * netAck2 is used to track the total bytes acked that are un-
42768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * amibguious and were never retransmitted. We track these on a per
42778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * destination address basis.
42788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
42798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
42808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(cum_ack, net->cwr_window_tsn)) {
42818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Drag along the window_tsn for cwr's */
42828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->cwr_window_tsn = cum_ack;
42838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->prev_cwnd = net->cwnd;
42858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->net_ack = 0;
42868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->net_ack2 = 0;
42878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
42888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
42898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT: Reset CUC and Fast recovery algo variables before
42908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * SACK processing
42918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
42928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->new_pseudo_cumack = 0;
42938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->will_exit_fast_recovery = 0;
42948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack) {
42958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(*stcb->asoc.cc_functions.sctp_cwnd_prepare_net_for_sack)(stcb, net);
42968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
42988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* process the new consecutive TSN first */
42998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
43008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GE(last_tsn, tp1->rec.data.TSN_seq)) {
43018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
43028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				accum_moved = 1;
43038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->sent < SCTP_DATAGRAM_ACKED) {
43048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
43058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * If it is less than ACKED, it is
43068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * now no-longer in flight. Higher
43078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * values may occur during marking
43088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
43098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((tp1->whoTo->dest_state &
43108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     SCTP_ADDR_UNCONFIRMED) &&
43118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (tp1->snd_count < 2)) {
43128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*
43138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * If there was no retran
43148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * and the address is
43158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * un-confirmed and we sent
43168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * there and are now
43178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * sacked.. its confirmed,
43188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * mark it so.
43198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
43208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						tp1->whoTo->dest_state &=
43218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							~SCTP_ADDR_UNCONFIRMED;
43228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
43238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (tp1->sent < SCTP_DATAGRAM_RESEND) {
43248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
43258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA,
43268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							               tp1->whoTo->flight_size,
43278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							               tp1->book_size,
43288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							               (uintptr_t)tp1->whoTo,
43298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							               tp1->rec.data.TSN_seq);
43308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
43318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_flight_size_decrease(tp1);
43328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_total_flight_decrease(stcb, tp1);
43338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged) {
43348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							(*stcb->asoc.cc_functions.sctp_cwnd_update_tsn_acknowledged)(tp1->whoTo,
43358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen														     tp1);
43368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
43378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
43388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->net_ack += tp1->send_size;
43398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* CMT SFR and DAC algos */
43418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					this_sack_lowest_newack = tp1->rec.data.TSN_seq;
43428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->saw_newack = 1;
43438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (tp1->snd_count < 2) {
43458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*
43468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * True non-retransmited
43478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * chunk
43488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
43498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						tp1->whoTo->net_ack2 +=
43508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							tp1->send_size;
43518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* update RTO too? */
43538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (tp1->do_rtt) {
43548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (rto_ok) {
43558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								tp1->whoTo->RTO =
43568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									sctp_calculate_rto(stcb,
43578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   asoc, tp1->whoTo,
43588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   &tp1->sent_rcv_time,
43598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   sctp_align_safe_nocopy,
43608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   SCTP_RTT_FROM_DATA);
43618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								rto_ok = 0;
43628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
43638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (tp1->whoTo->rto_needed == 0) {
43648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								tp1->whoTo->rto_needed = 1;
43658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
43668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							tp1->do_rtt = 0;
43678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
43688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
43698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
43708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * CMT: CUCv2 algorithm. From the
43718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * cumack'd TSNs, for each TSN being
43728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * acked for the first time, set the
43738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * following variables for the
43748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * corresp destination.
43758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * new_pseudo_cumack will trigger a
43768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * cwnd update.
43778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * find_(rtx_)pseudo_cumack will
43788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * trigger search for the next
43798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * expected (rtx-)pseudo-cumack.
43808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
43818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->new_pseudo_cumack = 1;
43828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->find_pseudo_cumack = 1;
43838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->find_rtx_pseudo_cumack = 1;
43848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
43878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_sack(asoc->last_acked_seq,
43888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						              cum_ack,
43898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						              tp1->rec.data.TSN_seq,
43908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						              0,
43918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						              0,
43928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						              SCTP_LOG_TSN_ACKED);
43938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
43948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
43958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_log_cwnd(stcb, tp1->whoTo, tp1->rec.data.TSN_seq, SCTP_CWND_LOG_FROM_SACK);
43968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
43978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
43988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->sent == SCTP_DATAGRAM_RESEND) {
43998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_ucount_decr(asoc->sent_queue_retran_cnt);
44008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
44018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_audit_log(0xB3,
44028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					               (asoc->sent_queue_retran_cnt & 0x000000ff));
44038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
44048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
44058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->rec.data.chunk_was_revoked) {
44068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* deflate the cwnd */
44078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->whoTo->cwnd -= tp1->book_size;
44088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tp1->rec.data.chunk_was_revoked = 0;
44098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
441060db5740d3bcc26fd4ebc19b6b0652506994fd14t				if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
441160db5740d3bcc26fd4ebc19b6b0652506994fd14t					tp1->sent = SCTP_DATAGRAM_ACKED;
441260db5740d3bcc26fd4ebc19b6b0652506994fd14t				}
44138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
44148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
44158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
44168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	biggest_tsn_newly_acked = biggest_tsn_acked = last_tsn;
44198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* always set this up to cum-ack */
44208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->this_sack_highest_gap = last_tsn;
44218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((num_seg > 0) || (num_nr_seg > 0)) {
44238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
44258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * CMT: SFR algo (and HTNA) - this_sack_highest_newack has
44268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * to be greater than the cumack. Also reset saw_newack to 0
44278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * for all dests.
44288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
44298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
44308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->saw_newack = 0;
44318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->this_sack_highest_newack = last_tsn;
44328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
44358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * thisSackHighestGap will increase while handling NEW
44368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * segments this_sack_highest_newack will increase while
44378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * handling NEWLY ACKED chunks. this_sack_lowest_newack is
44388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * used for CMT DAC algo. saw_newack will also change.
44398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
44408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_handle_segments(m, &offset_seg, stcb, asoc, last_tsn, &biggest_tsn_acked,
44418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			&biggest_tsn_newly_acked, &this_sack_lowest_newack,
44420ac02f34d6041cd0018437596a5a9a94685e6919tuexen			num_seg, num_nr_seg, &rto_ok)) {
44438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			wake_him++;
44448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_strict_sacks)) {
44468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
44478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * validate the biggest_tsn_acked in the gap acks if
44488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * strict adherence is wanted.
44498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
44508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GE(biggest_tsn_acked, send_s)) {
44518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
44528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * peer is either confused or we are under
44538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * attack. We must abort.
44548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
445547a306d634abf33223ef347472c4b1cd441d139ftuexen				SCTP_PRINTF("Hopeless peer! biggest_tsn_acked:%x largest seq:%x\n",
445647a306d634abf33223ef347472c4b1cd441d139ftuexen				            biggest_tsn_acked, send_s);
44578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto hopeless_peer;
44588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
44598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*******************************************/
44628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* cancel ALL T3-send timer if accum moved */
44638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*******************************************/
44648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->sctp_cmt_on_off > 0) {
44658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
44668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->new_pseudo_cumack)
44678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
44688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                stcb, net,
44698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                SCTP_FROM_SCTP_INDATA + SCTP_LOC_27);
44708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
44738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (accum_moved) {
44748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
44758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
44768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_28);
44778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
44788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/********************************************/
44818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* drop the acked chunks from the sentqueue */
44828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/********************************************/
44838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->last_acked_seq = cum_ack;
44848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(tp1, &asoc->sent_queue, sctp_next, tp2) {
44868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, cum_ack)) {
44878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
44888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
448960db5740d3bcc26fd4ebc19b6b0652506994fd14t		if (tp1->sent != SCTP_DATAGRAM_NR_ACKED) {
4490446be8e8a472f6e688885674d2430118fc4be5d7t			if (asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues > 0) {
4491446be8e8a472f6e688885674d2430118fc4be5d7t				asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues--;
4492446be8e8a472f6e688885674d2430118fc4be5d7t#ifdef INVARIANTS
4493446be8e8a472f6e688885674d2430118fc4be5d7t			} else {
4494446be8e8a472f6e688885674d2430118fc4be5d7t				panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number);
4495446be8e8a472f6e688885674d2430118fc4be5d7t#endif
4496446be8e8a472f6e688885674d2430118fc4be5d7t			}
44978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
449937a477684cd9fd2f02430cc2a9822c8c160973ect		if (PR_SCTP_ENABLED(tp1->flags)) {
45008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->pr_sctp_cnt != 0)
45018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->pr_sctp_cnt--;
45028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->sent_queue_cnt--;
45048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tp1->data) {
45058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* sa_ignore NO_NULL_CHK */
45068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_bufspace(stcb, asoc, tp1, 1);
45078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(tp1->data);
45088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1->data = NULL;
4509a8657c4fc04fb9cc82100f648810d51ec6ab155at			if (asoc->prsctp_supported && PR_SCTP_BUF_ENABLED(tp1->flags)) {
45108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->sent_queue_cnt_removeable--;
45118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_LOGGING_ENABLE) {
45148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_sack(asoc->last_acked_seq,
45158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			              cum_ack,
45168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			              tp1->rec.data.TSN_seq,
45178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			              0,
45188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			              0,
45198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			              SCTP_LOG_FREE_SENT);
45208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_a_chunk(stcb, tp1, SCTP_SO_NOT_LOCKED);
45228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		wake_him++;
45238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (TAILQ_EMPTY(&asoc->sent_queue) && (asoc->total_flight > 0)) {
45258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
45268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		panic("Warning flight size is postive and should be 0");
45278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
45288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("Warning flight size incorrect should be 0 is %d\n",
45298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		            asoc->total_flight);
45308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->total_flight = 0;
45328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
45340ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#if defined(__Userspace__)
45350ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen	if (stcb->sctp_ep->recv_callback) {
45360ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen		if (stcb->sctp_socket) {
45370ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			uint32_t inqueue_bytes, sb_free_now;
45380ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			struct sctp_inpcb *inp;
45390ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen
45400ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			inp = stcb->sctp_ep;
4541fbf619a4618811e6651f5a78cbacc6530797fd7etuexen			inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
4542283ff606e8e0d3d1880be501ae236653224cfa25tuexen			sb_free_now = SCTP_SB_LIMIT_SND(stcb->sctp_socket) - (inqueue_bytes + stcb->asoc.sb_send_resv);
45430ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen
45440ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			/* check if the amount free in the send socket buffer crossed the threshold */
45450ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			if (inp->send_callback &&
45460ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			   (((inp->send_sb_threshold > 0) && (sb_free_now >= inp->send_sb_threshold)) ||
45470ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			    (inp->send_sb_threshold == 0))) {
45480ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				atomic_add_int(&stcb->asoc.refcnt, 1);
45490ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				SCTP_TCB_UNLOCK(stcb);
45500ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				inp->send_callback(stcb->sctp_socket, sb_free_now);
45510ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				SCTP_TCB_LOCK(stcb);
45520ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				atomic_subtract_int(&stcb->asoc.refcnt, 1);
45530ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			}
4554fbf619a4618811e6651f5a78cbacc6530797fd7etuexen		}
45550ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen	} else if ((wake_him) && (stcb->sctp_socket)) {
4556fbf619a4618811e6651f5a78cbacc6530797fd7etuexen#else
45578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sa_ignore NO_NULL_CHK */
45588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((wake_him) && (stcb->sctp_socket)) {
45590ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#endif
45600612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
45618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct socket *so;
45628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
45638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_LOCK(&stcb->sctp_socket->so_snd);
45658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) {
45660ac02f34d6041cd0018437596a5a9a94685e6919tuexen			sctp_wakeup_log(stcb, wake_him, SCTP_WAKESND_FROM_SACK);
45678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45680612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
45698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so = SCTP_INP_SO(stcb->sctp_ep);
45708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
45718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
45728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_LOCK(so, 1);
45738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
45748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
45758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
45768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* assoc was freed while we were unlocked */
45778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_UNLOCK(so, 1);
45788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
45798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_sowwakeup_locked(stcb->sctp_ep, stcb->sctp_socket);
45820612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
45838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_UNLOCK(so, 1);
45848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
45868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_WAKE_LOGGING_ENABLE) {
45870ac02f34d6041cd0018437596a5a9a94685e6919tuexen			sctp_wakeup_log(stcb, wake_him, SCTP_NOWAKE_FROM_SACK);
45888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
45918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->fast_retran_loss_recovery && accum_moved) {
45928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GE(asoc->last_acked_seq, asoc->fast_recovery_tsn)) {
45938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Setup so we will exit RFC2582 fast recovery */
45948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			will_exit_fast_recovery = 1;
45958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
45988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Check for revoked fragments:
45998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
46008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * if Previous sack - Had no frags then we can't have any revoked if
46018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Previous sack - Had frag's then - If we now have frags aka
46028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * num_seg > 0 call sctp_check_for_revoked() to tell if peer revoked
46038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * some of them. else - The peer revoked all ACKED fragments, since
46048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * we had some before and now we have NONE.
46058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
46068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (num_seg) {
46088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_check_for_revoked(stcb, asoc, cum_ack, biggest_tsn_acked);
46098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->saw_sack_with_frags = 1;
46108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (asoc->saw_sack_with_frags) {
46118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int cnt_revoked = 0;
46128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Peer revoked all dg's marked or acked */
46148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
46158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->sent == SCTP_DATAGRAM_ACKED) {
46168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->sent = SCTP_DATAGRAM_SENT;
46178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
46188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
46198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					               tp1->whoTo->flight_size,
46208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					               tp1->book_size,
46218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					               (uintptr_t)tp1->whoTo,
46228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					               tp1->rec.data.TSN_seq);
46238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_flight_size_increase(tp1);
46258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_total_flight_increase(stcb, tp1);
46268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->rec.data.chunk_was_revoked = 1;
46278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
46288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * To ensure that this increase in
46298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * flightsize, which is artificial,
46308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * does not throttle the sender, we
46318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * also increase the cwnd
46328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * artificially.
46338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
46348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->whoTo->cwnd += tp1->book_size;
46358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cnt_revoked++;
46368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (cnt_revoked) {
46398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			reneged_all = 1;
46408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->saw_sack_with_frags = 0;
46428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (num_nr_seg > 0)
46448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->saw_sack_with_nr_frags = 1;
46458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
46468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->saw_sack_with_nr_frags = 0;
46478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* JRS - Use the congestion control given in the CC module */
46498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ecne_seen == 0) {
46508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
46518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->net_ack2 > 0) {
46528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
46538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * Karn's rule applies to clearing error count, this
46548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * is optional.
46558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
46568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->error_count = 0;
46578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
46588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* addr came good */
46598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state |= SCTP_ADDR_REACHABLE;
46608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
466147674b651417d493ff4e0318113fd7beeef119dbtuexen					                0, (void *)net, SCTP_SO_NOT_LOCKED);
46628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net == stcb->asoc.primary_destination) {
46658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (stcb->asoc.alternate) {
46668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* release the alternate, primary is good */
46678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_free_remote_addr(stcb->asoc.alternate);
46688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.alternate = NULL;
46698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
46708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dest_state & SCTP_ADDR_PF) {
46738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state &= ~SCTP_ADDR_PF;
46748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
46758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
46768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
46778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Done with this net */
46788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->net_ack = 0;
46798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* restore any doubled timers */
46818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
46828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->RTO < stcb->asoc.minrto) {
46838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->RTO = stcb->asoc.minrto;
46848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->RTO > stcb->asoc.maxrto) {
46868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->RTO = stcb->asoc.maxrto;
46878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery);
46918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (TAILQ_EMPTY(&asoc->sent_queue)) {
46948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* nothing left in-flight */
46958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
46968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* stop all timers */
46978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
46988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_30);
46998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->flight_size = 0;
47008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->partial_bytes_acked = 0;
47018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->total_flight = 0;
47038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->total_flight_count = 0;
47048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
47058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
47068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/**********************************/
47078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now what about shutdown issues */
47088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/**********************************/
47098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (TAILQ_EMPTY(&asoc->send_queue) && TAILQ_EMPTY(&asoc->sent_queue)) {
47108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* nothing left on sendqueue.. consider done */
47118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) {
47128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_rwnd_set(SCTP_SET_PEER_RWND_VIA_SACK,
47138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                  asoc->peers_rwnd, 0, 0, a_rwnd);
47148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->peers_rwnd = a_rwnd;
47168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
47178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* SWS sender side engages */
47188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->peers_rwnd = 0;
47198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* clean up */
47218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((asoc->stream_queue_cnt == 1) &&
47228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
47238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED)) &&
47248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (asoc->locked_on_sending)
47258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			) {
47268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_stream_queue_pending *sp;
47278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* I may be in a state where we got
47288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * all across.. but cannot write more due
47298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * to a shutdown... we abort since the
47308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * user did not indicate EOR in this case.
47318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
47328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sp = TAILQ_LAST(&((asoc->locked_on_sending)->outqueue),
47338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                sctp_streamhead);
47348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((sp) && (sp->length == 0)) {
47358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->locked_on_sending = NULL;
47368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sp->msg_is_complete) {
47378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->stream_queue_cnt--;
47388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
47398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
47408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->stream_queue_cnt--;
47418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
47428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) &&
47458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (asoc->stream_queue_cnt == 0)) {
47468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
47478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Need to abort here */
47488f9e45fea288542b24a6bda01269c6fc184d991at				struct mbuf *op_err;
47498f9e45fea288542b24a6bda01269c6fc184d991at
47508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			abort_out_now:
47518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*abort_now = 1;
47528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* XXX */
47538f9e45fea288542b24a6bda01269c6fc184d991at				op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
47548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_31;
47558f9e45fea288542b24a6bda01269c6fc184d991at				sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
47568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
47578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
47588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_nets *netp;
47597988ea8f0c067cf3757e798b473b1ae4d34b6dfdt
47608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
47618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
47628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
47638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
47648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
47658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
47668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stop_timers_for_shutdown(stcb);
47677988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				if (asoc->alternate) {
47687988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					netp = asoc->alternate;
47697988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				} else {
47707988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					netp = asoc->primary_destination;
47717988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				}
47728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_send_shutdown(stcb, netp);
47738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
47748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                 stcb->sctp_ep, stcb, netp);
47758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
47768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                 stcb->sctp_ep, stcb, netp);
47778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
47798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
47808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   (asoc->stream_queue_cnt == 0)) {
47818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_nets *netp;
47827988ea8f0c067cf3757e798b473b1ae4d34b6dfdt
47838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
47848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto abort_out_now;
47858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_DECR_GAUGE32(sctps_currestab);
47878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
47888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
47898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_stop_timers_for_shutdown(stcb);
47907988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			if (asoc->alternate) {
47917988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				netp = asoc->alternate;
47927988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			} else {
47937988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				netp = asoc->primary_destination;
47947988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			}
47957988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			sctp_send_shutdown_ack(stcb, netp);
47968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK,
47978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                 stcb->sctp_ep, stcb, netp);
47988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
47998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
48028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now here we are going to recycle net_ack for a different use...
48038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * HEADS UP.
48048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
48058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
48068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->net_ack = 0;
48078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
48108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * CMT DAC algorithm: If SACK DAC flag was 0, then no extra marking
48118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * to be done. Setting this_sack_lowest_newack to the cum_ack will
48128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * automatically ensure that.
48138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
48148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((asoc->sctp_cmt_on_off > 0) &&
48158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_BASE_SYSCTL(sctp_cmt_use_dac) &&
48168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (cmt_dac_flag == 0)) {
48178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		this_sack_lowest_newack = cum_ack;
48188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((num_seg > 0) || (num_nr_seg > 0)) {
48208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_strike_gap_ack_chunks(stcb, asoc, biggest_tsn_acked,
48218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                           biggest_tsn_newly_acked, this_sack_lowest_newack, accum_moved);
48228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* JRS - Use the congestion control given in the CC module */
48248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->cc_functions.sctp_cwnd_update_after_fr(stcb, asoc);
48258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now are we exiting loss recovery ? */
48278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (will_exit_fast_recovery) {
48288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Ok, we must exit fast recovery */
48298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->fast_retran_loss_recovery = 0;
48308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((asoc->sat_t3_loss_recovery) &&
48328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_TSN_GE(asoc->last_acked_seq, asoc->sat_t3_recovery_tsn)) {
48338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* end satellite t3 loss recovery */
48348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->sat_t3_loss_recovery = 0;
48358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
48378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * CMT Fast recovery
48388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
48398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
48408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->will_exit_fast_recovery) {
48418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Ok, we must exit fast recovery */
48428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->fast_retran_loss_recovery = 0;
48438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Adjust and set the new rwnd value */
48478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_RWND_ENABLE) {
48488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_rwnd_set(SCTP_SET_PEER_RWND_VIA_SACK,
48498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                  asoc->peers_rwnd, asoc->total_flight, (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh)), a_rwnd);
48508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->peers_rwnd = sctp_sbspace_sub(a_rwnd,
48528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                                    (uint32_t) (asoc->total_flight + (asoc->total_flight_count * SCTP_BASE_SYSCTL(sctp_peer_chunk_oh))));
48538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->peers_rwnd < stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
48548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* SWS sender side engages */
48558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->peers_rwnd = 0;
48568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->peers_rwnd > old_rwnd) {
48588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		win_probe_recovery = 1;
48598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
48628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now we must setup so we have a timer up for anyone with
48638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * outstanding data.
48648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
48658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	done_once = 0;
48668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenagain:
48678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	j = 0;
48688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
48698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (win_probe_recovery && (net->window_probe)) {
48708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			win_probe_recovered = 1;
48718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*-
48728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Find first chunk that was used with
48738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * window probe and clear the event. Put
48748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * it back into the send queue as if has
48758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * not been sent.
48768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
48778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
48788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->window_probe) {
48790ac02f34d6041cd0018437596a5a9a94685e6919tuexen					sctp_window_probe_recovery(stcb, asoc, tp1);
48808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
48818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
48828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->flight_size) {
48858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			j++;
48868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
48878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SEND,
48888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                 stcb->sctp_ep, stcb, net);
48898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->window_probe) {
48918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->window_probe = 0;
48928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
48948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->window_probe) {
48958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* In window probes we must assure a timer is still running there */
48968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
48978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_SEND,
48988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                 stcb->sctp_ep, stcb, net);
48998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
49008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
49018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
49028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
49038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                stcb, net,
49048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                SCTP_FROM_SCTP_INDATA + SCTP_LOC_22);
49058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
49088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((j == 0) &&
49098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (!TAILQ_EMPTY(&asoc->sent_queue)) &&
49108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (asoc->sent_queue_retran_cnt == 0) &&
49118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (win_probe_recovered == 0) &&
49128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (done_once == 0)) {
49138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* huh, this should not happen unless all packets
49148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * are PR-SCTP and marked to skip of course.
49158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
49168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_fs_audit(asoc)) {
49178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
49188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->flight_size = 0;
49198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->total_flight = 0;
49218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->total_flight_count = 0;
49228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->sent_queue_retran_cnt = 0;
49238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
49248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tp1->sent < SCTP_DATAGRAM_RESEND) {
49258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_flight_size_increase(tp1);
49268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_total_flight_increase(stcb, tp1);
49278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
49288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_ucount_incr(asoc->sent_queue_retran_cnt);
49298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
49308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		done_once = 1;
49338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto again;
49348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
49358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*********************************************/
49368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Here we perform PR-SCTP procedures        */
49378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* (section 4.2)                             */
49388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*********************************************/
49398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* C1. update advancedPeerAckPoint */
49408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GT(cum_ack, asoc->advanced_peer_ack_point)) {
49418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->advanced_peer_ack_point = cum_ack;
49428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
49438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* C2. try to further move advancedPeerAckPoint ahead */
4944a8657c4fc04fb9cc82100f648810d51ec6ab155at	if ((asoc->prsctp_supported) && (asoc->pr_sctp_cnt > 0)) {
49458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_tmit_chunk *lchk;
49468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t old_adv_peer_ack_point;
4947000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
49488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		old_adv_peer_ack_point = asoc->advanced_peer_ack_point;
49498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		lchk = sctp_try_advance_peer_ack_point(stcb, asoc);
49508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* C3. See if we need to send a Fwd-TSN */
49518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, cum_ack)) {
49528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
49538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * ISSUE with ECN, see FWD-TSN processing.
49548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
49558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
49568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_misc_ints(SCTP_FWD_TSN_CHECK,
49578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				               0xee, cum_ack, asoc->advanced_peer_ack_point,
49588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				               old_adv_peer_ack_point);
49598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GT(asoc->advanced_peer_ack_point, old_adv_peer_ack_point)) {
49618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				send_forward_tsn(stcb, asoc);
49628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (lchk) {
49638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* try to FR fwd-tsn's that get lost too */
49648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (lchk->rec.data.fwd_tsn_cnt >= 3) {
49658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					send_forward_tsn(stcb, asoc);
49668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
49678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (lchk) {
49708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Assure a timer is up */
49718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_start(SCTP_TIMER_TYPE_SEND,
49728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                 stcb->sctp_ep, stcb, lchk->whoTo);
49738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
49758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SACK_RWND_LOGGING_ENABLE) {
49768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_SACK_RWND_UPDATE,
49778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		               a_rwnd,
49788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		               stcb->asoc.peers_rwnd,
49798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		               stcb->asoc.total_flight,
49808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		               stcb->asoc.total_output_queue_size);
49818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
49828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
49838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
49848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
49850ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_update_acked(struct sctp_tcb *stcb, struct sctp_shutdown_chunk *cp, int *abort_flag)
49868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
49878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Copy cum-ack */
49888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t cum_ack, a_rwnd;
49898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
49908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cum_ack = ntohl(cp->cumulative_tsn_ack);
49918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Arrange so a_rwnd does NOT change */
49928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	a_rwnd = stcb->asoc.peers_rwnd + stcb->asoc.total_flight;
49938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
49948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now call the express sack handling */
49958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_express_handle_sack(stcb, cum_ack, a_rwnd, abort_flag, 0);
49968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
49978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
49988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
49998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
50008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_stream_in *strmin)
50018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
50028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *ctl, *nctl;
50038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
50048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t tt;
5005000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
50068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
50078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tt = strmin->last_sequence_delivered;
50088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
50098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * First deliver anything prior to and including the stream no that
50108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * came in
50118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
50128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next, nctl) {
50138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_SSN_GE(tt, ctl->sinfo_ssn)) {
50148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* this is deliverable now */
50158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&strmin->inqueue, ctl, next);
50168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* subtract pending on streams */
50178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->size_on_all_streams -= ctl->length;
50188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ucount_decr(asoc->cnt_on_all_streams);
50198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* deliver it to at least the delivery-q */
50208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->sctp_socket) {
50218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
50228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_add_to_readq(stcb->sctp_ep, stcb,
50238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  ctl,
50248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED);
50258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
50268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
50278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no more delivery now. */
50288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
50298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
50308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
50318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
50328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * now we must deliver things in queue the normal way  if any are
50338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * now ready.
50348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
50358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tt = strmin->last_sequence_delivered + 1;
50368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(ctl, &strmin->inqueue, next, nctl) {
50378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tt == ctl->sinfo_ssn) {
50388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* this is deliverable now */
50398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&strmin->inqueue, ctl, next);
50408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* subtract pending on streams */
50418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->size_on_all_streams -= ctl->length;
50428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ucount_decr(asoc->cnt_on_all_streams);
50438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* deliver it to at least the delivery-q */
50448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			strmin->last_sequence_delivered = ctl->sinfo_ssn;
50458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->sctp_socket) {
50468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_mark_non_revokable(asoc, ctl->sinfo_tsn);
50478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_add_to_readq(stcb->sctp_ep, stcb,
50488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  ctl,
50498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_HELD, SCTP_SO_NOT_LOCKED);
50508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
50528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tt = strmin->last_sequence_delivered + 1;
50538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
50548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
50558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
50568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
50578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
50588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
50608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
50618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc,
50628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t stream, uint16_t seq)
50638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
50648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk, *nchk;
50658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* For each one on here see if we need to toss it */
50678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
50688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * For now large messages held on the reasmqueue that are
50698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * complete will be tossed too. We could in theory do more
50708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * work to spin through and stop after dumping one msg aka
50718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * seeing the start of a new msg at the head, and call the
50728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * delivery function... to see if it can be delivered... But
50738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * for now we just dump everything on the queue.
50748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
50758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
50768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Do not toss it if on a different stream or
50778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * marked for unordered delivery in which case
50788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the stream sequence number has no meaning.
50798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
50808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((chk->rec.data.stream_number != stream) ||
50818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED)) {
50828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
50838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
50848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->rec.data.stream_seq == seq) {
50858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* It needs to be tossed */
50868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
50878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GT(chk->rec.data.TSN_seq, asoc->tsn_last_delivered)) {
50888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->tsn_last_delivered = chk->rec.data.TSN_seq;
50898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->str_of_pdapi = chk->rec.data.stream_number;
50908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->ssn_of_pdapi = chk->rec.data.stream_seq;
50918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->fragment_flags = chk->rec.data.rcv_flags;
50928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
50938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->size_on_reasm_queue -= chk->send_size;
50948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ucount_decr(asoc->cnt_on_reasm_queue);
50958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Clear up any stream problem */
50978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) != SCTP_DATA_UNORDERED &&
50988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_SSN_GT(chk->rec.data.stream_seq, asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered)) {
50998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
51008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * We must dump forward this streams
51018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * sequence number if the chunk is
51028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * not unordered that is being
51038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * skipped. There is a chance that
51048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * if the peer does not include the
51058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * last fragment in its FWD-TSN we
51068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * WILL have a problem here since
51078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * you would have a partial chunk in
51088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * queue that may not be
51098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * deliverable. Also if a Partial
51108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * delivery API as started the user
51118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * may get a partial chunk. The next
51128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * read returning a new chunk...
51138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * really ugly but I see no way
51148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * around it! Maybe a notify??
51158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
51168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered = chk->rec.data.stream_seq;
51178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->data) {
51198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(chk->data);
51208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				chk->data = NULL;
51218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
51238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (SCTP_SSN_GT(chk->rec.data.stream_seq, seq)) {
51248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* If the stream_seq is > than the purging one, we are done */
51258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
51268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
51298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
51328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_forward_tsn(struct sctp_tcb *stcb,
51338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                        struct sctp_forward_tsn_chunk *fwd,
51348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                        int *abort_flag, struct mbuf *m ,int offset)
51358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
51368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* The pr-sctp fwd tsn */
51378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
51388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * here we will perform all the data receiver side steps for
51398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * processing FwdTSN, as required in by pr-sctp draft:
51408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
51418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Assume we get FwdTSN(x):
51428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
51438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * 1) update local cumTSN to x 2) try to further advance cumTSN to x +
51448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * others we have 3) examine and update re-ordering queue on
51458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * pr-in-streams 4) clean up re-assembly queue 5) Send a sack to
51468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * report where we are.
51478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
51488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
51498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t new_cum_tsn, gap;
51500ac02f34d6041cd0018437596a5a9a94685e6919tuexen	unsigned int i, fwd_sz, m_size;
51518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t str_seq;
51528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_stream_in *strm;
51538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk, *nchk;
51548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *ctl, *sv;
51558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
51578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((fwd_sz = ntohs(fwd->ch.chunk_length)) < sizeof(struct sctp_forward_tsn_chunk)) {
51588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_INDATA1,
51598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"Bad size too small/big fwd-tsn\n");
51608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
51618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m_size = (stcb->asoc.mapping_array_size << 3);
51638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*************************************************************/
51648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* 1. Here we update local cumTSN and shift the bitmap array */
51658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*************************************************************/
51668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_cum_tsn = ntohl(fwd->new_cumulative_tsn);
51678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GE(asoc->cumulative_tsn, new_cum_tsn)) {
51698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Already got there ... */
51708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
51718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
51738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * now we know the new TSN is more advanced, let's find the actual
51748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * gap
51758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
51768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CALC_TSN_TO_GAP(gap, new_cum_tsn, asoc->mapping_array_base_tsn);
51778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->cumulative_tsn = new_cum_tsn;
51788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (gap >= m_size) {
51798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((long)gap > sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv)) {
51808f9e45fea288542b24a6bda01269c6fc184d991at			struct mbuf *op_err;
51818f9e45fea288542b24a6bda01269c6fc184d991at			char msg[SCTP_DIAG_INFO_LEN];
51828f9e45fea288542b24a6bda01269c6fc184d991at
51838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
51848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * out of range (of single byte chunks in the rwnd I
51858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * give out). This must be an attacker.
51868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
51878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*abort_flag = 1;
51888f9e45fea288542b24a6bda01269c6fc184d991at			snprintf(msg, sizeof(msg),
51898f9e45fea288542b24a6bda01269c6fc184d991at			         "New cum ack %8.8x too high, highest TSN %8.8x",
51908f9e45fea288542b24a6bda01269c6fc184d991at			         new_cum_tsn, asoc->highest_tsn_inside_map);
51918f9e45fea288542b24a6bda01269c6fc184d991at			op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
51928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA+SCTP_LOC_33;
51938f9e45fea288542b24a6bda01269c6fc184d991at			sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
51948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
51958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_fwdtsn_map_over);
5197000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
51988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size);
51998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->mapping_array_base_tsn = new_cum_tsn + 1;
52008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->highest_tsn_inside_map = new_cum_tsn;
5201000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
52028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size);
52038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->highest_tsn_inside_nr_map = new_cum_tsn;
5204000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
52058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
52068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_map(0, 3, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
52078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
52098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK_ASSERT(stcb);
52108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i <= gap; i++) {
52118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (!SCTP_IS_TSN_PRESENT(asoc->mapping_array, i) &&
52128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    !SCTP_IS_TSN_PRESENT(asoc->nr_mapping_array, i)) {
52138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i);
52148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_TSN_GT(asoc->mapping_array_base_tsn + i, asoc->highest_tsn_inside_nr_map)) {
52158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					asoc->highest_tsn_inside_nr_map = asoc->mapping_array_base_tsn + i;
52168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
52178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
52208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*************************************************************/
52218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* 2. Clear up re-assembly queue                             */
52228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*************************************************************/
52238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
52248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * First service it if pd-api is up, just in case we can progress it
52258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * forward
52268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
52278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->fragmented_delivery_inprogress) {
52288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_service_reassembly(stcb, asoc);
52298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
52308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* For each one on here see if we need to toss it */
52318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
52328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * For now large messages held on the reasmqueue that are
52338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * complete will be tossed too. We could in theory do more
52348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * work to spin through and stop after dumping one msg aka
52358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * seeing the start of a new msg at the head, and call the
52368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * delivery function... to see if it can be delivered... But
52378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * for now we just dump everything on the queue.
52388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
52398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
52408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_TSN_GE(new_cum_tsn, chk->rec.data.TSN_seq)) {
52418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* It needs to be tossed */
52428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
52438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_TSN_GT(chk->rec.data.TSN_seq, asoc->tsn_last_delivered)) {
52448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->tsn_last_delivered = chk->rec.data.TSN_seq;
52458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->str_of_pdapi = chk->rec.data.stream_number;
52468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->ssn_of_pdapi = chk->rec.data.stream_seq;
52478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->fragment_flags = chk->rec.data.rcv_flags;
52488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->size_on_reasm_queue -= chk->send_size;
52508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ucount_decr(asoc->cnt_on_reasm_queue);
52518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Clear up any stream problem */
52538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) != SCTP_DATA_UNORDERED &&
52548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_SSN_GT(chk->rec.data.stream_seq, asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered)) {
52558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
52568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * We must dump forward this streams
52578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * sequence number if the chunk is
52588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * not unordered that is being
52598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * skipped. There is a chance that
52608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * if the peer does not include the
52618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * last fragment in its FWD-TSN we
52628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * WILL have a problem here since
52638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * you would have a partial chunk in
52648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * queue that may not be
52658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * deliverable. Also if a Partial
52668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * delivery API as started the user
52678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * may get a partial chunk. The next
52688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * read returning a new chunk...
52698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * really ugly but I see no way
52708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * around it! Maybe a notify??
52718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
52728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered = chk->rec.data.stream_seq;
52738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->data) {
52758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(chk->data);
52768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				chk->data = NULL;
52778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
52798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
52808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
52818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Ok we have gone beyond the end of the
52828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * fwd-tsn's mark.
52838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
52848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
52858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
52878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*******************************************************/
52888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* 3. Update the PR-stream re-ordering queues and fix  */
52898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*    delivery issues as needed.                       */
52908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*******************************************************/
52918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	fwd_sz -= sizeof(*fwd);
52928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m && fwd_sz) {
52938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* New method. */
52948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		unsigned int num_str;
52958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_strseq *stseq, strseqbuf;
52968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += sizeof(*fwd);
52978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_LOCK(stcb->sctp_ep);
52998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		num_str = fwd_sz / sizeof(struct sctp_strseq);
53008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < num_str; i++) {
53018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint16_t st;
53028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stseq = (struct sctp_strseq *)sctp_m_getptr(m, offset,
53038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								    sizeof(struct sctp_strseq),
53048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								    (uint8_t *)&strseqbuf);
53058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			offset += sizeof(struct sctp_strseq);
53068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stseq == NULL) {
53078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
53088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Convert */
53108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			st = ntohs(stseq->stream);
53118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stseq->stream = st;
53128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			st = ntohs(stseq->sequence);
53138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stseq->sequence = st;
53148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* now process */
53168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
53188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Ok we now look for the stream/seq on the read queue
53198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * where its not all delivered. If we find it we transmute the
53208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * read entry into a PDI_ABORTED.
53218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
53228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stseq->stream >= asoc->streamincnt) {
53238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* screwed up streams, stop!  */
53248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
53258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((asoc->str_of_pdapi == stseq->stream) &&
53278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (asoc->ssn_of_pdapi == stseq->sequence)) {
53288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* If this is the one we were partially delivering
53298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * now then we no longer are. Note this will change
53308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * with the reassembly re-write.
53318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
53328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->fragmented_delivery_inprogress = 0;
53338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_flush_reassm_for_str_seq(stcb, asoc, stseq->stream, stseq->sequence);
53358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(ctl, &stcb->sctp_ep->read_queue, next) {
53368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((ctl->sinfo_stream == stseq->stream) &&
53378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (ctl->sinfo_ssn == stseq->sequence)) {
53388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					str_seq = (stseq->stream << 16) | stseq->sequence;
53398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ctl->end_added = 1;
53408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ctl->pdapi_aborted = 1;
53418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sv = stcb->asoc.control_pdapi;
53428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.control_pdapi = ctl;
53438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
53448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                stcb,
53458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                SCTP_PARTIAL_DELIVERY_ABORTED,
53468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                (void *)&str_seq,
53478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							SCTP_SO_NOT_LOCKED);
53488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.control_pdapi = sv;
53498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
53508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if ((ctl->sinfo_stream == stseq->stream) &&
53518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					   SCTP_SSN_GT(ctl->sinfo_ssn, stseq->sequence)) {
53528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* We are past our victim SSN */
53538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
53548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
53558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			strm = &asoc->strmin[stseq->stream];
53578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_SSN_GT(stseq->sequence, strm->last_sequence_delivered)) {
53588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Update the sequence number */
53598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				strm->last_sequence_delivered = stseq->sequence;
53608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* now kick the stream the new way */
53628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                        /*sa_ignore NO_NULL_CHK*/
53638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_kick_prsctp_reorder_queue(stcb, strm);
53648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
53668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
53678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
53688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now slide thing forward.
53698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
53708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_slide_mapping_arrays(stcb);
53718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
53738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* now lets kick out and check for more fragmented delivery */
53748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                /*sa_ignore NO_NULL_CHK*/
53758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_deliver_reasm_check(stcb, &stcb->asoc);
53768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
53778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5378