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