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