18c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*- 28c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Copyright (c) 2001-2008, 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> 358975bd5397c2ec97f50e0b87b544054e0536bfe1t__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 271230 2014-09-07 18:05:37Z 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_auth.h> 478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_indata.h> 488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_asconf.h> 498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_bsd_addr.h> 508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_timer.h> 518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_crc32.h> 5248830a703639020b04dbea0128bc37fd8a8ab35et#if defined(INET) || defined(INET6) 530ac02f34d6041cd0018437596a5a9a94685e6919tuexen#if !defined(__Userspace_os_Windows) 548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/udp.h> 5581616c6a3e184f46276632dd15aa489cd06d94dftuexen#endif 566c632b3f6e570981666f8a3ff4be34eaf1735835t#endif 578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) 588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/smp.h> 598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define APPLE_FILE_NO 2 638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_stop_all_cookie_timers(struct sctp_tcb *stcb) 688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 7023273859c39742f09cc5ec7c9bf32ff225661e82tuexen 718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This now not only stops all cookie timers 728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it also stops any INIT timers as well. This 738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * will make sure that the timers are stopped in 748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * all collision cases. 758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(stcb); 778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->rxt_timer.type == SCTP_TIMER_TYPE_COOKIE) { 798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, 808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, 818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, 82b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_1); 838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (net->rxt_timer.type == SCTP_TIMER_TYPE_INIT) { 848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_INIT, 858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, 868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, 87b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_2); 888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* INIT handler */ 938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 94e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_handle_init(struct mbuf *m, int iphlen, int offset, 95e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 9651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen struct sctp_init_chunk *cp, struct sctp_inpcb *inp, 9751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen struct sctp_tcb *stcb, int *abort_no_unlock, 9851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 9951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid, uint32_t mflowid, 10051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 10151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint32_t vrf_id, uint16_t port) 1028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 1038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_init *init; 1048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 1058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_init: handling INIT tcb:%p\n", 107ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)stcb); 1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 1098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(inp); 1108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11123273859c39742f09cc5ec7c9bf32ff225661e82tuexen /* validate length */ 1128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) { 1138f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 114e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 11551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 11651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 11751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id, port); 1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) 1208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto outnow; 1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* validate parameters */ 12423273859c39742f09cc5ec7c9bf32ff225661e82tuexen init = &cp->init; 1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (init->initiate_tag == 0) { 1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* protocol error... send abort */ 1278f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 128e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 12951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 13051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 13151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id, port); 1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) 1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 1358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto outnow; 1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) { 1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid parameter... send abort */ 1398f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 140e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 14151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 14251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 14351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 1448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id, port); 1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) 1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 1478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto outnow; 1488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (init->num_inbound_streams == 0) { 1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* protocol error... send abort */ 1518f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 152e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 15351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 15451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 15551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 1568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id, port); 1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) 1588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 1598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto outnow; 1608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (init->num_outbound_streams == 0) { 1628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* protocol error... send abort */ 1638f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 164e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 16551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 16651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 16751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 1688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id, port); 1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) 1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto outnow; 1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_validate_init_auth_params(m, offset + sizeof(*cp), 17423273859c39742f09cc5ec7c9bf32ff225661e82tuexen offset + ntohs(cp->ch.chunk_length))) { 1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* auth parameter(s) error... send abort */ 1768f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 1778f9e45fea288542b24a6bda01269c6fc184d991at "Problem with AUTH parameters"); 1788f9e45fea288542b24a6bda01269c6fc184d991at sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 17951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 18051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 18151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 18251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) 1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto outnow; 1868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18723273859c39742f09cc5ec7c9bf32ff225661e82tuexen /* We are only accepting if we have a socket with positive so_qlimit.*/ 18823273859c39742f09cc5ec7c9bf32ff225661e82tuexen if ((stcb == NULL) && 18923273859c39742f09cc5ec7c9bf32ff225661e82tuexen ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 19023273859c39742f09cc5ec7c9bf32ff225661e82tuexen (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 19123273859c39742f09cc5ec7c9bf32ff225661e82tuexen (inp->sctp_socket == NULL) || 19223273859c39742f09cc5ec7c9bf32ff225661e82tuexen (inp->sctp_socket->so_qlimit == 0))) { 19323273859c39742f09cc5ec7c9bf32ff225661e82tuexen /* 19423273859c39742f09cc5ec7c9bf32ff225661e82tuexen * FIX ME ?? What about TCP model and we have a 19523273859c39742f09cc5ec7c9bf32ff225661e82tuexen * match/restart case? Actually no fix is needed. 19623273859c39742f09cc5ec7c9bf32ff225661e82tuexen * the lookup will always find the existing assoc so stcb 19723273859c39742f09cc5ec7c9bf32ff225661e82tuexen * would not be NULL. It may be questionable to do this 19823273859c39742f09cc5ec7c9bf32ff225661e82tuexen * since we COULD just send back the INIT-ACK and hope that 19923273859c39742f09cc5ec7c9bf32ff225661e82tuexen * the app did accept()'s by the time the COOKIE was sent. But 20023273859c39742f09cc5ec7c9bf32ff225661e82tuexen * there is a price to pay for COOKIE generation and I don't 20123273859c39742f09cc5ec7c9bf32ff225661e82tuexen * want to pay it on the chance that the app will actually do 20223273859c39742f09cc5ec7c9bf32ff225661e82tuexen * some accepts(). The App just looses and should NOT be in 20323273859c39742f09cc5ec7c9bf32ff225661e82tuexen * this state :-) 20423273859c39742f09cc5ec7c9bf32ff225661e82tuexen */ 20523273859c39742f09cc5ec7c9bf32ff225661e82tuexen if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) { 2068f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 2078f9e45fea288542b24a6bda01269c6fc184d991at "No listener"); 2088f9e45fea288542b24a6bda01269c6fc184d991at sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, 20951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 21051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 21151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 21251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 21323273859c39742f09cc5ec7c9bf32ff225661e82tuexen } 21423273859c39742f09cc5ec7c9bf32ff225661e82tuexen goto outnow; 21523273859c39742f09cc5ec7c9bf32ff225661e82tuexen } 21623273859c39742f09cc5ec7c9bf32ff225661e82tuexen if ((stcb != NULL) && 21723273859c39742f09cc5ec7c9bf32ff225661e82tuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT)) { 21823273859c39742f09cc5ec7c9bf32ff225661e82tuexen SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending SHUTDOWN-ACK\n"); 21923273859c39742f09cc5ec7c9bf32ff225661e82tuexen sctp_send_shutdown_ack(stcb, NULL); 22023273859c39742f09cc5ec7c9bf32ff225661e82tuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 22123273859c39742f09cc5ec7c9bf32ff225661e82tuexen } else { 22223273859c39742f09cc5ec7c9bf32ff225661e82tuexen SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n"); 223e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, src, dst, 224e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sh, cp, 22551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 22651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 22751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 22851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port, 22923273859c39742f09cc5ec7c9bf32ff225661e82tuexen ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED)); 23023273859c39742f09cc5ec7c9bf32ff225661e82tuexen } 2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen outnow: 2328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 2348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 2368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 2388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process peer "INIT/INIT-ACK" chunk returns value < 0 on error 2398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 2428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked 2438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 2448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_UNUSED 2458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 2468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen) 2478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int unsent_data = 0; 2498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int i; 2508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_queue_pending *sp; 2518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 2528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This function returns the number of streams that have 2548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * true unsent data on them. Note that as it looks through 2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it will clean up any places that have old data that 2568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * has been sent but left at top of stream queue. 2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 2598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_LOCK(stcb); 2608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 2618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Check to see if some data queued */ 2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 2638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 2648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp = TAILQ_FIRST(&stcb->asoc.strmout[i].outqueue); 2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp == NULL) { 2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sp->msg_is_complete) && 2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sp->length == 0) && 2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sp->sender_all_done)) { 2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We are doing differed cleanup. Last 2728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * time through when we took all the data 2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the sender_all_done was not set. 2748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->put_last_out == 0) { 2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n"); 2778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d\n", 2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->sender_all_done, 2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->length, 2808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->msg_is_complete, 2818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->put_last_out); 2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.stream_queue_cnt, 1); 2848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&stcb->asoc.strmout[i].outqueue, sp, next); 2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->net) { 2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(sp->net); 2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->net = NULL; 2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->data) { 2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(sp->data); 2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->data = NULL; 2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_strmoq(stcb, sp, so_locked); 2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsent_data++; 2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_UNLOCK(stcb); 3018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (unsent_data); 3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 3050ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) 3068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_init *init; 3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 3098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *lnet; 3108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int i; 3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen init = &cp->init; 3138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 3148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* save off parameters */ 3158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peer_vtag = ntohl(init->initiate_tag); 3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peers_rwnd = ntohl(init->a_rwnd); 3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* init tsn's */ 3188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1; 3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&asoc->nets)) { 3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update any ssthresh's that may have a default */ 3228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) { 3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lnet->ssthresh = asoc->peers_rwnd; 3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) { 3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_INITIALIZATION); 3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_LOCK(stcb); 3318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) { 3328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int newcnt; 3338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_out *outs; 3348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_queue_pending *sp, *nsp; 3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, *nchk; 3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* abandon the upper streams */ 3388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen newcnt = ntohs(init->num_inbound_streams); 3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { 3408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.data.stream_number >= newcnt) { 3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); 3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->send_queue_cnt--; 343446be8e8a472f6e688885674d2430118fc4be5d7t if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 344446be8e8a472f6e688885674d2430118fc4be5d7t asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 345446be8e8a472f6e688885674d2430118fc4be5d7t#ifdef INVARIANTS 346446be8e8a472f6e688885674d2430118fc4be5d7t } else { 347446be8e8a472f6e688885674d2430118fc4be5d7t panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 348446be8e8a472f6e688885674d2430118fc4be5d7t#endif 349446be8e8a472f6e688885674d2430118fc4be5d7t } 3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data != NULL) { 3518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_bufspace(stcb, asoc, chk, 1); 35247674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 35347674b651417d493ff4e0318113fd7beeef119dbtuexen 0, chk, SCTP_SO_NOT_LOCKED); 3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 3558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 3608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 3618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->strmout) { 3648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = newcnt; i < asoc->pre_open_streams; i++) { 3658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen outs = &asoc->strmout[i]; 3668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { 3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&outs->outqueue, sp, next); 3688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_queue_cnt--; 3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, 37047674b651417d493ff4e0318113fd7beeef119dbtuexen stcb, 0, sp, SCTP_SO_NOT_LOCKED); 3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->data) { 3728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(sp->data); 3738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->data = NULL; 3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->net) { 3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(sp->net); 3778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->net = NULL; 3788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Free the chunk */ 3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED); 3818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 3828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* cut back the count */ 3868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->pre_open_streams = newcnt; 3878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_UNLOCK(stcb); 3898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams; 3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* EY - nr_sack: initialize highest tsn in nr_mapping_array */ 3928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 3948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_map(0, 5, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 3958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This is the next one we expect */ 3978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_reset_seq_in = asoc->asconf_seq_in + 1; 39832a191a90b5c914a02047389c5b3197e08fc9841tuexen 3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->mapping_array_base_tsn = ntohl(init->initial_tsn); 4008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in; 4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->advanced_peer_ack_point = asoc->last_acked_seq; 4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* open the requested streams */ 4048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->strmin != NULL) { 4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Free the old ones */ 4078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *ctl, *nctl; 4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < asoc->streamincnt; i++) { 4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) { 4118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next); 4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(ctl->whoFrom); 4138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ctl->whoFrom = NULL; 4148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(ctl->data); 4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ctl->data = NULL; 4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_readq(stcb, ctl); 4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(asoc->strmin, SCTP_M_STRMI); 4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 421f72906cec69866943ecd6c46cc74c87a8b5e9d5ft if (asoc->max_inbound_streams > ntohs(init->num_outbound_streams)) { 422f72906cec69866943ecd6c46cc74c87a8b5e9d5ft asoc->streamincnt = ntohs(init->num_outbound_streams); 423f72906cec69866943ecd6c46cc74c87a8b5e9d5ft } else { 424f72906cec69866943ecd6c46cc74c87a8b5e9d5ft asoc->streamincnt = asoc->max_inbound_streams; 4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt * 4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_stream_in), SCTP_M_STRMI); 4288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->strmin == NULL) { 4298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we didn't get memory for the streams! */ 4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "process_init: couldn't get memory for the streams!\n"); 4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 4328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < asoc->streamincnt; i++) { 4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmin[i].stream_no = i; 4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmin[i].last_sequence_delivered = 0xffff; 4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INIT(&asoc->strmin[i].inqueue); 4378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmin[i].delivery_started = 0; 4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 4408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * load_address_from_init will put the addresses into the 4418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * association when the COOKIE is processed or the INIT-ACK is 4428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * processed. Both types of COOKIE's existing and new call this 4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * routine. It will remove addresses that are no longer in the 4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * association (for the restarting case where addresses are 4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * removed). Up front when the INIT arrives we will discard it if it 4468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is a restart and new addresses have been added. 4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 4480ac02f34d6041cd0018437596a5a9a94685e6919tuexen /* sa_ignore MEMLEAK */ 4498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 4508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 4518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INIT-ACK message processing/consumption returns value < 0 on error 4548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 456e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_process_init_ack(struct mbuf *m, int iphlen, int offset, 457e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 45851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 45951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen struct sctp_nets *net, int *abort_no_unlock, 46051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 46151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid, uint32_t mflowid, 46251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 46351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint32_t vrf_id) 4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 4668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int retval, abort_flag; 4688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t initack_limit; 469b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int nat_friendly = 0; 4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* First verify that we have no illegal param's */ 4728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen abort_flag = 0; 4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen op_err = sctp_arethere_unrecognized_parameters(m, 4758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (offset + sizeof(struct sctp_init_chunk)), 4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly); 4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (abort_flag) { 4788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Send an abort and notify peer */ 47947674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 4818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->peer_supports_nat = (uint8_t)nat_friendly; 4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the peer's parameters in the INIT-ACK */ 4860ac02f34d6041cd0018437596a5a9a94685e6919tuexen retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb); 4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (retval < 0) { 4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (retval); 4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen initack_limit = offset + ntohs(cp->ch.chunk_length); 4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* load all addresses */ 4920ac02f34d6041cd0018437596a5a9a94685e6919tuexen if ((retval = sctp_load_addresses_from_init(stcb, m, 493e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen (offset + sizeof(struct sctp_init_chunk)), initack_limit, 494e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, NULL))) { 4958f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 4968f9e45fea288542b24a6bda01269c6fc184d991at "Problem with address parameters"); 4978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, 4988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "Load addresses from INIT causes an abort %d\n", 4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen retval); 500e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 5018f9e45fea288542b24a6bda01269c6fc184d991at src, dst, sh, op_err, 50251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 50351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 50451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 50551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, net->port); 5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 5078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* if the peer doesn't support asconf, flush the asconf queue */ 510fb3816eaffe5878bb1286adb120fd160da178a05t if (asoc->asconf_supported == 0) { 5118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr *param, *nparam; 5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) { 5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->asconf_queue, param, next); 5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(param, SCTP_M_ASC_ADDR); 5168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs, 5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.local_hmacs); 5218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (op_err) { 5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_queue_op_err(stcb, op_err); 5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* queuing will steal away the mbuf chain to the out queue */ 5248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen op_err = NULL; 5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* extract the cookie and queue it to "echo" it back... */ 5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 5308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 5328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->error_count = 0; 5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Cancel the INIT timer, We do this first before queueing the 5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cookie. We always cancel at the primary to assue that we are 5408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * canceling the timer started by the INIT which always goes to the 5418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * primary. 5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb, 5448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->primary_destination, SCTP_FROM_SCTP_INPUT+SCTP_LOC_4); 5458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* calculate the RTO */ 54732a191a90b5c914a02047389c5b3197e08fc9841tuexen net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, 5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RTT_FROM_NON_DATA); 5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen retval = sctp_send_cookie_echo(m, offset, stcb, net); 5518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (retval < 0) { 5528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * No cookie, we probably should send a op error. But in any 5548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * case if there is no cookie in the INIT-ACK, we can 5558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * abandon the peer, its broke. 5568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (retval == -3) { 5588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We abort with an error of missing mandatory param */ 5598f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, ""); 5608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (op_err) { 5618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Expand beyond to include the mandatory 5638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * param cookie 5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inv_mandatory_param *mp; 5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(op_err) = 5688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_inv_mandatory_param); 5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mp = mtod(op_err, 5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inv_mandatory_param *); 5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Subtract the reserved param */ 5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mp->length = 5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen htons(sizeof(struct sctp_inv_mandatory_param) - 2); 5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mp->num_param = htonl(1); 5758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mp->param = htons(SCTP_STATE_COOKIE); 5768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mp->resv = 0; 5778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 579e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 58051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 58151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 58251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 58351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, net->port); 5848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (retval); 5878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 5918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 5938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, 5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, struct sctp_nets *net) 5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 596bfb1bf7e665a02b48026482bf33d05c83dfad73bt union sctp_sockstore store; 5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *r_net, *f_net; 5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval tv; 5998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int req_prim = 0; 6008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t old_error_counter; 6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) { 6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Invalid length */ 6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&store, 0, sizeof(store)); 6088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (cp->heartbeat.hb_info.addr_family) { 6098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 6108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 6118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) { 612bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin.sin_family = cp->heartbeat.hb_info.addr_family; 6137b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 614bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin.sin_len = cp->heartbeat.hb_info.addr_len; 6158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 616bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin.sin_port = stcb->rport; 617bfb1bf7e665a02b48026482bf33d05c83dfad73bt memcpy(&store.sin.sin_addr, cp->heartbeat.hb_info.address, 618bfb1bf7e665a02b48026482bf33d05c83dfad73bt sizeof(store.sin.sin_addr)); 6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 6208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 6238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 6268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) { 627bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin6.sin6_family = cp->heartbeat.hb_info.addr_family; 6287b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN 629bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin6.sin6_len = cp->heartbeat.hb_info.addr_len; 6308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 631bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin6.sin6_port = stcb->rport; 6321b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t memcpy(&store.sin6.sin6_addr, cp->heartbeat.hb_info.address, sizeof(struct in6_addr)); 6338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6386a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#if defined(__Userspace__) 6396a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen case AF_CONN: 6406a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_conn)) { 641bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sconn.sconn_family = cp->heartbeat.hb_info.addr_family; 6427b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SCONN_LEN 643bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sconn.sconn_len = cp->heartbeat.hb_info.addr_len; 6446a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 645bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sconn.sconn_port = stcb->rport; 6461b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t memcpy(&store.sconn.sconn_addr, cp->heartbeat.hb_info.address, sizeof(void *)); 6476a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen } else { 6486a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen return; 6496a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen } 6506a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen break; 6516a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 6528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 655bfb1bf7e665a02b48026482bf33d05c83dfad73bt r_net = sctp_findnet(stcb, &store.sa); 6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (r_net == NULL) { 6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n"); 6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 6598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((r_net && (r_net->dest_state & SCTP_ADDR_UNCONFIRMED)) && 6618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (r_net->heartbeat_random1 == cp->heartbeat.hb_info.random_value1) && 6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (r_net->heartbeat_random2 == cp->heartbeat.hb_info.random_value2)) { 6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 6648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If the its a HB and it's random value is correct when can 6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * confirm the destination. 6668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (r_net->dest_state & SCTP_ADDR_REQ_PRIMARY) { 6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination = r_net; 6708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen r_net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY; 6718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen f_net = TAILQ_FIRST(&stcb->asoc.nets); 6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (f_net != r_net) { 6738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* first one on the list is NOT the primary 6748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_cmpaddr() is much more efficent if 6758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the primary is the first on the list, make it 6768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * so. 6778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 6788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&stcb->asoc.nets, r_net, sctp_next); 6798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_HEAD(&stcb->asoc.nets, r_net, sctp_next); 6808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen req_prim = 1; 6828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 6848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 6858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 6868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 6878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_error_counter = r_net->error_count; 6898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen r_net->error_count = 0; 6908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen r_net->hb_responded = 1; 6918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tv.tv_sec = cp->heartbeat.hb_info.time_value_1; 6928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tv.tv_usec = cp->heartbeat.hb_info.time_value_2; 6938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now lets do a RTO with this */ 69432a191a90b5c914a02047389c5b3197e08fc9841tuexen r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy, 6958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RTT_FROM_NON_DATA); 6968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) { 6978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen r_net->dest_state |= SCTP_ADDR_REACHABLE; 6988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 69947674b651417d493ff4e0318113fd7beeef119dbtuexen 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 7008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (r_net->dest_state & SCTP_ADDR_PF) { 7028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen r_net->dest_state &= ~SCTP_ADDR_PF; 7038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net); 7048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (old_error_counter > 0) { 7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 7088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (r_net == stcb->asoc.primary_destination) { 7108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.alternate) { 7118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* release the alternate, primary is good */ 7128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(stcb->asoc.alternate); 7138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.alternate = NULL; 7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Mobility adaptation */ 7178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (req_prim) { 7188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sctp_is_mobility_feature_on(stcb->sctp_ep, 719e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_BASE) || 720e2828360ea9cf8951730d46f5c14626c9425cb30t sctp_is_mobility_feature_on(stcb->sctp_ep, 721e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_FASTHANDOFF)) && 722e2828360ea9cf8951730d46f5c14626c9425cb30t sctp_is_mobility_feature_on(stcb->sctp_ep, 723e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_PRIM_DELETED)) { 7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER+SCTP_LOC_7); 7268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_mobility_feature_on(stcb->sctp_ep, 7278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MOBILITY_FASTHANDOFF)) { 7288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_assoc_immediate_retrans(stcb, 7298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination); 7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_mobility_feature_on(stcb->sctp_ep, 7328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MOBILITY_BASE)) { 7338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_move_chunks_from_net(stcb, 7348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.deleted_primary); 7358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_delete_prim_timer(stcb->sctp_ep, stcb, 7378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.deleted_primary); 7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_nat_colliding_state(struct sctp_tcb *stcb) 7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 7458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* return 0 means we want you to proceed with the abort 7468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * non-zero means no abort processing 7478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpasochead *head; 7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { 7518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* generate a new vtag and send init */ 7528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_asocs); 7530ac02f34d6041cd0018437596a5a9a94685e6919tuexen stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 7548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 7558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* put it in the bucket in the vtag hash of assoc's for the system */ 7568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(head, stcb, sctp_asocs); 7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 7588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* treat like a case where the cookie expired i.e.: 7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - dump current cookie. 7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - generate a new vtag. 7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - resend init. 7658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* generate a new vtag and send init */ 7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_asocs); 7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.state &= ~SCTP_STATE_COOKIE_ECHOED; 7698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.state |= SCTP_STATE_COOKIE_WAIT; 7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_all_cookie_timers(stcb); 7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_toss_old_cookies(stcb, &stcb->asoc); 7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* put it in the bucket in the vtag hash of assoc's for the system */ 7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(head, stcb, sctp_asocs); 7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 7778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_nat_missing_state(struct sctp_tcb *stcb, 7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 786fb3816eaffe5878bb1286adb120fd160da178a05t /* return 0 means we want you to proceed with the abort 787fb3816eaffe5878bb1286adb120fd160da178a05t * non-zero means no abort processing 788fb3816eaffe5878bb1286adb120fd160da178a05t */ 789fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.auth_supported == 0) { 790fb3816eaffe5878bb1286adb120fd160da178a05t SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n"); 791fb3816eaffe5878bb1286adb120fd160da178a05t return (0); 792fb3816eaffe5878bb1286adb120fd160da178a05t } 793fb3816eaffe5878bb1286adb120fd160da178a05t sctp_asconf_send_nat_state_update(stcb, net); 794fb3816eaffe5878bb1286adb120fd160da178a05t return (1); 7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 79947674b651417d493ff4e0318113fd7beeef119dbtuexensctp_handle_abort(struct sctp_abort_chunk *abort, 8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, struct sctp_nets *net) 8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 8020612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 8038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 8058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t len; 80647674b651417d493ff4e0318113fd7beeef119dbtuexen uint16_t error; 80747674b651417d493ff4e0318113fd7beeef119dbtuexen 8088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n"); 8098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) 8108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 8118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 81247674b651417d493ff4e0318113fd7beeef119dbtuexen len = ntohs(abort->ch.chunk_length); 8138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (len > sizeof (struct sctp_chunkhdr)) { 8148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Need to check the cause codes for our 8158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * two magic nat aborts which don't kill the assoc 8168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * necessarily. 8178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_missing_nat_state *natc; 81932a191a90b5c914a02047389c5b3197e08fc9841tuexen 82047674b651417d493ff4e0318113fd7beeef119dbtuexen natc = (struct sctp_missing_nat_state *)(abort + 1); 82147674b651417d493ff4e0318113fd7beeef119dbtuexen error = ntohs(natc->cause); 82247674b651417d493ff4e0318113fd7beeef119dbtuexen if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) { 8238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 82447674b651417d493ff4e0318113fd7beeef119dbtuexen abort->ch.chunk_flags); 8258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_handle_nat_colliding_state(stcb)) { 8268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 8278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 82847674b651417d493ff4e0318113fd7beeef119dbtuexen } else if (error == SCTP_CAUSE_NAT_MISSING_STATE) { 8298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 83047674b651417d493ff4e0318113fd7beeef119dbtuexen abort->ch.chunk_flags); 8318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_handle_nat_missing_state(stcb, net)) { 8328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 8338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 83547674b651417d493ff4e0318113fd7beeef119dbtuexen } else { 83647674b651417d493ff4e0318113fd7beeef119dbtuexen error = 0; 8378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* stop any receive timers */ 8398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_6); 8408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* notify user of the abort and clean up... */ 84147674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED); 8428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the tcb */ 8438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_aborted); 8448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 8458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 8468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 8478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS 8498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_print_out_track_log(stcb); 8508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 8510612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 8528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 8538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 8548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 8558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 8568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 8578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 8588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 8598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 8608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 8618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT+SCTP_LOC_6); 8620612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 8638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 8648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 8658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n"); 8668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 8678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 8698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_start_net_timers(struct sctp_tcb *stcb) 8708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 8718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t cnt_hb_sent; 8728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 8738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_hb_sent = 0; 8758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 8768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* For each network start: 8778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 1) A pmtu timer. 8788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 2) A HB timer 8798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 3) If the dest in unconfirmed send 8808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a hb as well if under max_hb_burst have 8818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * been sent. 8828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net); 8848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 8858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) && 886b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen (cnt_hb_sent < SCTP_BASE_SYSCTL(sctp_hb_maxburst))) { 8878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 8888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_hb_sent++; 8898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cnt_hb_sent) { 89232a191a90b5c914a02047389c5b3197e08fc9841tuexen sctp_chunk_output(stcb->sctp_ep, stcb, 89332a191a90b5c914a02047389c5b3197e08fc9841tuexen SCTP_OUTPUT_FROM_COOKIE_ACK, 8948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SO_NOT_LOCKED); 8958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 8978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 9008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_shutdown(struct sctp_shutdown_chunk *cp, 9018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag) 9028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 9038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 9048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int some_on_streamwheel; 9050612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 9088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 9108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_handle_shutdown: handling SHUTDOWN\n"); 9118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) 9128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 9148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 9158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 9168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) { 9198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Shutdown NOT the expected size */ 9208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 9220ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_update_acked(stcb, cp, abort_flag); 9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*abort_flag) { 9248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->control_pdapi) { 9288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* With a normal shutdown 9298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we assume the end of last record. 9308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_READ_LOCK(stcb->sctp_ep); 9328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->control_pdapi->end_added = 1; 9338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->control_pdapi->pdapi_aborted = 1; 9348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->control_pdapi = NULL; 9358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 9360612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 9378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 9388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 9398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 9408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 9418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 9428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 9438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 9448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* assoc was freed while we were unlocked */ 9458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 9468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 9498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 9500612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 9518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 9528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 9538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* goto SHUTDOWN_RECEIVED state to block new requests */ 9558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_socket) { 9568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 9578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) && 9588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 9598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED); 9608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 9618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* notify upper layer that peer has initiated a shutdown */ 9628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 9638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* reset time */ 9658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 9668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { 9698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * stop the shutdown timer, since we WILL move to 9718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SHUTDOWN-ACK-SENT. 9728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_8); 9748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now is there unsent data on a stream somewhere? */ 9768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED); 9778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&asoc->send_queue) || 9798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen !TAILQ_EMPTY(&asoc->sent_queue) || 9808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen some_on_streamwheel) { 9818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* By returning we will push more data out */ 9828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 9848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no outstanding data to send, so move on... */ 9858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* send SHUTDOWN-ACK */ 9868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* move to SHUTDOWN-ACK-SENT state */ 9878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 9888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 9898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 9908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); 9928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 9938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_timers_for_shutdown(stcb); 9947988ea8f0c067cf3757e798b473b1ae4d34b6dfdt sctp_send_shutdown_ack(stcb, net); 9958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, 9968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net); 9978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 9998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 10010ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, 10028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, 10038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 10048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 10058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 10060612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 10078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 10088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 10108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 10118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 10128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n"); 10138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) 10148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 10158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 10178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process according to association state */ 10188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 10198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 10208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* unexpected SHUTDOWN-ACK... do OOTB handling... */ 10218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_shutdown_complete(stcb, net, 1); 10228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 10238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 10248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) && 10268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { 10278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* unexpected SHUTDOWN-ACK... so ignore... */ 10288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 10298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 10308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->control_pdapi) { 10328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* With a normal shutdown 10338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we assume the end of last record. 10348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 10358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_READ_LOCK(stcb->sctp_ep); 10368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->control_pdapi->end_added = 1; 10378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->control_pdapi->pdapi_aborted = 1; 10388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->control_pdapi = NULL; 10398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 10400612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 10418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 10428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 10438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 10448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 10458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 10468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 10478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* assoc was freed while we were unlocked */ 10488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 10498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 10508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 10528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 10530612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 10548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 10558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 10568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 105797e4568a3ba270aaad30d8713c38235a1d8fa518t#ifdef INVARIANTS 10588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&asoc->send_queue) || 10598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen !TAILQ_EMPTY(&asoc->sent_queue) || 10608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 106197e4568a3ba270aaad30d8713c38235a1d8fa518t panic("Queues are not empty when handling SHUTDOWN-ACK"); 10628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 106397e4568a3ba270aaad30d8713c38235a1d8fa518t#endif 10648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* stop the timer */ 10658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_9); 10668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* send SHUTDOWN-COMPLETE */ 10678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_shutdown_complete(stcb, net, 0); 10688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* notify upper layer protocol */ 10698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_socket) { 10708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 10718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 107223273859c39742f09cc5ec7c9bf32ff225661e82tuexen stcb->sctp_socket->so_snd.sb_cc = 0; 10738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1074e5acde438f3c0c70f50751fa4c6a8209650f67cbtuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 10758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 10768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 10778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the TCB but first save off the ep */ 10780612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 10798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 10808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 10818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 10828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 10838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 10848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 10858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 10868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT+SCTP_LOC_10); 10870612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 10888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 10898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 10908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 10918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 10928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 10938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Skip past the param header and then we will find the chunk that caused the 10948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * problem. There are two possiblities ASCONF or FWD-TSN other than that and 10958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * our peer must be broken. 10968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 10978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 10988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr, 10998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 11008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 11018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_chunkhdr *chk; 11028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk = (struct sctp_chunkhdr *)((caddr_t)phdr + sizeof(*phdr)); 11048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (chk->chunk_type) { 11058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ASCONF_ACK: 11068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ASCONF: 11078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_asconf_cleanup(stcb, net); 11088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_FORWARD_CUM_TSN: 1110a8657c4fc04fb9cc82100f648810d51ec6ab155at stcb->asoc.prsctp_supported = 0; 11118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 11138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 11148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "Peer does not support chunk type %d(%x)??\n", 11158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->chunk_type, (uint32_t) chk->chunk_type); 11168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 11198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 11218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Skip past the param header and then we will find the param that caused the 11228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * problem. There are a number of param's in a ASCONF OR the prsctp param 11238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * these will turn of specific features. 1124fb3816eaffe5878bb1286adb120fd160da178a05t * XXX: Is this the right thing to do? 11258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 11278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr) 11288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 11298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *pbad; 11308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen pbad = phdr + 1; 11328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ntohs(pbad->param_type)) { 11338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* pr-sctp draft */ 11348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_PRSCTP_SUPPORTED: 1135a8657c4fc04fb9cc82100f648810d51ec6ab155at stcb->asoc.prsctp_supported = 0; 11368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SUPPORTED_CHUNK_EXT: 11388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* draft-ietf-tsvwg-addip-sctp */ 11408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_HAS_NAT_SUPPORT: 11418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peer_supports_nat = 0; 11428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ADD_IP_ADDRESS: 11448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_DEL_IP_ADDRESS: 11458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SET_PRIM_ADDR: 1146fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.asconf_supported = 0; 11478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SUCCESS_REPORT: 11498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ERROR_CAUSE_IND: 11508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n"); 11518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 11528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "Turning off ASCONF to this strange peer\n"); 1153fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.asconf_supported = 0; 11548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 11568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 11578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "Peer does not support param type %d(%x)??\n", 11588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen pbad->param_type, (uint32_t) pbad->param_type); 11598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 11628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 11648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_error(struct sctp_chunkhdr *ch, 11658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, struct sctp_nets *net) 11668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 11678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int chklen; 11688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *phdr; 116947674b651417d493ff4e0318113fd7beeef119dbtuexen uint16_t error, error_type; 11708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t error_len; 11718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 11728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int adjust; 11730612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 11748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 11758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 11768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* parse through all of the errors and process */ 11788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 11798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = (struct sctp_paramhdr *)((caddr_t)ch + 11808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_chunkhdr)); 11818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr); 118247674b651417d493ff4e0318113fd7beeef119dbtuexen error = 0; 11838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) { 11848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Process an Error Cause */ 11858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error_type = ntohs(phdr->param_type); 11868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error_len = ntohs(phdr->param_length); 11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((error_len > chklen) || (error_len == 0)) { 11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid param length for this param */ 11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Bogus length in error param- chunk left:%d errorlen:%d\n", 11908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chklen, error_len); 11918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 11928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 119347674b651417d493ff4e0318113fd7beeef119dbtuexen if (error == 0) { 119447674b651417d493ff4e0318113fd7beeef119dbtuexen /* report the first error cause */ 119547674b651417d493ff4e0318113fd7beeef119dbtuexen error = error_type; 119647674b651417d493ff4e0318113fd7beeef119dbtuexen } 11978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (error_type) { 11988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_INVALID_STREAM: 11998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_MISSING_PARAM: 12008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_INVALID_PARAM: 12018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_NO_USER_DATA: 12028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Software error we got a %d back? We have a bug :/ (or do they?)\n", 12038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error_type); 12048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_NAT_COLLIDING_STATE: 12068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 12078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch->chunk_flags); 12088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_handle_nat_colliding_state(stcb)) { 1209b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 12108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_NAT_MISSING_STATE: 12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch->chunk_flags); 12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_handle_nat_missing_state(stcb, net)) { 1216b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_STALE_COOKIE: 12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We only act if we have echoed a cookie and are 12228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * waiting. 12238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 12258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int *p; 12268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p = (int *)((caddr_t)phdr + sizeof(*phdr)); 12288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Save the time doubled */ 12298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_preserve_req = ntohl(*p) << 1; 12308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stale_cookie_count++; 12318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->stale_cookie_count > 12328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->max_init_times) { 123347674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); 12348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now free the asoc */ 12350612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 12368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 12378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 12388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 12398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 12408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 12418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 12428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 12438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 12448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT+SCTP_LOC_11); 12450612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 12468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 12478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 12488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 12498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* blast back to INIT state */ 12518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_toss_old_cookies(stcb, &stcb->asoc); 12528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->state &= ~SCTP_STATE_COOKIE_ECHOED; 12538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->state |= SCTP_STATE_COOKIE_WAIT; 12548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_all_cookie_timers(stcb); 12558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 12568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_UNRESOLVABLE_ADDR: 12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Nothing we can do here, we don't do hostname 12618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * addresses so if the peer does not like my IPv6 12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (or IPv4 for that matter) it does not matter. If 12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * they don't support that type of address, they can 12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOT possibly get that packet type... i.e. with no 12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * IPv6 you can't recieve a IPv6 packet. so we can 12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * safely ignore this one. If we ever added support 12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * for HOSTNAME Addresses, then we would need to do 12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * something here. 12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_UNRECOG_CHUNK: 12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_process_unrecog_chunk(stcb, phdr, net); 12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_UNRECOG_PARAM: 12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_process_unrecog_param(stcb, phdr); 12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_COOKIE_IN_SHUTDOWN: 12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 12798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We ignore this since the timer will drive out a 12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * new cookie anyway and there timer will drive us 12818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to send a SHUTDOWN_COMPLETE. We can't send one 12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * here since we don't have their tag. 12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_DELETING_LAST_ADDR: 12868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_RESOURCE_SHORTAGE: 12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_DELETING_SRC_ADDR: 12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 12898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We should NOT get these here, but in a 12908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASCONF-ACK. 12918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "Peer sends ASCONF errors in a Operational Error?<%d>?\n", 12938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error_type); 12948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_CAUSE_OUT_OF_RESC: 12968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * And what, pray tell do we do with the fact that 12988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the peer is out of resources? Not really sure we 12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * could do anything but abort. I suspect this 13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * should have came WITH an abort instead of in a 13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * OP-ERROR. 13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_handle_error: unknown error type = 0x%xh\n", 13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error_type); 13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen adjust = SCTP_SIZE32(error_len); 13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chklen -= adjust; 13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = (struct sctp_paramhdr *)((caddr_t)phdr + adjust); 13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 131347674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_ulp_notify(SCTP_NOTIFY_REMOTE_ERROR, stcb, error, ch, SCTP_SO_NOT_LOCKED); 13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 1318e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, 1319e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 132051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 132151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen struct sctp_nets *net, int *abort_no_unlock, 132251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 132351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid, uint32_t mflowid, 132451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 132551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint32_t vrf_id) 13268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 13278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_init_ack *init_ack; 13288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 13298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 13318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_handle_init_ack: handling INIT-ACK\n"); 13328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 13348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 13358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_handle_init_ack: TCB is null\n"); 13368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) { 13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Invalid length */ 13408f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1341e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1342e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 134351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 134451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 134551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 134651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, net->port); 13478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 13488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 13498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen init_ack = &cp->init; 13518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* validate parameters */ 13528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (init_ack->initiate_tag == 0) { 13538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* protocol error... send an abort */ 13548f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1355e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1356e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 135751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 135851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 135951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 136051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, net->port); 13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 13628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 13638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) { 13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* protocol error... send an abort */ 13668f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1367e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1368e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 136951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 137051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 137151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 137251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, net->port); 13738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 13748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 13758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (init_ack->num_inbound_streams == 0) { 13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* protocol error... send an abort */ 13788f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1379e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1380e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 138151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 138251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 138351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 138451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, net->port); 13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 13868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (init_ack->num_outbound_streams == 0) { 13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* protocol error... send an abort */ 13908f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1391e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1392e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 139351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 139451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 139551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 139651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, net->port); 13978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *abort_no_unlock = 1; 13988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 13998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process according to association state... */ 14018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (stcb->asoc.state & SCTP_STATE_MASK) { 14028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_COOKIE_WAIT: 14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* this is the expected state for this chunk */ 14048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the INIT-ACK parameters */ 14058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.primary_destination->dest_state & 14068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_UNCONFIRMED) { 14078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * The primary is where we sent the INIT, we can 14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * always consider it confirmed when the INIT-ACK is 14108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returned. Do this before we load addresses 14118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * though. 14128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 14138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination->dest_state &= 14148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ~SCTP_ADDR_UNCONFIRMED; 14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 14168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED); 14178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1418e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen if (sctp_process_init_ack(m, iphlen, offset, src, dst, sh, cp, stcb, 141951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen net, abort_no_unlock, 142051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 142151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 142251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 142351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id) < 0) { 14248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* error in parsing parameters */ 14258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 14268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update our state */ 14288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n"); 14298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED); 14308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* reset the RTO calc */ 14328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 14338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 14348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 14358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 14368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 14378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 14388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 14408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 14418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 14428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * collapse the init timer back in case of a exponential 14438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * backoff 14448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 14458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, 14468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net); 14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the send at the end of the inbound data processing will 14498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cause the cookie to be sent 14508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 14518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 14528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_SHUTDOWN_SENT: 14538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* incorrect state... discard */ 14548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 14558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_COOKIE_ECHOED: 14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* incorrect state... discard */ 14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 14588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_OPEN: 14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* incorrect state... discard */ 14608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_EMPTY: 14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_INUSE: 14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* incorrect state... discard */ 14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Leaving handle-init-ack end\n"); 14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 14718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_tcb * 14738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 1474e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, 14758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 14768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp, struct sctp_nets **netp, 14778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *init_src, int *notification, 14788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 147951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 148051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid, uint32_t mflowid, 148151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 14828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id, uint16_t port); 14838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 14868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * handle a state cookie for an existing association m: input packet mbuf 14878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a 14888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "split" mbuf and the cookie signature does not exist offset: offset into 14898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * mbuf to the cookie-echo chunk 14908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 14918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_tcb * 14928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, 1493e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, 14948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 14958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp, 14960ac02f34d6041cd0018437596a5a9a94685e6919tuexen struct sockaddr *init_src, int *notification, 149751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 149851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 149951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid, uint32_t mflowid, 150051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 150151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint32_t vrf_id, uint16_t port) 15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 15048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_init_chunk *init_cp, init_buf; 15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_init_ack_chunk *initack_cp, initack_buf; 15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 15078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 15088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int init_offset, initack_offset, i; 15098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int retval; 1510b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int spec_flag = 0; 15118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t how_indx; 151220d5d287bff2075897105f85287230d55bdfa420t#if defined(SCTP_DETAILED_STR_STATS) 151320d5d287bff2075897105f85287230d55bdfa420t int j; 151420d5d287bff2075897105f85287230d55bdfa420t#endif 151532a191a90b5c914a02047389c5b3197e08fc9841tuexen 15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net = *netp; 15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* I know that the TCB is non-NULL from the caller */ 15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); how_indx++) { 15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->cookie_how[how_indx] == 0) 15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) { 15248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 1; 15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 15278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* SHUTDOWN came in after sending INIT-ACK */ 15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination); 15298f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, ""); 1530e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, 153151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 153251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 153351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 153451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, net->port); 15358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 15368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 2; 15378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 15388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 15408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * find and validate the INIT chunk in the cookie (peer's info) the 15418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INIT should start after the cookie-echo header struct (chunk 15428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * header, state cookie header struct) 15438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen init_offset = offset += sizeof(struct sctp_cookie_echo_chunk); 15458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen init_cp = (struct sctp_init_chunk *) 15478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 15488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *) & init_buf); 15498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (init_cp == NULL) { 15508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* could not pull a INIT chunk in cookie */ 15518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (init_cp->ch.chunk_type != SCTP_INITIATION) { 15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * find and validate the INIT-ACK chunk in the cookie (my info) the 15588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INIT-ACK follows the INIT chunk 15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 1560b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen initack_cp = (struct sctp_init_ack_chunk *) 15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *) & initack_buf); 15648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (initack_cp == NULL) { 15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* could not pull INIT-ACK chunk in cookie */ 15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 15698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 15708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 15728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag)) { 15738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 15748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * case D in Section 5.2.4 Table 2: MMAA process accordingly 15758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to get into the OPEN state 15768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 15788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Opps, this means that we somehow generated two vtag's 15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the same. I.e. we did: 15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Us Peer 15828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * <---INIT(tag=a)------ 15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ----INIT-ACK(tag=t)--> 15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ----INIT(tag=t)------> *1 15858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * <---INIT-ACK(tag=a)--- 15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * <----CE(tag=t)------------- *2 15878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 15888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * At point *1 we should be generating a different 15898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * tag t'. Which means we would throw away the CE and send 15908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ours instead. Basically this is case C (throw away side). 15918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 15938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 17; 15948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 15958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1597e2828360ea9cf8951730d46f5c14626c9425cb30t switch (SCTP_GET_STATE(asoc)) { 15988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_COOKIE_WAIT: 15998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_COOKIE_ECHOED: 16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 16018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INIT was sent but got a COOKIE_ECHO with the 16028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * correct tags... just accept it...but we must 16038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process the init so that we can make sure we 16048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * have the right seq no's. 16058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 16068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* First we must process the INIT !! */ 16070ac02f34d6041cd0018437596a5a9a94685e6919tuexen retval = sctp_process_init(init_cp, stcb); 16088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (retval < 0) { 16098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 16108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 3; 16118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 16128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we have already processed the INIT so no problem */ 16148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, 16158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_12); 16168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_13); 16178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update current state */ 16188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 16198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 16208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 16218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 16228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 16248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 16258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 16268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, asoc->primary_destination); 16278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_GAUGE32(sctps_currestab); 16298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_all_cookie_timers(stcb); 16308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 16318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 16328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_socket->so_qlimit == 0) 16338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ) { 16340612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 16358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 16368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 16378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 16388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Here is where collision would go if we 16398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * did a connect() and instead got a 16408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * init/init-ack/cookie done before the 16418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * init-ack came back.. 16428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 16438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->sctp_flags |= 16448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_CONNECTED; 16450612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 16468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 16478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 16488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 16498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 16508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 16518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, -1); 16528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 16538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 1654e2828360ea9cf8951730d46f5c14626c9425cb30t return (NULL); 16558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 16578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen soisconnected(stcb->sctp_socket); 16580612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 16598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 16608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 16618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* notify upper layer */ 16638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *notification = SCTP_NOTIFY_ASSOC_UP; 16648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 16658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since we did not send a HB make sure we 16668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * don't double things 16678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 16688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->hb_responded = 1; 16698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = sctp_calculate_rto(stcb, asoc, net, 167032a191a90b5c914a02047389c5b3197e08fc9841tuexen &cookie->time_entered, 167132a191a90b5c914a02047389c5b3197e08fc9841tuexen sctp_align_unsafe_makecopy, 16728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RTT_FROM_NON_DATA); 16738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.sctp_autoclose_ticks && 16758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) { 16768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 16778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp, stcb, NULL); 16788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we're in the OPEN state (or beyond), so 16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * peer must have simply lost the COOKIE-ACK 16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* end switch */ 16878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_all_cookie_timers(stcb); 16888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 16898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We ignore the return code here.. not sure if we should 16908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * somehow abort.. but we do have an existing asoc. This 16918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * really should not fail. 16928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 16930ac02f34d6041cd0018437596a5a9a94685e6919tuexen if (sctp_load_addresses_from_init(stcb, m, 16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen init_offset + sizeof(struct sctp_init_chunk), 1695e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen initack_offset, src, dst, init_src)) { 16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 16978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 4; 16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* respond with a COOKIE-ACK */ 17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_toss_old_cookies(stcb, asoc); 17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_cookie_ack(stcb); 17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 5; 17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 170732a191a90b5c914a02047389c5b3197e08fc9841tuexen 17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag && 17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie->tie_tag_my_vtag == 0 && 17118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie->tie_tag_peer_vtag == 0) { 17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * case C in Section 5.2.4 Table 2: XMOO silently discard 17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 6; 17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If nat support, and the below and stcb is established, 17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * send back a ABORT(colliding state) if we are established. 17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) && 17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->peer_supports_nat) && 17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 17268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->peer_vtag == 0)))) { 17278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Special case - Peer's support nat. We may have 17288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * two init's that we gave out the same tag on since 17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one was not established.. i.e. we get INIT from host-1 17308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * behind the nat and we respond tag-a, we get a INIT from 17318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * host-2 behind the nat and we get tag-a again. Then we 17328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * bring up host-1 (or 2's) assoc, Then comes the cookie 17338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * from hsot-2 (or 1). Now we have colliding state. We must 17348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * send an abort here with colliding state indication. 17358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 17368f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, ""); 1737e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, 173851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 173951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 174051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 174151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 17458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 17468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->peer_vtag == 0))) { 17478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * case B in Section 5.2.4 Table 2: MXAA or MOAA my info 17498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * should be ok, re-accept peer info 17508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 17518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 17528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Extension of case C. 17538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If we hit this, then the random number 17548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * generator returned the same vtag when we 17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * first sent our INIT-ACK and when we later sent 17568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * our INIT. The side with the seq numbers that are 17578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * different will be the one that normnally would 17588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * have hit case C. This in effect "extends" our vtags 17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * in this collision case to be 64 bits. The same collision 17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * could occur aka you get both vtag and seq number the 17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * same twice in a row.. but is much less likely. If it 17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * did happen then we would proceed through and bring 17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * up the assoc.. we may end up with the wrong stream 17648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * setup however.. which would be bad.. but there is 17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * no way to tell.. until we send on a stream that does 17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not exist :-) 17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 7; 17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1771b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 17748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 8; 17758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_14); 17768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_all_cookie_timers(stcb); 17778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 17788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since we did not send a HB make sure we don't double 17798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * things 17808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 17818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->hb_responded = 1; 17828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.sctp_autoclose_ticks && 17838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 17848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, 17858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen NULL); 17868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 17888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 17898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) { 17918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Ok the peer probably discarded our 17928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * data (if we echoed a cookie+data). So anything 17938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * on the sent_queue should be marked for 17948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * retransmit, we may not get something to 17958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * kick us so it COULD still take a timeout 17968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to move these.. but it can't hurt to mark them. 17978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 17988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 17998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 18008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->sent < SCTP_DATAGRAM_RESEND) { 18018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent = SCTP_DATAGRAM_RESEND; 18028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_decrease(chk); 18038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_decrease(stcb, chk); 18048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 18058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen spec_flag++; 18068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the INIT info (peer's info) */ 18110ac02f34d6041cd0018437596a5a9a94685e6919tuexen retval = sctp_process_init(init_cp, stcb); 18128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (retval < 0) { 18138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 9; 18158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 18168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18170ac02f34d6041cd0018437596a5a9a94685e6919tuexen if (sctp_load_addresses_from_init(stcb, m, 18188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen init_offset + sizeof(struct sctp_init_chunk), 1819e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen initack_offset, src, dst, init_src)) { 18208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 18218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 10; 18228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 18238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->state & SCTP_STATE_COOKIE_WAIT) || 18258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->state & SCTP_STATE_COOKIE_ECHOED)) { 18268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *notification = SCTP_NOTIFY_ASSOC_UP; 18278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 18298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 18308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_socket->so_qlimit == 0)) { 18310612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 18328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 18338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 18348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->sctp_flags |= 18358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_CONNECTED; 18360612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 18378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 18388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 18398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 18408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 18418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 18428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, -1); 18438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 18448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 18458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 18468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 18488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen soisconnected(stcb->sctp_socket); 18490612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 18508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 18518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 18528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 18548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 18558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 18568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 18578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_GAUGE32(sctps_currestab); 18588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 18598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_restartestab); 18608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 18618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 18628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 18648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 18658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 18668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, asoc->primary_destination); 18678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_all_cookie_timers(stcb); 18698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_toss_old_cookies(stcb, asoc); 18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_cookie_ack(stcb); 18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (spec_flag) { 18728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* only if we have retrans set do we do this. What 18738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this call does is get only the COOKIE-ACK out 18748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and then when we return the normal call to 18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_chunk_output will get the retrans out 18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * behind this. 18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_chunk_output(inp,stcb, SCTP_OUTPUT_FROM_COOKIE_ACK, SCTP_SO_NOT_LOCKED); 18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 11; 18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 18848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 18868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) && 18878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie->tie_tag_my_vtag == asoc->my_vtag_nonce && 18888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce && 18898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie->tie_tag_peer_vtag != 0) { 18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpasochead *head; 1891ea4ad6b0591b5fcab0af327804d0ac0190694b57t#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1892ea4ad6b0591b5fcab0af327804d0ac0190694b57t struct socket *so; 1893ea4ad6b0591b5fcab0af327804d0ac0190694b57t#endif 1894ea4ad6b0591b5fcab0af327804d0ac0190694b57t 18958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peer_supports_nat) { 1896b6a8c974796d76c59ef64a7555e446c9cd171877t /* This is a gross gross hack. 1897b6a8c974796d76c59ef64a7555e446c9cd171877t * Just call the cookie_new code since we 1898b6a8c974796d76c59ef64a7555e446c9cd171877t * are allowing a duplicate association. 1899b6a8c974796d76c59ef64a7555e446c9cd171877t * I hope this works... 1900b6a8c974796d76c59ef64a7555e446c9cd171877t */ 1901b6a8c974796d76c59ef64a7555e446c9cd171877t return (sctp_process_cookie_new(m, iphlen, offset, src, dst, 1902b6a8c974796d76c59ef64a7555e446c9cd171877t sh, cookie, cookie_len, 1903b6a8c974796d76c59ef64a7555e446c9cd171877t inp, netp, init_src,notification, 1904b6a8c974796d76c59ef64a7555e446c9cd171877t auth_skipped, auth_offset, auth_len, 190551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 1906b6a8c974796d76c59ef64a7555e446c9cd171877t use_mflowid, mflowid, 190751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 1908b6a8c974796d76c59ef64a7555e446c9cd171877t vrf_id, port)); 19098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 19118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * case A in Section 5.2.4 Table 2: XXMM (peer restarted) 19128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 19138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* temp code */ 19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 19158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 12; 19168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_15); 19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_16); 19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* notify upper layer */ 19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *notification = SCTP_NOTIFY_ASSOC_RESTART; 19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN) && 19238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 19248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 19258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_GAUGE32(sctps_currestab); 19268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_GAUGE32(sctps_restartestab); 19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { 19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_GAUGE32(sctps_collisionestab); 19318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 19348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, asoc->primary_destination); 19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) { 19388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* move to OPEN state, if not in SHUTDOWN_SENT */ 19398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 19408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->pre_open_streams = 19428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(initack_cp->init.num_outbound_streams); 19438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 19468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_reset_seq_in = asoc->init_seq_number; 19508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->advanced_peer_ack_point = asoc->last_acked_seq; 19528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->mapping_array) { 19538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(asoc->mapping_array, 0, 19548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->mapping_array_size); 19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->nr_mapping_array) { 19578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(asoc->nr_mapping_array, 0, 19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->mapping_array_size); 19598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 1961ea4ad6b0591b5fcab0af327804d0ac0190694b57t#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1962ea4ad6b0591b5fcab0af327804d0ac0190694b57t so = SCTP_INP_SO(stcb->sctp_ep); 1963ea4ad6b0591b5fcab0af327804d0ac0190694b57t SCTP_SOCKET_LOCK(so, 1); 1964ea4ad6b0591b5fcab0af327804d0ac0190694b57t#endif 19658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WLOCK(); 19668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(stcb->sctp_ep); 19678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 19688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, -1); 19698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* send up all the data */ 19708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_LOCK(stcb); 19718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1972ea4ad6b0591b5fcab0af327804d0ac0190694b57t sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED); 197360db5740d3bcc26fd4ebc19b6b0652506994fd14t for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 197460db5740d3bcc26fd4ebc19b6b0652506994fd14t stcb->asoc.strmout[i].chunks_on_queues = 0; 197520d5d287bff2075897105f85287230d55bdfa420t#if defined(SCTP_DETAILED_STR_STATS) 197620d5d287bff2075897105f85287230d55bdfa420t for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) { 197720d5d287bff2075897105f85287230d55bdfa420t asoc->strmout[i].abandoned_sent[j] = 0; 197820d5d287bff2075897105f85287230d55bdfa420t asoc->strmout[i].abandoned_unsent[j] = 0; 197920d5d287bff2075897105f85287230d55bdfa420t } 198020d5d287bff2075897105f85287230d55bdfa420t#else 198120d5d287bff2075897105f85287230d55bdfa420t asoc->strmout[i].abandoned_sent[0] = 0; 198220d5d287bff2075897105f85287230d55bdfa420t asoc->strmout[i].abandoned_unsent[0] = 0; 198320d5d287bff2075897105f85287230d55bdfa420t#endif 19848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmout[i].stream_no = i; 1985e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t stcb->asoc.strmout[i].next_sequence_send = 0; 19868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmout[i].last_msg_incomplete = 0; 19878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the INIT-ACK info (my info) */ 19898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 19908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 19918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* pull from vtag hash */ 19938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_asocs); 19948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* re-insert to new vtag position */ 19958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, 19968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(hashasocmark))]; 19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * put it in the bucket in the vtag hash of assoc's for the 19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * system 20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(head, stcb, sctp_asocs); 20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_UNLOCK(stcb); 20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(stcb->sctp_ep); 20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 2006ea4ad6b0591b5fcab0af327804d0ac0190694b57t#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2007ea4ad6b0591b5fcab0af327804d0ac0190694b57t SCTP_SOCKET_UNLOCK(so, 1); 2008ea4ad6b0591b5fcab0af327804d0ac0190694b57t#endif 200984c69be44d793ca2fffe2ff446114f81b80c96a5t asoc->total_flight = 0; 201084c69be44d793ca2fffe2ff446114f81b80c96a5t asoc->total_flight_count = 0; 201184c69be44d793ca2fffe2ff446114f81b80c96a5t /* process the INIT info (peer's info) */ 20120ac02f34d6041cd0018437596a5a9a94685e6919tuexen retval = sctp_process_init(init_cp, stcb); 20138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (retval < 0) { 20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 20158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 13; 20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 20208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since we did not send a HB make sure we don't double 20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * things 20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->hb_responded = 1; 20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20250ac02f34d6041cd0018437596a5a9a94685e6919tuexen if (sctp_load_addresses_from_init(stcb, m, 20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen init_offset + sizeof(struct sctp_init_chunk), 2027e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen initack_offset, src, dst, init_src)) { 20288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 14; 20308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* respond with a COOKIE-ACK */ 20348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_all_cookie_timers(stcb); 20358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_toss_old_cookies(stcb, asoc); 20368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_cookie_ack(stcb); 20378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 20388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 15; 20398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (how_indx < sizeof(asoc->cookie_how)) 20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->cookie_how[how_indx] = 16; 20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* all other cases... */ 20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * handle a state cookie for a new association m: input packet mbuf chain-- 20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a "split" mbuf 20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and the cookie signature does not exist offset: offset into mbuf to the 20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cookie-echo chunk length: length of the cookie chunk to: where the init 20548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * was from returns a new TCB 20558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 205651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexenstatic struct sctp_tcb * 20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 2058e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, 20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp, struct sctp_nets **netp, 20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *init_src, int *notification, 20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 206351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 206451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid, uint32_t mflowid, 206551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 20668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id, uint16_t port) 20678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 20688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_init_chunk *init_cp, init_buf; 20708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_init_ack_chunk *initack_cp, initack_buf; 2071bfb1bf7e665a02b48026482bf33d05c83dfad73bt union sctp_sockstore store; 20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int init_offset, initack_offset, initack_limit; 20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int retval; 20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int error = 0; 20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE]; 20770612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 20788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(inp); 20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * find and validate the INIT chunk in the cookie (peer's info) the 20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INIT should start after the cookie-echo header struct (chunk 20868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * header, state cookie header struct) 20878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 20888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen init_offset = offset + sizeof(struct sctp_cookie_echo_chunk); 20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen init_cp = (struct sctp_init_chunk *) 20908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 20918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *) & init_buf); 20928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (init_cp == NULL) { 20938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* could not pull a INIT chunk in cookie */ 20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, 20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_cookie_new: could not pull INIT chunk hdr\n"); 20968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 20978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (init_cp->ch.chunk_type != SCTP_INITIATION) { 20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "HUH? process_cookie_new: could not find INIT chunk!\n"); 21008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 21018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2102b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 21038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 21048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * find and validate the INIT-ACK chunk in the cookie (my info) the 21058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INIT-ACK follows the INIT chunk 21068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 21078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen initack_cp = (struct sctp_init_ack_chunk *) 21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *) & initack_buf); 21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (initack_cp == NULL) { 21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* could not pull INIT-ACK chunk in cookie */ 21128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: could not pull INIT-ACK chunk hdr\n"); 21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: We can't use the INIT_ACK's chk_length to determine the 21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "initack_limit" value. This is because the chk_length field 21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * includes the length of the cookie, but the cookie is omitted when 21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the INIT and INIT_ACK are tacked onto the cookie... 21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 21248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen initack_limit = offset + cookie_len; 21258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 21278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * now that we know the INIT/INIT-ACK are in place, create a new TCB 21288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and popluate 21298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 21308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Here we do a trick, we set in NULL for the proc/thread argument. We 21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * do this since in effect we only use the p argument when 21348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the socket is unbound and we must do an implicit bind. 21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Since we are getting a cookie, we cannot be unbound. 21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb = sctp_aloc_assoc(inp, init_src, &error, 21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohl(initack_cp->init.initiate_tag), vrf_id, 21398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 21408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct thread *)NULL 21418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__) 21428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (PKTHREAD)NULL 21438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 21448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct proc *)NULL 21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 21468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ); 21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* memory problem? */ 21518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, 21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "process_cookie_new: no room for another TCB!\n"); 21538f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 2155e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 215651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 215751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 215851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 215951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 21608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the correct sctp_nets */ 21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp) 21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp = sctp_findnet(stcb, init_src); 21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get scope variables out of cookie */ 21687988ea8f0c067cf3757e798b473b1ae4d34b6dfdt asoc->scope.ipv4_local_scope = cookie->ipv4_scope; 21697988ea8f0c067cf3757e798b473b1ae4d34b6dfdt asoc->scope.site_scope = cookie->site_scope; 21707988ea8f0c067cf3757e798b473b1ae4d34b6dfdt asoc->scope.local_scope = cookie->local_scope; 21717988ea8f0c067cf3757e798b473b1ae4d34b6dfdt asoc->scope.loopback_scope = cookie->loopback_scope; 21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21737988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__) 21747988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if ((asoc->scope.ipv4_addr_legal != cookie->ipv4_addr_legal) || 21757988ea8f0c067cf3757e798b473b1ae4d34b6dfdt (asoc->scope.ipv6_addr_legal != cookie->ipv6_addr_legal) || 21767988ea8f0c067cf3757e798b473b1ae4d34b6dfdt (asoc->scope.conn_addr_legal != cookie->conn_addr_legal)) { 21777988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#else 21787988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if ((asoc->scope.ipv4_addr_legal != cookie->ipv4_addr_legal) || 21797988ea8f0c067cf3757e798b473b1ae4d34b6dfdt (asoc->scope.ipv6_addr_legal != cookie->ipv6_addr_legal)) { 21807988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif 21818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 21828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Houston we have a problem. The EP changed while the 21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cookie was in flight. Only recourse is to abort the 21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * association. 21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 21898f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 2191e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 219251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 219351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 219451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 219551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 21960612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 22018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT+SCTP_LOC_16); 22030612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 22068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 22078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the INIT-ACK info (my info) */ 22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 22118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 22148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_reset_seq_in = asoc->init_seq_number; 22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->advanced_peer_ack_point = asoc->last_acked_seq; 22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the INIT info (peer's info) */ 22228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp) 22230ac02f34d6041cd0018437596a5a9a94685e6919tuexen retval = sctp_process_init(init_cp, stcb); 22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen retval = 0; 22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (retval < 0) { 22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 22280612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 22308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_16); 22340612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 22388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* load all addresses */ 22410ac02f34d6041cd0018437596a5a9a94685e6919tuexen if (sctp_load_addresses_from_init(stcb, m, 2242e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen init_offset + sizeof(struct sctp_init_chunk), initack_offset, 2243e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, init_src)) { 22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 22450612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 22468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 22498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 22508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_17); 22510612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 22528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * verify any preceding AUTH chunk that was skipped 22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* pull the local authentication parameters from the cookie/init-ack */ 22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auth_get_cookie_params(stcb, m, 22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen initack_offset + sizeof(struct sctp_init_ack_chunk), 22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk))); 22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (auth_skipped) { 22658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_auth_chunk *auth; 22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth = (struct sctp_auth_chunk *) 22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf); 22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, auth_offset)) { 22708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* auth HMAC failed, dump the assoc and packet */ 22718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_AUTH1, 22728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "COOKIE-ECHO: AUTH failed\n"); 22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 22740612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 22788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_18); 22800612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 22828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 22848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remaining chunks checked... good to go */ 22878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.authenticated = 1; 22888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update current state */ 22918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 22928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, asoc->primary_destination); 22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_all_cookie_timers(stcb); 22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_passiveestab); 22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_GAUGE32(sctps_currestab); 23008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if we're doing ASCONFs, check to see if we have any new local 23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * addresses that need to get added to the peer (eg. addresses 23048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * changed while cookie echo in flight). This needs to be done 23058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * after we go to the OPEN state to do the correct asconf 23068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * processing. else, make sure we have the correct addresses in our 23078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * lists 23088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* warning, we re-use sin, sin6, sa_store here! */ 23118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* pull in local_address (our "from" address) */ 23128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (cookie->laddr_type) { 23138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 23148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV4_ADDRESS: 23158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* source addr is IPv4 */ 2316bfb1bf7e665a02b48026482bf33d05c83dfad73bt memset(&store.sin, 0, sizeof(struct sockaddr_in)); 2317bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin.sin_family = AF_INET; 23187b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 2319bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin.sin_len = sizeof(struct sockaddr_in); 23208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 2321bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin.sin_addr.s_addr = cookie->laddress[0]; 23228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV6_ADDRESS: 23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* source addr is IPv6 */ 2327bfb1bf7e665a02b48026482bf33d05c83dfad73bt memset(&store.sin6, 0, sizeof(struct sockaddr_in6)); 2328bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin6.sin6_family = AF_INET6; 23297b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN 2330bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin6.sin6_len = sizeof(struct sockaddr_in6); 23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 2332bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin6.sin6_scope_id = cookie->scope_id; 23331b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t memcpy(&store.sin6.sin6_addr, cookie->laddress, sizeof(struct in6_addr)); 23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 23366a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#if defined(__Userspace__) 23376a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen case SCTP_CONN_ADDRESS: 2338bfb1bf7e665a02b48026482bf33d05c83dfad73bt /* source addr is conn */ 23397b4117116463e6f61e3c39d542fd9fdfb5c395fat memset(&store.sconn, 0, sizeof(struct sockaddr_conn)); 2340bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sconn.sconn_family = AF_CONN; 23417b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SCONN_LEN 2342bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sconn.sconn_len = sizeof(struct sockaddr_conn); 23436a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 2344bfb1bf7e665a02b48026482bf33d05c83dfad73bt memcpy(&store.sconn.sconn_addr, cookie->laddress, sizeof(void *)); 23456a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen break; 23466a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 23478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 23488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 23490612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 23508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 23518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 23528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 23538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 23548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_19); 23550612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 23568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 23578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 23588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 23598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 23608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set up to notify upper layer */ 23638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *notification = SCTP_NOTIFY_ASSOC_UP; 23648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 23658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 23668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_socket->so_qlimit == 0)) { 23678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 23688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This is an endpoint that called connect() how it got a 23698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cookie that is NEW is a bit of a mystery. It must be that 23708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the INIT was sent, but before it got there.. a complete 23718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INIT/INIT-ACK/COOKIE arrived. But of course then it 23728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * should have went to the other code.. not here.. oh well.. 23738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a bit of protection is worth having.. 23748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 23760612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 23778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 23788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 23798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 23808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 23818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 23828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 23838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 23848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 23858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 23878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen soisconnected(stcb->sctp_socket); 23880612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 23898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 23908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 23918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 23928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_socket->so_qlimit)) { 23938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 23948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We don't want to do anything with this one. Since it is 23958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the listening guy. The timer will get started for 23968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * accepted connections in the caller. 23978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ; 23998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* since we did not send a HB make sure we don't double things */ 24018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((netp) && (*netp)) 24028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*netp)->hb_responded = 1; 24038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.sctp_autoclose_ticks && 24058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 24068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL); 24078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* calculate the RTT */ 24098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 24108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((netp) && (*netp)) { 24118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp, 241232a191a90b5c914a02047389c5b3197e08fc9841tuexen &cookie->time_entered, sctp_align_unsafe_makecopy, 24138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RTT_FROM_NON_DATA); 24148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* respond with a COOKIE-ACK */ 24168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_cookie_ack(stcb); 24178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 24198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * check the address lists for any ASCONFs that need to be sent 24208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * AFTER the cookie-ack is sent 24218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 24228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_check_address_list(stcb, m, 24238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen initack_offset + sizeof(struct sctp_init_ack_chunk), 24248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)), 2425bfb1bf7e665a02b48026482bf33d05c83dfad73bt &store.sa, cookie->local_scope, cookie->site_scope, 24268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie->ipv4_scope, cookie->loopback_scope); 24278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 24308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 24318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 24338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CODE LIKE THIS NEEDS TO RUN IF the peer supports the NAT extension, i.e 24348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we NEED to make sure we are not already using the vtag. If so we 24358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * need to send back an ABORT-TRY-AGAIN-WITH-NEW-TAG No middle box bit! 24368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag, 24378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(hashasocmark))]; 24388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(stcb, head, sctp_asocs) { 24398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.my_vtag == tag) && (stcb->rport == rport) && (inp == stcb->sctp_ep)) { 24408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen -- SEND ABORT - TRY AGAIN -- 24418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen*/ 24448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 24468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * handles a COOKIE-ECHO message stcb: modified to either a new or left as 24478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * existing (non-NULL) TCB 24488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 24498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf * 24508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, 2451e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, 24528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp, 24538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp, 24548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 245551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen struct sctp_tcb **locked_tcb, 245651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 245751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid, uint32_t mflowid, 245851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 245951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint32_t vrf_id, uint16_t port) 24608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 24618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_state_cookie *cookie; 24628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *l_stcb = *stcb; 24638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *l_inp; 24648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *to; 24658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_pcb *ep; 24668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m_sig; 24678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE]; 24688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t *sig; 24698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t cookie_ok = 0; 24700784257f13611c0e5c3a4b43b1eb73414d5d89a8tuexen unsigned int sig_offset, cookie_offset; 24718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int cookie_len; 24728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval now; 24738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval time_expires; 24748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int notification = 0; 24758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *netl; 24768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int had_a_existing_tcb = 0; 24778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int send_int_conf = 0; 24788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 24798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in sin; 24808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 24828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 sin6; 24838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24846a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#if defined(__Userspace__) 24856a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen struct sockaddr_conn sconn; 24866a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 24878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 24898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_handle_cookie: handling COOKIE-ECHO\n"); 24908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp_p == NULL) { 24928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 24938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie = &cp->cookie; 24958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie_offset = offset + sizeof(struct sctp_chunkhdr); 24968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie_len = ntohs(cp->ch.chunk_length); 24978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((cookie->peerport != sh->src_port) && 24998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (cookie->myport != sh->dest_port) && 25008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (cookie->my_vtag != sh->v_tag)) { 25018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 25028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * invalid ports or bad tag. Note that we always leave the 25038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * v_tag in the header in network order and when we stored 25048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it in the my_vtag slot we also left it in network order. 25058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This maintains the match even though it may be in the 25068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * opposite byte order of the machine :-> 25078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 25088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 25098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25100784257f13611c0e5c3a4b43b1eb73414d5d89a8tuexen if (cookie_len < sizeof(struct sctp_cookie_echo_chunk) + 25118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_init_chunk) + 25128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) { 25130784257f13611c0e5c3a4b43b1eb73414d5d89a8tuexen /* cookie too small */ 25148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 25158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 25178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * split off the signature into its own mbuf (since it should not be 25188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * calculated in the sctp_hmac_m() call). 25198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 25208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE; 252168beeca578347438d9c434680197647ed551935ft m_sig = m_split(m, sig_offset, M_NOWAIT); 25228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m_sig == NULL) { 25238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* out of memory or ?? */ 25248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 25258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MBUF_LOGGING 25278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 25288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *mat; 2529208d5309857156b26b753ba8cb35813775f49c5btuexen 2530208d5309857156b26b753ba8cb35813775f49c5btuexen for (mat = m_sig; mat; mat = SCTP_BUF_NEXT(mat)) { 25318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_IS_EXTENDED(mat)) { 25328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_mb(mat, SCTP_MBUF_SPLIT); 25338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 25378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 25398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * compute the signature/digest for the cookie 25408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 25418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ep = &(*inp_p)->sctp_ep; 25428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen l_inp = *inp_p; 25438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (l_stcb) { 25448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(l_stcb); 25458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(l_inp); 25478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (l_stcb) { 25488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(l_stcb); 25498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* which cookie is it? */ 25518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) && 25528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ep->current_secret_number != ep->last_secret_number)) { 25538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* it's the old cookie */ 25548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_hmac_m(SCTP_HMAC, 25558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *)ep->secret_key[(int)ep->last_secret_number], 25568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 25578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 25588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* it's the current cookie */ 25598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_hmac_m(SCTP_HMAC, 25608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *)ep->secret_key[(int)ep->current_secret_number], 25618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 25628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the signature */ 25648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(l_inp); 25658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sig = (uint8_t *) sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (uint8_t *) & tmp_sig); 25668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sig == NULL) { 25678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* couldn't find signature */ 25688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(m_sig); 25698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 25708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* compare the received digest with the computed digest */ 25728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) { 25738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* try the old cookie? */ 25748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) && 25758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ep->current_secret_number != ep->last_secret_number)) { 25768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* compute digest with old */ 25778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_hmac_m(SCTP_HMAC, 25788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *)ep->secret_key[(int)ep->last_secret_number], 25798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 25808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* compare */ 25818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0) 25828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie_ok = 1; 25838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 25858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie_ok = 1; 25868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 25898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now before we continue we must reconstruct our mbuf so that 25908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * normal processing of any other chunks will work. 25918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 25928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 25938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m_at; 25948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_at = m; 25968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (SCTP_BUF_NEXT(m_at) != NULL) { 25978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m_at = SCTP_BUF_NEXT(m_at); 25988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_NEXT(m_at) = m_sig; 26008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cookie_ok == 0) { 26038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "handle_cookie_echo: cookie signature validation failed!\n"); 26048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 26058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "offset = %u, cookie_offset = %u, sig_offset = %u\n", 26068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint32_t) offset, cookie_offset, sig_offset); 26078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 26088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 26118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * check the cookie timestamps to be sure it's not stale 26128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&now); 26148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Expire time is in Ticks, so we convert to seconds */ 26158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life); 26168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen time_expires.tv_usec = cookie->time_entered.tv_usec; 26178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TODO sctp_constants.h needs alternative time macros when 26188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * _KERNEL is undefined. 26198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __FreeBSD__ 26218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (timercmp(&now, &time_expires, >)) 26228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 26238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (timevalcmp(&now, &time_expires, >)) 26248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 26258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 26268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* cookie is stale! */ 26278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 26288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stale_cookie_msg *scm; 26298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t tim; 26308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg), 263168beeca578347438d9c434680197647ed551935ft 0, M_NOWAIT, 1, MT_DATA); 26328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (op_err == NULL) { 26338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* FOOBAR */ 26348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 26358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Set the len */ 26378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg); 26388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen scm = mtod(op_err, struct sctp_stale_cookie_msg *); 26398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE); 26408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) + 26418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sizeof(uint32_t)))); 26428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* seconds to usec */ 26438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tim = (now.tv_sec - time_expires.tv_sec) * 1000000; 26448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add in usec */ 26458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tim == 0) 26468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tim = now.tv_usec - cookie->time_entered.tv_usec; 26478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen scm->time_usec = htonl(tim); 2648e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, 264951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 265051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 265151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 265251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 26538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 26548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 26568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now we must see with the lookup address if we have an existing 26578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * asoc. This will only happen if we were in the COOKIE-WAIT state 26588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and a INIT collided with us and somewhere the peer sent the 26598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cookie on another address besides the single address our assoc 26608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * had for him. In this case we will have one of the tie-tags set at 26618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * least AND the address field in the cookie can be used to look it 26628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * up. 26638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to = NULL; 26658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (cookie->addr_type) { 26668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 26678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV6_ADDRESS: 26688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&sin6, 0, sizeof(sin6)); 26698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6.sin6_family = AF_INET6; 26707b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN 26718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6.sin6_len = sizeof(sin6); 26728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 26738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6.sin6_port = sh->src_port; 26748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6.sin6_scope_id = cookie->scope_id; 26758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&sin6.sin6_addr.s6_addr, cookie->address, 26768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(sin6.sin6_addr.s6_addr)); 26778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to = (struct sockaddr *)&sin6; 26788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 26798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 26808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 26818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV4_ADDRESS: 26828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&sin, 0, sizeof(sin)); 26838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin.sin_family = AF_INET; 26847b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 26858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin.sin_len = sizeof(sin); 26868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 26878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin.sin_port = sh->src_port; 26888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin.sin_addr.s_addr = cookie->address[0]; 26898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to = (struct sockaddr *)&sin; 26908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 26918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 26926a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#if defined(__Userspace__) 26936a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen case SCTP_CONN_ADDRESS: 26946a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen memset(&sconn, 0, sizeof(struct sockaddr_conn)); 26956a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen sconn.sconn_family = AF_CONN; 26967b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SCONN_LEN 26976a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen sconn.sconn_len = sizeof(struct sockaddr_conn); 26986a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 26996a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen sconn.sconn_port = sh->src_port; 27006a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen memcpy(&sconn.sconn_addr, cookie->address, sizeof(void *)); 27016a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen to = (struct sockaddr *)&sconn; 27026a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen break; 27036a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 27048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 27058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This should not happen */ 27068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 27078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((*stcb == NULL) && to) { 27098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yep, lets check */ 2710e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen *stcb = sctp_findassociation_ep_addr(inp_p, to, netp, dst, NULL); 27118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*stcb == NULL) { 27128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 27138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We should have only got back the same inp. If we 27148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * got back a different ep we have a problem. The 27158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * original findep got back l_inp and now 27168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (l_inp != *inp_p) { 27188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Bad problem find_ep got a diff inp then special_locate?\n"); 27198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 27218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*locked_tcb == NULL) { 27228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* In this case we found the assoc only 27238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * after we locked the create lock. This means 27248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we are in a colliding case and we must make 27258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sure that we unlock the tcb if its one of the 27268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cases where we throw away the incoming packets. 27278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *locked_tcb = *stcb; 27298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We must also increment the inp ref count 27318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since the ref_count flags was set when we 27328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * did not find the TCB, now we found it which 27338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * reduces the refcount.. we must raise it back 27348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * out to balance it all :-) 27358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INCR_REF((*stcb)->sctp_ep); 27378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((*stcb)->sctp_ep != l_inp) { 27388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Huh? ep:%p diff then l_inp:%p?\n", 2739ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)(*stcb)->sctp_ep, (void *)l_inp); 27408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (to == NULL) { 27458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 27468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 274732a191a90b5c914a02047389c5b3197e08fc9841tuexen 27488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie_len -= SCTP_SIGNATURE_SIZE; 27498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*stcb == NULL) { 27508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* this is the "normal" case... get a new TCB */ 2751e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen *stcb = sctp_process_cookie_new(m, iphlen, offset, src, dst, sh, 2752e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen cookie, cookie_len, *inp_p, 2753e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen netp, to, ¬ification, 275451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen auth_skipped, auth_offset, auth_len, 275551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 275651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 275751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 275851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 27598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 27608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* this is abnormal... cookie-echo on existing TCB */ 27618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen had_a_existing_tcb = 1; 2762e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen *stcb = sctp_process_cookie_existing(m, iphlen, offset, 2763e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, 27648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie, cookie_len, *inp_p, *stcb, netp, to, 276551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen ¬ification, auth_skipped, auth_offset, auth_len, 276651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 276751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 276851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 276951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 27708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*stcb == NULL) { 27738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* still no TCB... must be bad cookie-echo */ 27748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 27758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) 277751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen if ((*netp != NULL) && (use_mflowid != 0)) { 277851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen (*netp)->flowid = mflowid; 27798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 27808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*netp)->flowidset = 1; 27818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 27858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok, we built an association so confirm the address we sent the 27868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INIT-ACK to. 27878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netl = sctp_findnet(*stcb, to); 27898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 27908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This code should in theory NOT run but 27918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netl == NULL) { 27938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TSNH! Huh, why do I need to add this address here? */ 2794b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (sctp_add_remote_addr(*stcb, to, NULL, SCTP_DONOT_SETSCOPE, SCTP_IN_COOKIE_PROC)) { 2795b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 2796b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } 27978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netl = sctp_findnet(*stcb, to); 27988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netl) { 28008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netl->dest_state & SCTP_ADDR_UNCONFIRMED) { 28018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 28028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL, 28038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netl); 28048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_int_conf = 1; 28058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_start_net_timers(*stcb); 28088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) { 28098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!had_a_existing_tcb || 28108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) { 28118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 28128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If we have a NEW cookie or the connect never 28138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * reached the connected state during collision we 28148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * must do the TCP accept thing. 28158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 28168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so, *oso; 28178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 28188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (notification == SCTP_NOTIFY_ASSOC_RESTART) { 28208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 28218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For a restart we will keep the same 28228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * socket, no need to do anything. I THINK!! 28238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 28240ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 28258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (send_int_conf) { 28268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2827e2828360ea9cf8951730d46f5c14626c9425cb30t (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 28288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (m); 28308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen oso = (*inp_p)->sctp_socket; 28328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version < 700000) 28338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 28348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We do this to keep the sockets side happy during 28358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the sonewcon ONLY. 28368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 28378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen NET_LOCK_GIANT(); 28388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&(*stcb)->asoc.refcnt, 1); 28408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK((*stcb)); 28418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 28428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen CURVNET_SET(oso->so_vnet); 28438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 28458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(oso, 1); 28468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = sonewconn(oso, 0 28488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 28498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ,NULL 28508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __Panda__ 28528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ,NULL , (*inp_p)->def_vrf_id 28538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ); 28558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version < 700000) 28568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen NET_UNLOCK_GIANT(); 28578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 28598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(oso, 1); 28608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 28628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen CURVNET_RESTORE(); 28638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK((*stcb)); 28658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 28668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (so == NULL) { 28688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 28690612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 28708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *pcb_so; 28718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Too many sockets */ 28738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n"); 28748f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 28758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_abort_association(*inp_p, NULL, m, iphlen, 2876e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 287751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 287851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 287951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 288051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 28810612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 28828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen pcb_so = SCTP_INP_SO(*inp_p); 28838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&(*stcb)->asoc.refcnt, 1); 28848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK((*stcb)); 28858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(pcb_so, 1); 28868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK((*stcb)); 28878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 28888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_20); 28900612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 28918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(pcb_so, 1); 28928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 28948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = (struct sctp_inpcb *)so->so_pcb; 28968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INCR_REF(inp); 28978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 28988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We add the unbound flag here so that 28998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if we get an soabort() before we get the 29008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * move_pcb done, we will properly cleanup. 29018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | 29038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_CONNECTED | 29048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_IN_TCPPOOL | 2905e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_PCB_FLAGS_UNBOUND | 29068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) | 29078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_DONT_WAKE); 29088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_features = (*inp_p)->sctp_features; 29098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features; 29108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_socket = so; 29118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_frag_point = (*inp_p)->sctp_frag_point; 29128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off; 2913aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t inp->ecn_supported = (*inp_p)->ecn_supported; 2914a8657c4fc04fb9cc82100f648810d51ec6ab155at inp->prsctp_supported = (*inp_p)->prsctp_supported; 2915fb3816eaffe5878bb1286adb120fd160da178a05t inp->auth_supported = (*inp_p)->auth_supported; 2916fb3816eaffe5878bb1286adb120fd160da178a05t inp->asconf_supported = (*inp_p)->asconf_supported; 29172344bfccffeb80545fca6a86e8cda3d56a6f50bft inp->reconfig_supported = (*inp_p)->reconfig_supported; 291844318e900a771ba1a5bafb510c38f33fd5cd8a39t inp->nrsack_supported = (*inp_p)->nrsack_supported; 2919669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t inp->pktdrop_supported = (*inp_p)->pktdrop_supported; 29208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->partial_delivery_point = (*inp_p)->partial_delivery_point; 29218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_context = (*inp_p)->sctp_context; 2922c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen inp->local_strreset_support = (*inp_p)->local_strreset_support; 29238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->inp_starting_point_for_iterator = NULL; 292432a191a90b5c914a02047389c5b3197e08fc9841tuexen#if defined(__Userspace__) 2925d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen inp->ulp_info = (*inp_p)->ulp_info; 292632a191a90b5c914a02047389c5b3197e08fc9841tuexen inp->recv_callback = (*inp_p)->recv_callback; 292732a191a90b5c914a02047389c5b3197e08fc9841tuexen inp->send_callback = (*inp_p)->send_callback; 292832a191a90b5c914a02047389c5b3197e08fc9841tuexen inp->send_sb_threshold = (*inp_p)->send_sb_threshold; 292932a191a90b5c914a02047389c5b3197e08fc9841tuexen#endif 29308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 29318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * copy in the authentication parameters from the 29328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * original endpoint 29338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_ep.local_hmacs) 29358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_hmaclist(inp->sctp_ep.local_hmacs); 29368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_ep.local_hmacs = 29378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_copy_hmaclist((*inp_p)->sctp_ep.local_hmacs); 29388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_ep.local_auth_chunks) 29398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_chunklist(inp->sctp_ep.local_auth_chunks); 29408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_ep.local_auth_chunks = 29418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_copy_chunklist((*inp_p)->sctp_ep.local_auth_chunks); 29428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 29448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now we must move it from one hash table to 29458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * another and get the tcb in the right place. 29468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This is where the one-2-one socket is put into 29498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the accept state waiting for the accept! 29508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*stcb) { 29528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb)->asoc.state |= SCTP_STATE_IN_ACCEPT_QUEUE; 29538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_move_pcb_and_assoc(*inp_p, inp, *stcb); 29558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&(*stcb)->asoc.refcnt, 1); 29578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK((*stcb)); 29588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) 29608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_pull_off_control_to_new_inp((*inp_p), inp, *stcb, 29618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0); 29628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 29638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_pull_off_control_to_new_inp((*inp_p), inp, *stcb, M_NOWAIT); 29648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK((*stcb)); 29668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 29678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now we must check to see if we were aborted while 29708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the move was going on and the lock/unlock happened. 29718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 29738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* yep it was, we leave the 29748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assoc attached to the socket since 29758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the sctp_inpcb_free() call will send 29768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * an abort for us. 29778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 29798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 29808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 29828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Switch over to the new guy */ 29838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *inp_p = inp; 29848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 29858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (send_int_conf) { 29868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 29878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 29888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Pull it from the incomplete queue and wake the guy */ 29910612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 29928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&(*stcb)->asoc.refcnt, 1); 29938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK((*stcb)); 29948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 29958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen soisconnected(so); 29970612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 29988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK((*stcb)); 29998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 30008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 30018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (m); 30038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3005186f71381d5ac588524f9a1401d0c0a9997601e5tuexen if (notification) { 3006186f71381d5ac588524f9a1401d0c0a9997601e5tuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 3007186f71381d5ac588524f9a1401d0c0a9997601e5tuexen } 3008186f71381d5ac588524f9a1401d0c0a9997601e5tuexen if (send_int_conf) { 3009186f71381d5ac588524f9a1401d0c0a9997601e5tuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 3010186f71381d5ac588524f9a1401d0c0a9997601e5tuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 30118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (m); 30138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 30148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 30160ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED, 30178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, struct sctp_nets *net) 30188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 30198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* cp must not be used, others call this without a c-ack :-) */ 30208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 30218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 30238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_handle_cookie_ack: handling COOKIE-ACK\n"); 30248975bd5397c2ec97f50e0b87b544054e0536bfe1t if ((stcb == NULL) || (net == NULL)) { 30258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 30268975bd5397c2ec97f50e0b87b544054e0536bfe1t } 30278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 30298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_all_cookie_timers(stcb); 30318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process according to association state */ 30328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 30338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* state change only needed when I am in right state */ 30348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 30358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 30368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_start_net_timers(stcb); 30378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 30388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 30398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, asoc->primary_destination); 30408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update RTO */ 30438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 30448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_GAUGE32(sctps_currestab); 30458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->overall_error_count == 0) { 30468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO = sctp_calculate_rto(stcb, asoc, net, 304732a191a90b5c914a02047389c5b3197e08fc9841tuexen &asoc->time_entered, sctp_align_safe_nocopy, 30488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RTT_FROM_NON_DATA); 30498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 30518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 30528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 30538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 30540612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 30558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 30568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 30590612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 30608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 30618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 30628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 30638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 30648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 30658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 30668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) == 0) { 30688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen soisconnected(stcb->sctp_socket); 30698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30700612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 30718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 30728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 30758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since we did not send a HB make sure we don't double 30768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * things 30778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->hb_responded = 1; 30798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 30818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We don't need to do the asconf thing, 30828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * nor hb or autoclose if the socket is closed. 30838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto closed_socket; 30858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, 30888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net); 30898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.sctp_autoclose_ticks && 30928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTOCLOSE)) { 30938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 30948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, NULL); 30958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 30978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * send ASCONF if parameters are pending and ASCONFs are 30988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * allowed (eg. addresses changed when init/cookie echo were 30998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * in flight) 31008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 31018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) && 3102fb3816eaffe5878bb1286adb120fd160da178a05t (stcb->asoc.asconf_supported == 1) && 31038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) { 31048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF 31058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 31068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, 31078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination); 31088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 31098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf(stcb, stcb->asoc.primary_destination, 31108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_NOT_LOCKED); 31118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 31128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenclosed_socket: 31158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Toss the cookie if I can */ 31168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_toss_old_cookies(stcb, asoc); 31178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&asoc->sent_queue)) { 31188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Restart the timer if we have pending data */ 31198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 31208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk = TAILQ_FIRST(&asoc->sent_queue); 31228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 31238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 31258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 31278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_ecn_echo(struct sctp_ecne_chunk *cp, 31288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb) 31298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 31308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 31318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *lchk; 31328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ecne_chunk bkup; 3133b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen uint8_t override_bit; 31348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t tsn, window_data_tsn; 31358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int len; 31368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int pkt_cnt; 3137b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen 31388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen len = ntohs(cp->ch.chunk_length); 31398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((len != sizeof(struct sctp_ecne_chunk)) && 31408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (len != sizeof(struct old_sctp_ecne_chunk))) { 31418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 31428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (len == sizeof(struct old_sctp_ecne_chunk)) { 31448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its the old format */ 31458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&bkup, cp, sizeof(struct old_sctp_ecne_chunk)); 31468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bkup.num_pkts_since_cwr = htonl(1); 31478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cp = &bkup; 31488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvecne); 31508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsn = ntohl(cp->tsn); 31518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen pkt_cnt = ntohl(cp->num_pkts_since_cwr); 31528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lchk = TAILQ_LAST(&stcb->asoc.send_queue, sctpchunk_listhead); 31538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lchk == NULL) { 31548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen window_data_tsn = stcb->asoc.sending_seq - 1; 31558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 31568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen window_data_tsn = lchk->rec.data.TSN_seq; 31578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Find where it was sent to if possible. */ 31608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net = NULL; 31618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) { 31628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lchk->rec.data.TSN_seq == tsn) { 31638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net = lchk->whoTo; 31648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send; 31658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 31668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) { 31688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 31698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == NULL) { 317232a191a90b5c914a02047389c5b3197e08fc9841tuexen /* 31738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * What to do. A previous send of a 31748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CWR was possibly lost. See how old it is, we 31758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * may have it marked on the actual net. 31768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 31778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 31788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tsn == net->last_cwr_tsn) { 31798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Found him, send it off */ 3180b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen break; 31818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3183b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (net == NULL) { 318432a191a90b5c914a02047389c5b3197e08fc9841tuexen /* 3185b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen * If we reach here, we need to send a special 3186b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen * CWR that says hey, we did this a long time 3187b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen * ago and you lost the response. 3188b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen */ 3189b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen net = TAILQ_FIRST(&stcb->asoc.nets); 3190b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (net == NULL) { 3191b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen /* TSNH */ 3192b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return; 3193b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } 3194b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen override_bit = SCTP_CWR_REDUCE_OVERRIDE; 3195b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } else { 3196b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen override_bit = 0; 3197b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } 3198b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } else { 3199b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen override_bit = 0; 32008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) && 32028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((override_bit&SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 32038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* JRS - Use the congestion control given in the pluggable CC module */ 32048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt); 32058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 32068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We reduce once every RTT. So we will only lower cwnd at 32078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the next sending seq i.e. the window_data_tsn 32088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->cwr_window_tsn = window_data_tsn; 32108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ecn_ce_pkt_cnt += pkt_cnt; 32118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->lost_cnt = pkt_cnt; 32128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->last_cwr_tsn = tsn; 32138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 32148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen override_bit |= SCTP_CWR_IN_SAME_WINDOW; 32158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tsn, net->last_cwr_tsn) && 32168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((override_bit&SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 32178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 32188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Another loss in the same window update how 32198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * many marks/packets lost we have had. 32208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int cnt = 1; 32228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (pkt_cnt > net->lost_cnt) { 32238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Should be the case */ 32248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt = (pkt_cnt - net->lost_cnt); 32258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ecn_ce_pkt_cnt += cnt; 32268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->lost_cnt = pkt_cnt; 32288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->last_cwr_tsn = tsn; 32298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 32308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Most CC functions will ignore this call, since we are in-window 32318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * yet of the initial CE the peer saw. 32328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 1, cnt); 32348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 32378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We always send a CWR this way if our previous one was lost our 32388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * peer will get an update, or if it is not time again to reduce we 32398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * still get the cwr to the peer. Note we set the override when we 32408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * could not find the TSN on the chunk or the destination network. 32418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_cwr(stcb, net, net->last_cwr_tsn, override_bit); 32438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 32448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 32468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net) 32478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 32488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 32498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Here we get a CWR from the peer. We must look in the outqueue and 3250f405d7f07b0213ec54f2055f8bdc6185c836870ct * make sure that we have a covered ECNE in the control chunk part. 32518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If so remove it. 32528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 32548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ecne_chunk *ecne; 32558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int override; 32568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t cwr_tsn; 32578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cwr_tsn = ntohl(cp->tsn); 32588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE; 32608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 32618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) { 32628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 32638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((override == 0) && (chk->whoTo != net)) { 32658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Must be from the right src unless override is set */ 32668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 32678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ecne = mtod(chk->data, struct sctp_ecne_chunk *); 32698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GE(cwr_tsn, ntohl(ecne->tsn))) { 32708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* this covers this ECNE, we can remove it */ 32718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.ecn_echo_cnt_onq--; 32728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk, 32738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_next); 32748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 32758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 32768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 32778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.ctrl_queue_cnt--; 32798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 32808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (override == 0) { 32818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 32828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 32868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 32880ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSED, 32898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, struct sctp_nets *net) 32908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 32918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 32920612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 32938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 32948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 32958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 32978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n"); 32988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) 32998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 33008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 33028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process according to association state */ 33038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) { 33048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* unexpected SHUTDOWN-COMPLETE... so ignore... */ 33058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 33068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_handle_shutdown_complete: not in SCTP_STATE_SHUTDOWN_ACK_SENT --- ignore\n"); 33078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 33088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 33098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* notify upper layer protocol */ 33118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_socket) { 33128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 33138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 331497e4568a3ba270aaad30d8713c38235a1d8fa518t#ifdef INVARIANTS 331597e4568a3ba270aaad30d8713c38235a1d8fa518t if (!TAILQ_EMPTY(&asoc->send_queue) || 331697e4568a3ba270aaad30d8713c38235a1d8fa518t !TAILQ_EMPTY(&asoc->sent_queue) || 331797e4568a3ba270aaad30d8713c38235a1d8fa518t !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 331897e4568a3ba270aaad30d8713c38235a1d8fa518t panic("Queues are not empty when handling SHUTDOWN-COMPLETE"); 331997e4568a3ba270aaad30d8713c38235a1d8fa518t } 332097e4568a3ba270aaad30d8713c38235a1d8fa518t#endif 33218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* stop the timer */ 33228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_22); 33238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 33248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the TCB */ 33258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, 33268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "sctp_handle_shutdown_complete: calls free-asoc\n"); 33270612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 33288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(stcb->sctp_ep); 33298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 33308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 33318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 33328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 33338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 33348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_23); 33360612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 33378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 33388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 33408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 33418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 33438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenprocess_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, 33448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, uint8_t flg) 33458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 33468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (desc->chunk_type) { 33478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_DATA: 33488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* find the tsn to resend (possibly */ 33498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 33508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t tsn; 33518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *tp1; 33528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsn = ntohl(desc->tsn_ifany); 33548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 33558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.TSN_seq == tsn) { 33568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 33578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 33588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, tsn)) { 33608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not found */ 33618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1 = NULL; 33628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 33638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1 == NULL) { 33668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 33678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Do it the other way , aka without paying 33688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * attention to queue seq order. 33698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 33708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpdnfnd); 33718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 33728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->rec.data.TSN_seq == tsn) { 33738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 33748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 33758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1 == NULL) { 33798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrptsnnf); 33808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((tp1) && (tp1->sent < SCTP_DATAGRAM_ACKED)) { 33828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t *ddp; 33838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((flg & SCTP_BADCRC) == 0) && 33858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 33868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 33878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.peers_rwnd == 0) && 33898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 33908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpdiwnp); 33918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 33928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.peers_rwnd == 0 && 33948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (flg & SCTP_FROM_MIDDLE_BOX)) { 33958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpdizrw); 33968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 33978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3398b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen ddp = (uint8_t *) (mtod(tp1->data, caddr_t) + 33998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_data_chunk)); 34008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 34018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int iii; 34028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (iii = 0; iii < sizeof(desc->data_bytes); 34048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen iii++) { 34058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ddp[iii] != desc->data_bytes[iii]) { 34068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpbadd); 34078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 34088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->do_rtt) { 34138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 34148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this guy had a RTO calculation 34158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * pending on it, cancel it 34168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->whoTo->rto_needed == 0) { 34188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->rto_needed = 1; 34198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->do_rtt = 0; 34218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpmark); 34238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent != SCTP_DATAGRAM_RESEND) 34248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 34258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 34268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * mark it as if we were doing a FR, since 34278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we will be getting gap ack reports behind 34288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the info from the router. 34298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.doing_fast_retransmit = 1; 34318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 34328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * mark the tsn with what sequences can 34338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cause a new FR. 34348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { 34368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; 34378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 34388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq; 34398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* restart the timer */ 34428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 34438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, tp1->whoTo, SCTP_FROM_SCTP_INPUT+SCTP_LOC_24); 34448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 34458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, tp1->whoTo); 34468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* fix counts and things */ 34488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 34498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP, 34508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->whoTo->flight_size, 34518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->book_size, 34528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uintptr_t)stcb, 34538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->rec.data.TSN_seq); 34548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent < SCTP_DATAGRAM_RESEND) { 34568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_flight_size_decrease(tp1); 34578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_total_flight_decrease(stcb, tp1); 34588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tp1->sent = SCTP_DATAGRAM_RESEND; 34608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } { 34618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* audit code */ 34628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int audit; 34638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen audit = 0; 34658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 34668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_RESEND) 34678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen audit++; 34688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(tp1, &stcb->asoc.control_send_queue, 34708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_next) { 34718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tp1->sent == SCTP_DATAGRAM_RESEND) 34728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen audit++; 34738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (audit != stcb->asoc.sent_queue_retran_cnt) { 34758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("**Local Audit finds cnt:%d asoc cnt:%d\n", 34768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen audit, stcb->asoc.sent_queue_retran_cnt); 34778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef SCTP_AUDITING_ENABLED 34788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.sent_queue_retran_cnt = audit; 34798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 34808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 34848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ASCONF: 34858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 34868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *asconf; 34878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue, 34898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_next) { 34908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asconf->rec.chunk_id.id == SCTP_ASCONF) { 34918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 34928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asconf) { 34958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asconf->sent != SCTP_DATAGRAM_RESEND) 34968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 34978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf->sent = SCTP_DATAGRAM_RESEND; 34988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf->snd_count--; 34998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_INITIATION: 35038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* resend the INIT */ 35048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.dropped_special_cnt++; 35058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.dropped_special_cnt < SCTP_RETRY_DROPPED_THRESH) { 35068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 35078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If we can get it in, in a few attempts we do 35088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this, otherwise we let the timer fire. 35098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 35108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, 35118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_25); 35128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 35138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SELECTIVE_ACK: 35168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_NR_SELECTIVE_ACK: 35178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* resend the sack */ 35188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 35198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_HEARTBEAT_REQUEST: 35218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* resend a demand HB */ 35228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.overall_error_count + 3) < stcb->asoc.max_send_times) { 35238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Only retransmit if we KNOW we wont destroy the tcb */ 35248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 35258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SHUTDOWN: 35288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_shutdown(stcb, net); 35298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SHUTDOWN_ACK: 35318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_shutdown_ack(stcb, net); 35328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_COOKIE_ECHO: 35348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 35358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *cookie; 35368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie = NULL; 35388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, 35398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_next) { 35408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) { 35418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cookie) { 35458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cookie->sent != SCTP_DATAGRAM_RESEND) 35468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 35478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cookie->sent = SCTP_DATAGRAM_RESEND; 35488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_stop_all_cookie_timers(stcb); 35498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_COOKIE_ACK: 35538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_cookie_ack(stcb); 35548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ASCONF_ACK: 35568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* resend last asconf ack */ 35578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf_ack(stcb); 35588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_FORWARD_CUM_TSN: 35608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_forward_tsn(stcb, &stcb->asoc); 35618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* can't do anything with these */ 35638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_PACKET_DROPPED: 35648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_INITIATION_ACK: /* this should not happen */ 35658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_HEARTBEAT_ACK: 35668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ABORT_ASSOCIATION: 35678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_OPERATION_ERROR: 35688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SHUTDOWN_COMPLETE: 35698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ECN_ECHO: 35708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ECN_CWR: 35718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 35728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 35738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 35758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 35768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 3578b6a8c974796d76c59ef64a7555e446c9cd171877tsctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *list) 35798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3580c1f5477d96c0c5178c74caad234035e534c37bdct uint32_t i; 35818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t temp; 35828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 35848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We set things to 0xffff since this is the last delivered sequence 35858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and we will be sending in 0 after the reset. 35868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 35878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (number_entries) { 35898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < number_entries; i++) { 35908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen temp = ntohs(list[i]); 35918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (temp >= stcb->asoc.streamincnt) { 35928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 35938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmin[temp].last_sequence_delivered = 0xffff; 35958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 35978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen list = NULL; 35988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < stcb->asoc.streamincnt; i++) { 35998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 36008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 36038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 36048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 3606b6a8c974796d76c59ef64a7555e446c9cd171877tsctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *list) 36078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3608b6a8c974796d76c59ef64a7555e446c9cd171877t uint32_t i; 3609b6a8c974796d76c59ef64a7555e446c9cd171877t uint16_t temp; 36108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3611b6a8c974796d76c59ef64a7555e446c9cd171877t if (number_entries > 0) { 36128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < number_entries; i++) { 36138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen temp = ntohs(list[i]); 36148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (temp >= stcb->asoc.streamoutcnt) { 36158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no such stream */ 36168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 36178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3618e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t stcb->asoc.strmout[temp].next_sequence_send = 0; 3619b6a8c974796d76c59ef64a7555e446c9cd171877t } 3620b6a8c974796d76c59ef64a7555e446c9cd171877t } else { 3621b6a8c974796d76c59ef64a7555e446c9cd171877t for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 3622b6a8c974796d76c59ef64a7555e446c9cd171877t stcb->asoc.strmout[i].next_sequence_send = 0; 36238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 36268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 36278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_stream_reset_out_request * 36308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk) 36318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 36328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 363324feb751a6f488d36918e2f333dc2be853c259c8t struct sctp_chunkhdr *ch; 36348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_out_request *r; 36358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 36368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int len, clen; 36378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 36398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 36408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_reset_outstanding = 0; 36418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 36428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.str_reset == NULL) { 36448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_reset_outstanding = 0; 36458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 36468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk = stcb->asoc.str_reset; 36488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data == NULL) { 36498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 36508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (bchk) { 36528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* he wants a copy of the chk pointer */ 36538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *bchk = chk; 36548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen clen = chk->send_size; 365624feb751a6f488d36918e2f333dc2be853c259c8t ch = mtod(chk->data, struct sctp_chunkhdr *); 365724feb751a6f488d36918e2f333dc2be853c259c8t r = (struct sctp_stream_reset_out_request *)(ch + 1); 36588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohl(r->request_seq) == seq) { 36598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 36608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (r); 36618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen len = SCTP_SIZE32(ntohs(r->ph.param_length)); 36638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (clen > (len + (int)sizeof(struct sctp_chunkhdr))) { 36648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* move to the next one, there can only be a max of two */ 36658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen r = (struct sctp_stream_reset_out_request *)((caddr_t)r + len); 36668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohl(r->request_seq) == seq) { 36678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (r); 36688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* that seq is not here */ 36718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 36728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 36738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 36758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_clean_up_stream_reset(struct sctp_tcb *stcb) 36768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 36778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 36788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk = stcb->asoc.str_reset; 36798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.str_reset == NULL) { 36818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 36828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 36848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT+SCTP_LOC_26); 36868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->control_send_queue, 36878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk, 36888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_next); 36898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 36908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 36918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 36928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->ctrl_queue_cnt--; 36948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 36958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NO_NULL_CHK*/ 36968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.str_reset = NULL; 36978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 36988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 37008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 37018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_stream_reset_response(struct sctp_tcb *stcb, 3702c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen uint32_t seq, uint32_t action, 3703c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen struct sctp_stream_reset_response *respin) 37048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 37058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t type; 37068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int lparm_len; 37078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc = &stcb->asoc; 37088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 37098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_out_request *srparam; 3710b6a8c974796d76c59ef64a7555e446c9cd171877t uint32_t number_entries; 37118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 37128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->stream_reset_outstanding == 0) { 37138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* duplicate */ 37148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 37158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (seq == stcb->asoc.str_reset_seq_out) { 37178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen srparam = sctp_find_stream_reset(stcb, seq, &chk); 37188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (srparam) { 37198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.str_reset_seq_out++; 37208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen type = ntohs(srparam->ph.param_type); 37218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lparm_len = ntohs(srparam->ph.param_length); 37228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (type == SCTP_STR_RESET_OUT_REQUEST) { 37238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t); 37248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_reset_out_is_outstanding = 0; 37258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->stream_reset_outstanding) 37268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_reset_outstanding--; 372737d37f01a7cf8a44de69d2e65e02191552a3894ctuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 37288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* do it */ 37298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_reset_out_streams(stcb, number_entries, srparam->list_of_streams); 3730cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3731cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 37328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 37338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 37348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (type == SCTP_STR_RESET_IN_REQUEST) { 37368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Answered my request */ 37378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t); 37388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->stream_reset_outstanding) 37398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_reset_outstanding--; 3740cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3741cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_IN, stcb, 3742cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 3743cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 374432a191a90b5c914a02047389c5b3197e08fc9841tuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb, 3745c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 3746c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } 3747c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else if (type == SCTP_STR_RESET_ADD_OUT_STREAMS) { 3748c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen /* Ok we now may have more streams */ 3749c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen int num_stream; 3750c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen 3751c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen num_stream = stcb->asoc.strm_pending_add_size; 3752c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen if (num_stream > (stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt)) { 3753c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen /* TSNH */ 3754c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen num_stream = stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt; 3755c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } 3756c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen stcb->asoc.strm_pending_add_size = 0; 3757c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen if (asoc->stream_reset_outstanding) 3758c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen asoc->stream_reset_outstanding--; 375937d37f01a7cf8a44de69d2e65e02191552a3894ctuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3760c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen /* Put the new streams into effect */ 3761c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen stcb->asoc.streamoutcnt += num_stream; 3762c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 3763cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3764cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3765cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen SCTP_STREAM_CHANGE_DENIED); 3766c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else { 376732a191a90b5c914a02047389c5b3197e08fc9841tuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3768cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen SCTP_STREAM_CHANGE_FAILED); 3769c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } 3770c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else if (type == SCTP_STR_RESET_ADD_IN_STREAMS) { 3771c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen if (asoc->stream_reset_outstanding) 3772c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen asoc->stream_reset_outstanding--; 3773cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3774cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3775cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen SCTP_STREAM_CHANGE_DENIED); 3776cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 377732a191a90b5c914a02047389c5b3197e08fc9841tuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3778cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen SCTP_STREAM_CHANGE_FAILED); 37798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (type == SCTP_STR_RESET_TSN_REQUEST) { 37818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /** 37828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) Adopt the new in tsn. 37838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * b) reset the map 37848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * c) Adopt the new out-tsn 37858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 37868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_response_tsn *resp; 37878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_forward_tsn_chunk fwdtsn; 37888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int abort_flag = 0; 37898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (respin == NULL) { 37908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* huh ? */ 37918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 37928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 379337d37f01a7cf8a44de69d2e65e02191552a3894ctuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 37948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen resp = (struct sctp_stream_reset_response_tsn *)respin; 37958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_reset_outstanding--; 37968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 37978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 37988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fwdtsn.new_cumulative_tsn = htonl(ntohl(resp->senders_next_tsn) - 1); 37998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 38008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (abort_flag) { 38018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 38028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.highest_tsn_inside_map = (ntohl(resp->senders_next_tsn) - 1); 38048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 3805c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_log_map(0, 7, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 38068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map; 38098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn); 38108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); 381132a191a90b5c914a02047389c5b3197e08fc9841tuexen 38128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; 38138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size); 381432a191a90b5c914a02047389c5b3197e08fc9841tuexen 38158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn); 38168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn; 38178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 38198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 3820cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 0); 3821cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3822cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 3823cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen SCTP_ASSOC_RESET_DENIED); 3824c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else { 3825cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 3826cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen SCTP_ASSOC_RESET_FAILED); 38278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get rid of the request and get the request flags */ 38308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->stream_reset_outstanding == 0) { 38318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_clean_up_stream_reset(stcb); 38328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 38368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 38378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 38398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_str_reset_request_in(struct sctp_tcb *stcb, 38408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, 38418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_in_request *req, int trunc) 38428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 38438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t seq; 38448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int len, i; 38458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int number_entries; 38468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t temp; 38478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 38498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * peer wants me to send a str-reset to him for my outgoing seq's if 38508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * seq_in is right. 38518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 38528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc = &stcb->asoc; 38538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen seq = ntohl(req->request_seq); 38558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->str_reset_seq_in == seq) { 385637d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[1] = asoc->last_reset_action[0]; 385737d37f01a7cf8a44de69d2e65e02191552a3894ctuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 385837d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 385937d37f01a7cf8a44de69d2e65e02191552a3894ctuexen } else if (trunc) { 38608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't do it, since they exceeded our buffer size */ 386137d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 38628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (stcb->asoc.stream_reset_out_is_outstanding == 0) { 38638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen len = ntohs(req->ph.param_length); 38648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t)); 38658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < number_entries; i++) { 38668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen temp = ntohs(req->list_of_streams[i]); 38678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen req->list_of_streams[i] = temp; 38688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 386937d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 38708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams, 38718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_reset_seq_out, 38728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen seq, (asoc->sending_seq - 1)); 38738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->stream_reset_out_is_outstanding = 1; 38748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_reset = chk; 38758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); 38768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.stream_reset_outstanding++; 38778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 38788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't do it, since we have sent one out */ 387937d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 38808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3881c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 38828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_reset_seq_in++; 38838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (asoc->str_reset_seq_in - 1 == seq) { 38848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 38858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (asoc->str_reset_seq_in - 2 == seq) { 38868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 38878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 388837d37f01a7cf8a44de69d2e65e02191552a3894ctuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 38898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 38918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 38938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb, 38948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, 38958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_tsn_request *req) 38968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 38978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* reset all in and out and update the tsn */ 38988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 38998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * A) reset my str-seq's on in and out. B) Select a receive next, 39008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and set cum-ack to it. Also process this selected number as a 39018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * fwd-tsn as well. C) set in the response my next sending seq. 39028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 39038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_forward_tsn_chunk fwdtsn; 39048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc = &stcb->asoc; 39058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int abort_flag = 0; 39068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t seq; 39078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen seq = ntohl(req->request_seq); 39098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->str_reset_seq_in == seq) { 391047674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->last_reset_action[1] = stcb->asoc.last_reset_action[0]; 391137d37f01a7cf8a44de69d2e65e02191552a3894ctuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 391237d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 391347674b651417d493ff4e0318113fd7beeef119dbtuexen } else { 391447674b651417d493ff4e0318113fd7beeef119dbtuexen fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 391547674b651417d493ff4e0318113fd7beeef119dbtuexen fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 391647674b651417d493ff4e0318113fd7beeef119dbtuexen fwdtsn.ch.chunk_flags = 0; 391747674b651417d493ff4e0318113fd7beeef119dbtuexen fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1); 391847674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 391947674b651417d493ff4e0318113fd7beeef119dbtuexen if (abort_flag) { 392047674b651417d493ff4e0318113fd7beeef119dbtuexen return (1); 392147674b651417d493ff4e0318113fd7beeef119dbtuexen } 392247674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA; 392347674b651417d493ff4e0318113fd7beeef119dbtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 392447674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 392547674b651417d493ff4e0318113fd7beeef119dbtuexen } 392647674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->highest_tsn_inside_map; 392747674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->mapping_array_base_tsn = asoc->highest_tsn_inside_map + 1; 392847674b651417d493ff4e0318113fd7beeef119dbtuexen memset(asoc->mapping_array, 0, asoc->mapping_array_size); 392947674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 393047674b651417d493ff4e0318113fd7beeef119dbtuexen memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); 393147674b651417d493ff4e0318113fd7beeef119dbtuexen atomic_add_int(&asoc->sending_seq, 1); 393247674b651417d493ff4e0318113fd7beeef119dbtuexen /* save off historical data for retrans */ 393347674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->last_sending_seq[1] = asoc->last_sending_seq[0]; 393447674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->last_sending_seq[0] = asoc->sending_seq; 393547674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->last_base_tsnsent[1] = asoc->last_base_tsnsent[0]; 393647674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->last_base_tsnsent[0] = asoc->mapping_array_base_tsn; 393747674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 393847674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 393947674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 394047674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_notify_stream_reset_tsn(stcb, asoc->sending_seq, (asoc->mapping_array_base_tsn + 1), 0); 394147674b651417d493ff4e0318113fd7beeef119dbtuexen } 394247674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 394347674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 39448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_reset_seq_in++; 39458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (asoc->str_reset_seq_in - 1 == seq) { 39468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 394747674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 39488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (asoc->str_reset_seq_in - 2 == seq) { 39498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[1], 395047674b651417d493ff4e0318113fd7beeef119dbtuexen asoc->last_sending_seq[1], asoc->last_base_tsnsent[1]); 39518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 395237d37f01a7cf8a44de69d2e65e02191552a3894ctuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 39538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 39558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 39568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 39588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_str_reset_request_out(struct sctp_tcb *stcb, 39598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, 39608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_out_request *req, int trunc) 39618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 39628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t seq, tsn; 39638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int number_entries, len; 39648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc = &stcb->asoc; 39658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen seq = ntohl(req->request_seq); 39678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now if its not a duplicate we process it */ 39698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->str_reset_seq_in == seq) { 39708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen len = ntohs(req->ph.param_length); 39718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen number_entries = ((len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t)); 39728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 39738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the sender is resetting, handle the list issue.. we must 39748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) verify if we can do the reset, if so no problem b) If 39758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we can't do the reset we must copy the request. c) queue 39768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it, and setup the data in processor to trigger it off 39778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * when needed and dequeue all the queued data. 39788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 39798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tsn = ntohl(req->send_reset_at_tsn); 39808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* move the reset action back one */ 39828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_reset_action[1] = asoc->last_reset_action[0]; 398337d37f01a7cf8a44de69d2e65e02191552a3894ctuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 398437d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 398537d37f01a7cf8a44de69d2e65e02191552a3894ctuexen } else if (trunc) { 398637d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 39878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) { 39888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we can do it now */ 39898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_reset_in_stream(stcb, number_entries, req->list_of_streams); 399037d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 39918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 39928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 39938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we must queue it up and thus wait for the TSN's 39948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to arrive that are at or before tsn 39958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 39968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_list *liste; 39978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int siz; 39988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen siz = sizeof(struct sctp_stream_reset_list) + (number_entries * sizeof(uint16_t)); 40008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(liste, struct sctp_stream_reset_list *, 40018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen siz, SCTP_M_STRESET); 40028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (liste == NULL) { 40038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* gak out of memory */ 400437d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 400537d37f01a7cf8a44de69d2e65e02191552a3894ctuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 40068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 40078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen liste->tsn = tsn; 40098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen liste->number_entries = number_entries; 4010c1f5477d96c0c5178c74caad234035e534c37bdct memcpy(&liste->list_of_streams, req->list_of_streams, number_entries * sizeof(uint16_t)); 40118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp); 401237d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 40138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4014c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 40158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->str_reset_seq_in++; 40168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((asoc->str_reset_seq_in - 1) == seq) { 40178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 40188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one seq back, just echo back last action since my 40198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * response was lost. 40208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 40218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 40228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((asoc->str_reset_seq_in - 2) == seq) { 40238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 40248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * two seq back, just echo back last action since my 40258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * response was lost. 40268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 40278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 40288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 402937d37f01a7cf8a44de69d2e65e02191552a3894ctuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 40308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 40328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 40338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 40348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 4035c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen struct sctp_stream_reset_add_strm *str_add) 40368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 403737d37f01a7cf8a44de69d2e65e02191552a3894ctuexen /* 403837d37f01a7cf8a44de69d2e65e02191552a3894ctuexen * Peer is requesting to add more streams. 403937d37f01a7cf8a44de69d2e65e02191552a3894ctuexen * If its within our max-streams we will 404037d37f01a7cf8a44de69d2e65e02191552a3894ctuexen * allow it. 404137d37f01a7cf8a44de69d2e65e02191552a3894ctuexen */ 4042c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen uint32_t num_stream, i; 40438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t seq; 40448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc = &stcb->asoc; 40458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *ctl, *nctl; 40468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 40478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Get the number. */ 40488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen seq = ntohl(str_add->request_seq); 40498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_stream = ntohs(str_add->number_of_streams); 40508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now what would be the new total? */ 40518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->str_reset_seq_in == seq) { 40528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_stream += stcb->asoc.streamincnt; 405337d37f01a7cf8a44de69d2e65e02191552a3894ctuexen stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 405437d37f01a7cf8a44de69d2e65e02191552a3894ctuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 405537d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 405637d37f01a7cf8a44de69d2e65e02191552a3894ctuexen } else if ((num_stream > stcb->asoc.max_inbound_streams) || 4057b6a8c974796d76c59ef64a7555e446c9cd171877t (num_stream > 0xffff)) { 40588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We must reject it they ask for to many */ 40598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen denied: 406037d37f01a7cf8a44de69d2e65e02191552a3894ctuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 40618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 40628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Ok, we can do that :-) */ 40638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_in *oldstrm; 40648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 40658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* save off the old */ 40668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen oldstrm = stcb->asoc.strmin; 40678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(stcb->asoc.strmin, struct sctp_stream_in *, 40688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (num_stream * sizeof(struct sctp_stream_in)), 40698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_STRMI); 40708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.strmin == NULL) { 40718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmin = oldstrm; 40728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto denied; 40738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* copy off the old data */ 40758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < stcb->asoc.streamincnt; i++) { 40768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 40778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmin[i].stream_no = i; 40788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered; 40798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started; 40808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now anything on those queues? */ 40818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) { 40828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next); 40838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next); 40848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Init the new streams */ 40878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = stcb->asoc.streamincnt; i < num_stream; i++) { 40888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 40898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmin[i].stream_no = i; 40908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 40918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strmin[i].delivery_started = 0; 40928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(oldstrm, SCTP_M_STRMI); 40948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update the size */ 40958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.streamincnt = num_stream; 409637d37f01a7cf8a44de69d2e65e02191552a3894ctuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 4097c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 40988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4099c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 4100c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen asoc->str_reset_seq_in++; 41018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((asoc->str_reset_seq_in - 1) == seq) { 41028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 41038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one seq back, just echo back last action since my 41048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * response was lost. 41058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 41068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 41078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((asoc->str_reset_seq_in - 2) == seq) { 41088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 41098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * two seq back, just echo back last action since my 41108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * response was lost. 41118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 41128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 41138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 411437d37f01a7cf8a44de69d2e65e02191552a3894ctuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 41158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 41168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 41188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4119c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexenstatic void 4120c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexensctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 4121c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen struct sctp_stream_reset_add_strm *str_add) 4122c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen{ 412337d37f01a7cf8a44de69d2e65e02191552a3894ctuexen /* 412437d37f01a7cf8a44de69d2e65e02191552a3894ctuexen * Peer is requesting to add more streams. 412537d37f01a7cf8a44de69d2e65e02191552a3894ctuexen * If its within our max-streams we will 412637d37f01a7cf8a44de69d2e65e02191552a3894ctuexen * allow it. 412737d37f01a7cf8a44de69d2e65e02191552a3894ctuexen */ 4128c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen uint16_t num_stream; 4129c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen uint32_t seq; 4130c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen struct sctp_association *asoc = &stcb->asoc; 4131c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen 4132c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen /* Get the number. */ 4133c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen seq = ntohl(str_add->request_seq); 4134c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen num_stream = ntohs(str_add->number_of_streams); 4135c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen /* Now what would be the new total? */ 4136c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen if (asoc->str_reset_seq_in == seq) { 413737d37f01a7cf8a44de69d2e65e02191552a3894ctuexen stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 413837d37f01a7cf8a44de69d2e65e02191552a3894ctuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 413937d37f01a7cf8a44de69d2e65e02191552a3894ctuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 414037d37f01a7cf8a44de69d2e65e02191552a3894ctuexen } else if (stcb->asoc.stream_reset_outstanding) { 4141c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen /* We must reject it we have something pending */ 414237d37f01a7cf8a44de69d2e65e02191552a3894ctuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 4143c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else { 4144c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen /* Ok, we can do that :-) */ 4145c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen int mychk; 4146c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen mychk = stcb->asoc.streamoutcnt; 4147c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen mychk += num_stream; 4148c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen if (mychk < 0x10000) { 414937d37f01a7cf8a44de69d2e65e02191552a3894ctuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 4150c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) { 415137d37f01a7cf8a44de69d2e65e02191552a3894ctuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4152c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } 4153c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else { 415437d37f01a7cf8a44de69d2e65e02191552a3894ctuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4155c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } 4156c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } 4157c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_add_stream_reset_result(chk, seq, stcb->asoc.last_reset_action[0]); 4158c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen asoc->str_reset_seq_in++; 4159c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else if ((asoc->str_reset_seq_in - 1) == seq) { 4160c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen /* 4161c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen * one seq back, just echo back last action since my 4162c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen * response was lost. 4163c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen */ 4164c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 4165c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else if ((asoc->str_reset_seq_in - 2) == seq) { 4166c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen /* 4167c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen * two seq back, just echo back last action since my 4168c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen * response was lost. 4169c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen */ 4170c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 4171c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else { 417237d37f01a7cf8a44de69d2e65e02191552a3894ctuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 4173c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } 4174c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen} 4175c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen 41768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__Panda__) 41778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __GNUC__ 41788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen__attribute__ ((noinline)) 41798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 41808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 41818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int 41828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset, 418324feb751a6f488d36918e2f333dc2be853c259c8t struct sctp_chunkhdr *ch_req) 41848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 41858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int chk_length, param_len, ptype; 41868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr pstore; 41878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE]; 418837d37f01a7cf8a44de69d2e65e02191552a3894ctuexen uint32_t seq = 0; 41898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int num_req = 0; 4190b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int trunc = 0; 41918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 41928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_chunkhdr *ch; 41938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *ph; 41948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int ret_code = 0; 41958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int num_param = 0; 41968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 41978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now it may be a reset or a reset-response */ 419824feb751a6f488d36918e2f333dc2be853c259c8t chk_length = ntohs(ch_req->chunk_length); 41998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* setup for adding the response */ 42018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_alloc_a_chunk(stcb, chk); 42028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk == NULL) { 42038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ret_code); 42048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.chunk_id.id = SCTP_STREAM_RESET; 42068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->rec.chunk_id.can_take_data = 0; 42078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->asoc = &stcb->asoc; 42088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->no_fr_allowed = 0; 42098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr); 42108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->book_size_scale = 0; 421168beeca578347438d9c434680197647ed551935ft chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 42128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data == NULL) { 42138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strres_nochunk: 42148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 42158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 42168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 42178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 42198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ret_code); 42208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); 42228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* setup chunk parameters */ 42248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->sent = SCTP_DATAGRAM_UNSENT; 42258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->snd_count = 0; 42268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo = NULL; 42278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = mtod(chk->data, struct sctp_chunkhdr *); 42298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch->chunk_type = SCTP_STREAM_RESET; 42308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch->chunk_flags = 0; 42318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch->chunk_length = htons(chk->send_size); 42328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size); 42338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += sizeof(struct sctp_chunkhdr); 42348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while ((size_t)chk_length >= sizeof(struct sctp_stream_reset_tsn_request)) { 42358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(pstore), (uint8_t *)&pstore); 42368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ph == NULL) 42378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 42388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen param_len = ntohs(ph->param_length); 42398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_len < (int)sizeof(struct sctp_stream_reset_tsn_request)) { 42408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* bad param */ 42418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 42428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, (int)sizeof(cstore)), 42448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (uint8_t *)&cstore); 42458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ptype = ntohs(ph->param_type); 42468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_param++; 42478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (param_len > (int)sizeof(cstore)) { 42488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen trunc = 1; 42498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 42508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen trunc = 0; 42518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (num_param > SCTP_MAX_RESET_PARAMS) { 42538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* hit the max of parameters already sorry.. */ 42548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 42558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ptype == SCTP_STR_RESET_OUT_REQUEST) { 42578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_out_request *req_out; 42588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen req_out = (struct sctp_stream_reset_out_request *)ph; 42598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_req++; 42608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.stream_reset_outstanding) { 42618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen seq = ntohl(req_out->response_seq); 42628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (seq == stcb->asoc.str_reset_seq_out) { 42638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* implicit ack */ 426437d37f01a7cf8a44de69d2e65e02191552a3894ctuexen (void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL); 42658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc); 4268c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) { 4269c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen struct sctp_stream_reset_add_strm *str_add; 4270c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen str_add = (struct sctp_stream_reset_add_strm *)ph; 4271c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen num_req++; 4272c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_handle_str_reset_add_strm(stcb, chk, str_add); 4273c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen } else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) { 4274c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen struct sctp_stream_reset_add_strm *str_add; 4275c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen str_add = (struct sctp_stream_reset_add_strm *)ph; 4276c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen num_req++; 4277c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_handle_str_reset_add_out_strm(stcb, chk, str_add); 42788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_STR_RESET_IN_REQUEST) { 42798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_in_request *req_in; 42808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_req++; 42818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen req_in = (struct sctp_stream_reset_in_request *)ph; 42828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_str_reset_request_in(stcb, chk, req_in, trunc); 42838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_STR_RESET_TSN_REQUEST) { 42848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_tsn_request *req_tsn; 42858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_req++; 42868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen req_tsn = (struct sctp_stream_reset_tsn_request *)ph; 42878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_handle_str_reset_request_tsn(stcb, chk, req_tsn)) { 42888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ret_code = 1; 42898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto strres_nochunk; 42908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no more */ 42928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 42938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_STR_RESET_RESPONSE) { 42948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_response *resp; 42958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t result; 42968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen resp = (struct sctp_stream_reset_response *)ph; 42978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen seq = ntohl(resp->response_seq); 42988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen result = ntohl(resp->result); 42998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_handle_stream_reset_response(stcb, seq, result, resp)) { 43008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ret_code = 1; 43018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto strres_nochunk; 43028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 43048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 43058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += SCTP_SIZE32(param_len); 43078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk_length -= SCTP_SIZE32(param_len); 43088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (num_req == 0) { 43108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we have no response free the stuff */ 43118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto strres_nochunk; 43128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ok we have a chunk to link in */ 43148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue, 4315c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen chk, 4316c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen sctp_next); 43178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.ctrl_queue_cnt++; 43188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ret_code); 43198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 43208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 43228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Handle a router or endpoints report of a packet loss, there are two ways 43238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to handle this, either we get the whole packet and must disect it 43248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ourselves (possibly with truncation and or corruption) or it is a summary 43258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * from a middle box that did the disectting for us. 43268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 43278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 43288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp, 43298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t limit) 43308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 43318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t bottle_bw, on_queue; 43328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t trunc_len; 43338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int chlen; 43348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int at; 43358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_chunk_desc desc; 43368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_chunkhdr *ch; 43378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chlen = ntohs(cp->ch.chunk_length); 43398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chlen -= sizeof(struct sctp_pktdrop_chunk); 43408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* XXX possible chlen underflow */ 43418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chlen == 0) { 43428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = NULL; 43438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) 43448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpbwrpt); 43458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 43468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = (struct sctp_chunkhdr *)(cp->data + sizeof(struct sctphdr)); 43478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chlen -= sizeof(struct sctphdr); 43488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* XXX possible chlen underflow */ 43498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&desc, 0, sizeof(desc)); 43508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen trunc_len = (uint16_t) ntohs(cp->trunc_len); 43528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (trunc_len > limit) { 43538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen trunc_len = limit; 43548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now the chunks themselves */ 43578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) { 43588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen desc.chunk_type = ch->chunk_type; 43598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get amount we need to move */ 43608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen at = ntohs(ch->chunk_length); 43618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (at < sizeof(struct sctp_chunkhdr)) { 43628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* corrupt chunk, maybe at the end? */ 43638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpcrupt); 43648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 43658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (trunc_len == 0) { 43678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we are supposed to have all of it */ 43688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (at > chlen) { 43698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* corrupt skip it */ 43708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpcrupt); 43718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 43728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 43748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is there enough of it left ? */ 43758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (desc.chunk_type == SCTP_DATA) { 43768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chlen < (sizeof(struct sctp_data_chunk) + 43778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(desc.data_bytes))) { 43788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 43798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 43818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chlen < sizeof(struct sctp_chunkhdr)) { 43828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 43838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (desc.chunk_type == SCTP_DATA) { 43878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* can we get out the tsn? */ 43888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 43898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpmbda); 43908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chlen >= (sizeof(struct sctp_data_chunk) + sizeof(uint32_t))) { 43928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* yep */ 43938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_data_chunk *dcp; 43948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t *ddp; 43958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int iii; 43968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen dcp = (struct sctp_data_chunk *)ch; 43988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ddp = (uint8_t *) (dcp + 1); 43998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (iii = 0; iii < sizeof(desc.data_bytes); iii++) { 44008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen desc.data_bytes[iii] = ddp[iii]; 44018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen desc.tsn_ifany = dcp->dp.tsn; 44038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 44048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nope we are done. */ 44058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpnedat); 44068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 44078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 44098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 44108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpmbct); 44118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (process_chunk_drop(stcb, &desc, net, cp->ch.chunk_flags)) { 44148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrppdbrk); 44158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 44168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_SIZE32(at) > chlen) { 44188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 44198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chlen -= SCTP_SIZE32(at); 44218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chlen < sizeof(struct sctp_chunkhdr)) { 44228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* done, none left */ 44238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 44248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = (struct sctp_chunkhdr *)((caddr_t)ch + SCTP_SIZE32(at)); 44268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now update any rwnd --- possibly */ 44288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) == 0) { 44298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* From a peer, we get a rwnd report */ 44308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t a_rwnd; 44318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpfehos); 44338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bottle_bw = ntohl(cp->bottle_bw); 44358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen on_queue = ntohl(cp->current_onq); 44368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (bottle_bw && on_queue) { 44378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* a rwnd report is in here */ 44388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (bottle_bw > on_queue) 44398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a_rwnd = bottle_bw - on_queue; 44408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 44418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a_rwnd = 0; 44428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (a_rwnd == 0) 44448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_rwnd = 0; 44458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else { 44468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (a_rwnd > stcb->asoc.total_flight) { 44478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_rwnd = 44488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a_rwnd - stcb->asoc.total_flight; 44498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 44508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_rwnd = 0; 44518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.peers_rwnd < 44538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 44548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* SWS sender side engages */ 44558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_rwnd = 0; 44568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 44608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_pdrpfmbox); 44618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now middle boxes in sat networks get a cwnd bump */ 44648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) && 44658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.sat_t3_loss_recovery == 0) && 44668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.sat_network)) { 44678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 44688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This is debateable but for sat networks it makes sense 44698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Note if a T3 timer has went off, we will prohibit any 44708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * changes to cwnd until we exit the t3 loss recovery. 44718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 44728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped(stcb, 44738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net, cp, &bottle_bw, &on_queue); 44748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 44768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 44788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * handles all control chunks in a packet inputs: - m: mbuf chain, assumed to 44798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * still contain IP/SCTP header - stcb: is the tcb found for this packet - 44808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * offset: offset into the mbuf chain to first chunkhdr - length: is the 44818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * length of the complete packet outputs: - length: modified to remaining 44828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * length after control processing - netp: modified to new sctp_nets after 44838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cookie-echo processing - return NULL to discard the packet (ie. no asoc, 44848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * bad packet,...) otherwise return the tcb for this packet 44858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 44868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__Panda__) 44878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __GNUC__ 44888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen__attribute__ ((noinline)) 44898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 44908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 44918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_tcb * 44928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, 4493e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, 44948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp, 44958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen, 449651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 449751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid, uint32_t mflowid, 449851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 44998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id, uint16_t port) 45008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 45018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 45028f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *op_err; 45038f9e45fea288542b24a6bda01269c6fc184d991at char msg[SCTP_DIAG_INFO_LEN]; 45048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vtag_in; 45058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int num_chunks = 0; /* number of control chunks processed */ 45068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t chk_length; 45078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int ret; 45088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int abort_no_unlock = 0; 45098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int ecne_seen = 0; 45108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 45118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * How big should this be, and should it be alloc'd? Lets try the 45128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * d-mtu-ceiling for now (2k) and that should hopefully work ... 45138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * until we get into jumbo grams and such.. 45148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 45158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t chunk_buf[SCTP_CHUNK_BUFFER_SIZE]; 45168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *locked_tcb = stcb; 45178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int got_auth = 0; 45188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t auth_offset = 0, auth_len = 0; 45198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int auth_skipped = 0; 45208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int asconf_cnt = 0; 45210612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 45228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 45238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 45248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 45258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n", 4526ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t iphlen, *offset, length, (void *)stcb); 45278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 45288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* validate chunk header length... */ 45298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohs(ch->chunk_length) < sizeof(*ch)) { 45308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Invalid header length %d\n", 45318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(ch->chunk_length)); 45328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 45338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 45348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 45368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 45388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * validate the verification tag 45398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 45408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vtag_in = ntohl(sh->v_tag); 45418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 45428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 45438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_ASSERT(locked_tcb); 45448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch->chunk_type == SCTP_INITIATION) { 45468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Its an INIT of len:%d vtag:%x\n", 45478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(ch->chunk_length), vtag_in); 45488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vtag_in != 0) { 45498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* protocol error- silently discard... */ 45508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_badvtag); 45518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 45528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 45538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 45558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ch->chunk_type != SCTP_COOKIE_ECHO) { 45578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 45588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If there is no stcb, skip the AUTH chunk and process 45598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * later after a stcb is found (to validate the lookup was 45608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * valid. 45618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 45628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ch->chunk_type == SCTP_AUTHENTICATION) && 45638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb == NULL) && 4564fb3816eaffe5878bb1286adb120fd160da178a05t (inp->auth_supported == 1)) { 45658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* save this chunk for later processing */ 45668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth_skipped = 1; 45678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth_offset = *offset; 45688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth_len = ntohs(ch->chunk_length); 45698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 45708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* (temporarily) move past this chunk */ 45718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset += SCTP_SIZE32(auth_len); 45728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*offset >= length) { 45738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no more data left in the mbuf chain */ 45748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 45758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 45768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 45778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 45798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 45818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_chunkhdr), chunk_buf); 45828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch == NULL) { 45848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Help */ 45858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 45868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 45878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 45888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 45908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch->chunk_type == SCTP_COOKIE_ECHO) { 45928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto process_control_chunks; 45938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 45958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * first check if it's an ASCONF with an unknown src addr we 45968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * need to look inside to find the association 45978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 45988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch->chunk_type == SCTP_ASCONF && stcb == NULL) { 45998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_chunkhdr *asconf_ch = ch; 46008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t asconf_offset = 0, asconf_len = 0; 46018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* inp's refcount may be reduced */ 46038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INCR_REF(inp); 46048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf_offset = *offset; 46068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen do { 46078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf_len = ntohs(asconf_ch->chunk_length); 46088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asconf_len < sizeof(struct sctp_asconf_paramhdr)) 46098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 46100ac02f34d6041cd0018437596a5a9a94685e6919tuexen stcb = sctp_findassociation_ep_asconf(m, 4611e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen *offset, 4612e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen dst, 4613e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sh, &inp, netp, vrf_id); 46148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb != NULL) 46158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 46168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf_offset += SCTP_SIZE32(asconf_len); 46178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf_ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, asconf_offset, 46188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_chunkhdr), chunk_buf); 46198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } while (asconf_ch != NULL && asconf_ch->chunk_type == SCTP_ASCONF); 46208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 46218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 46228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * reduce inp's refcount if not reduced in 46238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_findassociation_ep_asconf(). 46248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 46258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 46268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 46278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen locked_tcb = stcb; 46288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now go back and verify any auth chunk to be sure */ 46318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (auth_skipped && (stcb != NULL)) { 46328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_auth_chunk *auth; 46338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth = (struct sctp_auth_chunk *) 46358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_getptr(m, auth_offset, 46368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth_len, chunk_buf); 46378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen got_auth = 1; 46388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth_skipped = 0; 46398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, 46408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth_offset)) { 46418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* auth HMAC failed so dump it */ 46428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 46438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 46448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 46458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 46478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 46488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remaining chunks are HMAC checked */ 46498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.authenticated = 1; 46508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 46548f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 46558f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 46568f9e45fea288542b24a6bda01269c6fc184d991at msg); 46578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no association, so it's out of the blue... */ 46588f9e45fea288542b24a6bda01269c6fc184d991at sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err, 465951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 466051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 466151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 46628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id, port); 46638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 46648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 46658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 46668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 46688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 46708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ABORT and SHUTDOWN can use either v_tag... */ 46718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) || 46728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) || 46738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ch->chunk_type == SCTP_PACKET_DROPPED)) { 467484a42e7150ac17acef0963810b547fbc3b4b8ac1t /* Take the T-bit always into account. */ 467584a42e7150ac17acef0963810b547fbc3b4b8ac1t if ((((ch->chunk_flags & SCTP_HAD_NO_TCB) == 0) && 467684a42e7150ac17acef0963810b547fbc3b4b8ac1t (vtag_in == asoc->my_vtag)) || 467784a42e7150ac17acef0963810b547fbc3b4b8ac1t (((ch->chunk_flags & SCTP_HAD_NO_TCB) == SCTP_HAD_NO_TCB) && 46788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (vtag_in == asoc->peer_vtag))) { 46798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* this is valid */ 46808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 46818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* drop this packet... */ 46828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_badvtag); 46838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 46848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 46858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 46878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 46898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vtag_in != asoc->my_vtag) { 46908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 46918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this could be a stale SHUTDOWN-ACK or the 46928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * peer never got the SHUTDOWN-COMPLETE and 46938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is still hung; we have started a new asoc 46948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * but it won't complete until the shutdown 46958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is completed 46968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 46978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 46988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 46998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47008f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 47018f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 47028f9e45fea288542b24a6bda01269c6fc184d991at msg); 4703e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_handle_ootb(m, iphlen, *offset, src, dst, 47048f9e45fea288542b24a6bda01269c6fc184d991at sh, inp, op_err, 470551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 470651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 470751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 4708eab8290432042d40f3c599ebfb67890c39d16556tuexen vrf_id, port); 47098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 47108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 47128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* for all other chunks, vtag must match */ 47138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vtag_in != asoc->my_vtag) { 47148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid vtag... */ 47158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, 47168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "invalid vtag: %xh, expect %xh\n", 47178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vtag_in, asoc->my_vtag); 47188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_badvtag); 47198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 47208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 47218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 47238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 47248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* end if !SCTP_COOKIE_ECHO */ 47278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 47288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process all control chunks... 47298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 47308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((ch->chunk_type == SCTP_SELECTIVE_ACK) || 473123273859c39742f09cc5ec7c9bf32ff225661e82tuexen (ch->chunk_type == SCTP_NR_SELECTIVE_ACK) || 473223273859c39742f09cc5ec7c9bf32ff225661e82tuexen (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) && 47338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { 47348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* implied cookie-ack.. we must have lost the ack */ 47358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 47368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 47378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 47388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 47398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 47408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 47418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 47438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, 47448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp); 47458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 47478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen process_control_chunks: 47488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (IS_SCTP_CONTROL(ch)) { 47498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* validate chunk length */ 47508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk_length = ntohs(ch->chunk_length); 47518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_process_control: processing a chunk type=%u, len=%u\n", 47528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch->chunk_type, chk_length); 47538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_CHK(inp, stcb, ch->chunk_type, chk_length); 47548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk_length < sizeof(*ch) || 47558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*offset + (int)chk_length) > length) { 47568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 47578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 47588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 47598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 47618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER64(sctps_incontrolchunks); 47638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 47648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INIT-ACK only gets the init ack "header" portion only 47658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * because we don't have to process the peer's COOKIE. All 47668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * others get a complete chunk. 47678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 47688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ch->chunk_type == SCTP_INITIATION_ACK) || 47698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ch->chunk_type == SCTP_INITIATION)) { 47708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get an init-ack chunk */ 47718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 47728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_init_ack_chunk), chunk_buf); 47738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch == NULL) { 47748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 47758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 47768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 47778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 47798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 47818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* For cookies and all other chunks. */ 47828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk_length > sizeof(chunk_buf)) { 47838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 47848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * use just the size of the chunk buffer 47858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * so the front part of our chunks fit in 47868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * contiguous space up to the chunk buffer 47878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * size (508 bytes). 47888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For chunks that need to get more than that 47898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * they must use the sctp_m_getptr() function 47908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * or other means (e.g. know how to parse mbuf 47918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * chains). Cookies do this already. 47928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 47938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 47948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sizeof(chunk_buf) - 4), 47958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chunk_buf); 47968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch == NULL) { 47978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 47988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 47998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 48008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 48028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 48048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We can fit it all */ 48058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 48068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk_length, chunk_buf); 48078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch == NULL) { 48088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("sctp_process_control: Can't get the all data....\n"); 48098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 48108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 48118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 48128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 48148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_chunks++; 48188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Save off the last place we got a control from */ 48198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb != NULL) { 48208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((netp != NULL) && (*netp != NULL)) || (ch->chunk_type == SCTP_ASCONF)) { 48218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 48228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * allow last_control to be NULL if 48238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASCONF... ASCONF processing will find the 48248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * right net later 48258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 48268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((netp != NULL) && (*netp != NULL)) 48278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.last_control_chunk_from = *netp; 48288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED 48318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_audit_log(0xB0, ch->chunk_type); 48328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 48338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* check to see if this chunk required auth, but isn't */ 48358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb != NULL) && 4836fb3816eaffe5878bb1286adb120fd160da178a05t (stcb->asoc.auth_supported == 1) && 48378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) && 48388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen !stcb->asoc.authenticated) { 48398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* "silently" ignore */ 48408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvauthmissing); 48418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_chunk; 48428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ch->chunk_type) { 48448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_INITIATION: 48458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT\n"); 484623273859c39742f09cc5ec7c9bf32ff225661e82tuexen /* The INIT chunk must be the only chunk. */ 484723273859c39742f09cc5ec7c9bf32ff225661e82tuexen if ((num_chunks > 1) || 484823273859c39742f09cc5ec7c9bf32ff225661e82tuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 48498f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 48508f9e45fea288542b24a6bda01269c6fc184d991at "INIT not the only chunk"); 4851e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(inp, stcb, m, iphlen, 48528f9e45fea288542b24a6bda01269c6fc184d991at src, dst, sh, op_err, 485351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 485451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 485551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 485651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 48578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 48588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 48598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 486023273859c39742f09cc5ec7c9bf32ff225661e82tuexen /* Honor our resource limit. */ 486123273859c39742f09cc5ec7c9bf32ff225661e82tuexen if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) { 48628f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 4863e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(inp, stcb, m, iphlen, 4864e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 486551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 486651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 486751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 486851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 48698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 48708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 48718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4872e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_handle_init(m, iphlen, *offset, src, dst, sh, 487323273859c39742f09cc5ec7c9bf32ff225661e82tuexen (struct sctp_init_chunk *)ch, inp, 487451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen stcb, &abort_no_unlock, 487551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 487651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 487751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 487851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 48798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 488023273859c39742f09cc5ec7c9bf32ff225661e82tuexen if ((!abort_no_unlock) && (locked_tcb)) { 48818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 48828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 48848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 48858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_PAD_CHUNK: 48868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 48878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_INITIATION_ACK: 48888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n"); 48898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 48908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We are not interested anymore */ 4891e2828360ea9cf8951730d46f5c14626c9425cb30t if ((stcb) && (stcb->asoc.total_output_queue_size)) { 48928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ; 48938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 48948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb != stcb) { 48958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Very unlikely */ 48968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 48978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 48998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 49000612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 49018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(inp); 49028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 49038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 49048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 49058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 49068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 49078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 49088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_27); 49090612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 49108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 49118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 49128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 49148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 491623273859c39742f09cc5ec7c9bf32ff225661e82tuexen /* The INIT-ACK chunk must be the only chunk. */ 49178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((num_chunks > 1) || 491823273859c39742f09cc5ec7c9bf32ff225661e82tuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 49198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 49208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 49218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 49228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 49248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((netp) && (*netp)) { 4926e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen ret = sctp_handle_init_ack(m, iphlen, *offset, 4927e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, 4928e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen (struct sctp_init_ack_chunk *)ch, 492951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen stcb, *netp, 493051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen &abort_no_unlock, 493151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 493251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 493351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 493451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id); 49358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 49368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ret = -1; 49378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 493823273859c39742f09cc5ec7c9bf32ff225661e82tuexen *offset = length; 493923273859c39742f09cc5ec7c9bf32ff225661e82tuexen if (abort_no_unlock) { 494023273859c39742f09cc5ec7c9bf32ff225661e82tuexen return (NULL); 494123273859c39742f09cc5ec7c9bf32ff225661e82tuexen } 49428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 49438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Special case, I must call the output routine to 49448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * get the cookie echoed 49458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 494623273859c39742f09cc5ec7c9bf32ff225661e82tuexen if ((stcb != NULL) && (ret == 0)) { 49478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 494823273859c39742f09cc5ec7c9bf32ff225661e82tuexen } 49498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 49508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 49518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 49538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 49548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SELECTIVE_ACK: 49558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 49568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_sack_chunk *sack; 49578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int abort_now = 0; 49588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t a_rwnd, cum_ack; 49598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t num_seg, num_dup; 49608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t flags; 49618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int offset_seg, offset_dup; 49628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 49638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n"); 49648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvsacks); 49658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 49668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing SACK chunk\n"); 49678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 49688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk_length < sizeof(struct sctp_sack_chunk)) { 49708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on SACK chunk, too small\n"); 49718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 49728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 49748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 49758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If we have sent a shutdown-ack, we will pay no 49768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * attention to a sack sent in to us since 49778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we don't care anymore. 49788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 49798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 49808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sack = (struct sctp_sack_chunk *)ch; 49828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen flags = ch->chunk_flags; 49838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ack = ntohl(sack->sack.cum_tsn_ack); 49848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_seg = ntohs(sack->sack.num_gap_ack_blks); 49858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_dup = ntohs(sack->sack.num_dup_tsns); 49868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a_rwnd = (uint32_t) ntohl(sack->sack.a_rwnd); 49878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sizeof(struct sctp_sack_chunk) + 49888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_seg * sizeof(struct sctp_gap_ack_block) + 49898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_dup * sizeof(uint32_t) != chk_length) { 49908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of SACK chunk\n"); 49918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 49928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset_seg = *offset + sizeof(struct sctp_sack_chunk); 49948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 49958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 49968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ack, num_seg, a_rwnd); 49978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.seen_a_sack_this_pkt = 1; 49988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.pr_sctp_cnt == 0) && 49998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (num_seg == 0) && 5000b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 50018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.saw_sack_with_frags == 0) && 50028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.saw_sack_with_nr_frags == 0) && 50038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) 50048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ) { 50058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We have a SIMPLE sack having no prior segments and 50068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * data on sent queue to be acked.. Use the faster 50078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * path sack processing. We also allow window update 50088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sacks with no missing segments to go this way too. 50098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 50108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen); 50118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 50128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp && *netp) 50130ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_handle_sack(m, offset_seg, offset_dup, stcb, 50148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_seg, 0, num_dup, &abort_now, flags, 50158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ack, a_rwnd, ecne_seen); 50168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (abort_now) { 50188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ABORT signal from sack processing */ 50198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 50208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 50218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 50238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_EMPTY(&stcb->asoc.sent_queue) && 50248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.stream_queue_cnt == 0)) { 50258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 50268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 50298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* EY - nr_sack: If the received chunk is an nr_sack chunk */ 50308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_NR_SELECTIVE_ACK: 50318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 50328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nr_sack_chunk *nr_sack; 50338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int abort_now = 0; 50348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t a_rwnd, cum_ack; 50358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t num_seg, num_nr_seg, num_dup; 50368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t flags; 50378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int offset_seg, offset_dup; 50388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 50398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n"); 50408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvsacks); 50418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 50428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n"); 50438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 50448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 504544318e900a771ba1a5bafb510c38f33fd5cd8a39t if (stcb->asoc.nrsack_supported == 0) { 50468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto unknown_chunk; 50478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk_length < sizeof(struct sctp_nr_sack_chunk)) { 50498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR-SACK chunk, too small\n"); 50508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 50518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 50538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 50548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If we have sent a shutdown-ack, we will pay no 50558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * attention to a sack sent in to us since 50568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we don't care anymore. 50578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 50588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 50598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen nr_sack = (struct sctp_nr_sack_chunk *)ch; 50618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen flags = ch->chunk_flags; 50628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack); 50638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks); 50648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks); 50658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_dup = ntohs(nr_sack->nr_sack.num_dup_tsns); 50668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a_rwnd = (uint32_t) ntohl(nr_sack->nr_sack.a_rwnd); 50678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sizeof(struct sctp_nr_sack_chunk) + 50688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (num_seg + num_nr_seg) * sizeof(struct sctp_gap_ack_block) + 50698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_dup * sizeof(uint32_t) != chk_length) { 50708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of NR_SACK chunk\n"); 50718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 50728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset_seg = *offset + sizeof(struct sctp_nr_sack_chunk); 50748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 50758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 50768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ack, num_seg, a_rwnd); 50778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.seen_a_sack_this_pkt = 1; 50788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.pr_sctp_cnt == 0) && 50798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (num_seg == 0) && (num_nr_seg == 0) && 50808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 50818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.saw_sack_with_frags == 0) && 50828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.saw_sack_with_nr_frags == 0) && 50838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 50848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 50858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We have a SIMPLE sack having no 50868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * prior segments and data on sent 50878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queue to be acked. Use the 50888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * faster path sack processing. We 50898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * also allow window update sacks 50908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * with no missing segments to go 50918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this way too. 50928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 50938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_express_handle_sack(stcb, cum_ack, a_rwnd, 50948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &abort_now, ecne_seen); 50958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 50968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp && *netp) 50970ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_handle_sack(m, offset_seg, offset_dup, stcb, 50988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_seg, num_nr_seg, num_dup, &abort_now, flags, 50998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cum_ack, a_rwnd, ecne_seen); 51008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (abort_now) { 51028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ABORT signal from sack processing */ 51038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 51048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 51058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 51078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_EMPTY(&stcb->asoc.sent_queue) && 51088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.stream_queue_cnt == 0)) { 51098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 51108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 51138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_HEARTBEAT_REQUEST: 51158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT\n"); 51168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb) && netp && *netp) { 51178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvheartbeat); 51188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_heartbeat_ack(stcb, m, *offset, 51198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk_length, *netp); 51208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* He's alive so give him credit */ 51228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 51238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 51248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 51258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 51268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 51278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 51288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 51308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 51328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_HEARTBEAT_ACK: 51338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT-ACK\n"); 51348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb == NULL) || (chk_length != sizeof(struct sctp_heartbeat_chunk))) { 51358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its not ours */ 51368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 51378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 51388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 51398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 51418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* He's alive so give him credit */ 51438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 51448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 51458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 51468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 51478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 51488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 51498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 51518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvheartbeatack); 51528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp && *netp) 51538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch, 51548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, *netp); 51558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 51568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ABORT_ASSOCIATION: 51578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n", 5158ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)stcb); 51598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb) && netp && *netp) 51608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_abort((struct sctp_abort_chunk *)ch, 51618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, *netp); 51628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 51638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 51648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 51658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SHUTDOWN: 51668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n", 5167ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)stcb); 51688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) { 51698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 51708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 51718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 51728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 51748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp && *netp) { 51768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int abort_flag = 0; 51778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch, 51798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, *netp, &abort_flag); 51808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (abort_flag) { 51818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 51828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 51838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 51868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SHUTDOWN_ACK: 5187ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", (void *)stcb); 51888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb) && (netp) && (*netp)) 51898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp); 51908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 51918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 51928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 51938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_OPERATION_ERROR: 51958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP-ERR\n"); 51968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb) && netp && *netp && sctp_handle_error(ch, stcb, *netp) < 0) { 51978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 51988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 51998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 52018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_COOKIE_ECHO: 52028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, 5203ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t "SCTP_COOKIE-ECHO, stcb %p\n", (void *)stcb); 52048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb) && (stcb->asoc.total_output_queue_size)) { 52058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ; 52068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 52078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 52088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We are not interested anymore */ 52098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen abend: 52108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 52118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 52128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 52148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 52158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 52188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * First are we accepting? We do this again here 52198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since it is possible that a previous endpoint WAS 52208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * listening responded to a INIT-ACK and then 52218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * closed. We opened and bound.. and are now no 52228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * longer listening. 52238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 52248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { 52268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 52278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { 52288f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 5229e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_abort_association(inp, stcb, m, iphlen, 5230e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, op_err, 523151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 523251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 523351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 523451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 52358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 52378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 52388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 52398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *ret_buf; 52408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *linp; 52418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 52428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen linp = NULL; 52438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 52448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen linp = inp; 52458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (linp) { 52488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_CREATE_LOCK(linp); 52498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 52508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 52518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_CREATE_UNLOCK(linp); 52528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto abend; 52538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp) { 52578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ret_buf = 52588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_cookie_echo(m, iphlen, 5259e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen *offset, 5260e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, 5261e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sh, 5262e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen (struct sctp_cookie_echo_chunk *)ch, 5263e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen &inp, &stcb, netp, 5264e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen auth_skipped, 5265e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen auth_offset, 5266e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen auth_len, 5267e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen &locked_tcb, 526851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 526951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, 527051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen mflowid, 527151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 5272e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen vrf_id, 5273e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen port); 52748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 52758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ret_buf = NULL; 52768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (linp) { 52788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_CREATE_UNLOCK(linp); 52798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ret_buf == NULL) { 52818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 52828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 52838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, 52858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "GAK, null buffer\n"); 52868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 52878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 52888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* if AUTH skipped, see if it verified... */ 52908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (auth_skipped) { 52918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen got_auth = 1; 52928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth_skipped = 0; 52938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) { 52958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 52968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Restart the timer if we have 52978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * pending data 52988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 52998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk; 53008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 53018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 53028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 53038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 53068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_COOKIE_ACK: 5307ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", (void *)stcb); 53088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) { 53098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 53108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 53118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 53138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 53158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We are not interested anymore */ 53168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb) && (stcb->asoc.total_output_queue_size)) { 53178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ; 53188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (stcb) { 53190612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 53208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(inp); 53218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 53228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 53238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 53248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 53258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 53268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 53278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_27); 53280612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 53298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 53308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 53318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 53328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 53338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* He's alive so give him credit */ 53368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb) && netp && *netp) { 53378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 53388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 53398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 53408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 53418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 53428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 53438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 53458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch,stcb, *netp); 53468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 53488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ECN_ECHO: 53498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-ECHO\n"); 53508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* He's alive so give him credit */ 53518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb == NULL) || (chk_length != sizeof(struct sctp_ecne_chunk))) { 53528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its not ours */ 53538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 53548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 53558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 53578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 53588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 5360fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.ecn_supported == 0) { 5361fb3816eaffe5878bb1286adb120fd160da178a05t goto unknown_chunk; 5362fb3816eaffe5878bb1286adb120fd160da178a05t } 53638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 53648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 53658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 53668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 53678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 53688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 53698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 53718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch, 53728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb); 53738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ecne_seen = 1; 53748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 53768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ECN_CWR: 53778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-CWR\n"); 53788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* He's alive so give him credit */ 53798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb == NULL) || (chk_length != sizeof(struct sctp_cwr_chunk))) { 53808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its not ours */ 53818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 53828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 53838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 53858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 53868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 5388fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.ecn_supported == 0) { 5389fb3816eaffe5878bb1286adb120fd160da178a05t goto unknown_chunk; 5390fb3816eaffe5878bb1286adb120fd160da178a05t } 53918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 53928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 53938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 53948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 53958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 53968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 53978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 53998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp); 54008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 54028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_SHUTDOWN_COMPLETE: 5403ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", (void *)stcb); 54048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* must be first and only chunk */ 54058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((num_chunks > 1) || 54068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 54078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 54088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 54098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 54108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 54128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb) && netp && *netp) { 54148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch, 54158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, *netp); 54168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 54188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 54198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 54208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ASCONF: 54218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n"); 54228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* He's alive so give him credit */ 54238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 5424fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.asconf_supported == 0) { 5425fb3816eaffe5878bb1286adb120fd160da178a05t goto unknown_chunk; 5426fb3816eaffe5878bb1286adb120fd160da178a05t } 54278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 54288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 54298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 54308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 54318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 54328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 54338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 5435e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_handle_asconf(m, *offset, src, 54368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_asconf_chunk *)ch, stcb, asconf_cnt == 0); 54378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asconf_cnt++; 54388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 54408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ASCONF_ACK: 54418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF-ACK\n"); 54428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk_length < sizeof(struct sctp_asconf_ack_chunk)) { 54438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its not ours */ 54448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 54458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 54468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 54488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 54498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb) && netp && *netp) { 5451fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.asconf_supported == 0) { 5452fb3816eaffe5878bb1286adb120fd160da178a05t goto unknown_chunk; 5453fb3816eaffe5878bb1286adb120fd160da178a05t } 54548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* He's alive so give him credit */ 54558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 54568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 54578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 54588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 54598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 54608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 54618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 54638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_asconf_ack(m, *offset, 54648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_asconf_ack_chunk *)ch, stcb, *netp, &abort_no_unlock); 54658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (abort_no_unlock) 54668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 54678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 54698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_FORWARD_CUM_TSN: 54708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD-TSN\n"); 54718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk_length < sizeof(struct sctp_forward_tsn_chunk)) { 54728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its not ours */ 54738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 54748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 54758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 54778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 54788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 54808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* He's alive so give him credit */ 54818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 54828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int abort_flag = 0; 5483fb3816eaffe5878bb1286adb120fd160da178a05t 5484fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.prsctp_supported == 0) { 5485fb3816eaffe5878bb1286adb120fd160da178a05t goto unknown_chunk; 5486fb3816eaffe5878bb1286adb120fd160da178a05t } 54878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 54888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 54898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 54908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 54918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 54928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 54938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 54948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *fwd_tsn_seen = 1; 54968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 54978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We are not interested anymore */ 54980612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 54998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = SCTP_INP_SO(inp); 55008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 55018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 55028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_LOCK(so, 1); 55038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 55048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 55058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 55068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_29); 55070612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 55088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOCKET_UNLOCK(so, 1); 55098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 55108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 55118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 55128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_forward_tsn(stcb, 55148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_forward_tsn_chunk *)ch, &abort_flag, m, *offset); 55158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (abort_flag) { 55168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 55178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 55188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 55198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 55208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 55218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 55228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 55238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 55248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 55258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 55278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 55298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 55318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STREAM_RESET: 55328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_STREAM_RESET\n"); 5533b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (((stcb == NULL) || (ch == NULL) || (chk_length < sizeof(struct sctp_stream_reset_tsn_req)))) { 55348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its not ours */ 55358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 55368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 55378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 55398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 55408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55412344bfccffeb80545fca6a86e8cda3d56a6f50bft if (stcb->asoc.reconfig_supported == 0) { 5542fb3816eaffe5878bb1286adb120fd160da178a05t goto unknown_chunk; 55438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 554424feb751a6f488d36918e2f333dc2be853c259c8t if (sctp_handle_stream_reset(stcb, m, *offset, ch)) { 55458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* stop processing */ 55468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 55478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 55488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 55508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_PACKET_DROPPED: 55518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_PACKET_DROPPED\n"); 55528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* re-get it all please */ 55538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk_length < sizeof(struct sctp_pktdrop_chunk)) { 55548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its not ours */ 55558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 55568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 55578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 55598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 55608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 55628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 55638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch && (stcb) && netp && (*netp)) { 5564fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.pktdrop_supported == 0) { 5565fb3816eaffe5878bb1286adb120fd160da178a05t goto unknown_chunk; 5566fb3816eaffe5878bb1286adb120fd160da178a05t } 55678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch, 55688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, *netp, 55698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min(chk_length, (sizeof(chunk_buf) - 4))); 55708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 55718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 55738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 55748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_AUTHENTICATION: 55758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n"); 55768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 55778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* save the first AUTH for later processing */ 55788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (auth_skipped == 0) { 55798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth_offset = *offset; 55808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth_len = chk_length; 55818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen auth_skipped = 1; 55828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* skip this chunk (temporarily) */ 55848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_chunk; 55858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5586fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.auth_supported == 0) { 5587fb3816eaffe5878bb1286adb120fd160da178a05t goto unknown_chunk; 5588fb3816eaffe5878bb1286adb120fd160da178a05t } 55898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((chk_length < (sizeof(struct sctp_auth_chunk))) || 55908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (chk_length > (sizeof(struct sctp_auth_chunk) + 55910ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen SCTP_AUTH_DIGEST_LEN_MAX))) { 55928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its not ours */ 55938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 55948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 55958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 55978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 55988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (got_auth == 1) { 56008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* skip this chunk... it's already auth'd */ 56018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_chunk; 56028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen got_auth = 1; 56048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ch == NULL) || sctp_handle_auth(stcb, (struct sctp_auth_chunk *)ch, 56058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m, *offset)) { 56068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* auth HMAC failed so dump the packet */ 56078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 56088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 56098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 56108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remaining chunks are HMAC checked */ 56118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.authenticated = 1; 56128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 56148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 56168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unknown_chunk: 56178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* it's an unknown chunk! */ 56188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ch->chunk_type & 0x40) && (stcb != NULL)) { 56198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *mm; 56208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *phd; 56218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 562368beeca578347438d9c434680197647ed551935ft 0, M_NOWAIT, 1, MT_DATA); 56248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mm) { 56258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phd = mtod(mm, struct sctp_paramhdr *); 56268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 56278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We cheat and use param type since 56288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we did not bother to define a 56298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * error cause struct. They are the 56308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * same basic format with different 56318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * names. 56328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 56338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK); 56348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phd->param_length = htons(chk_length + sizeof(*phd)); 56358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BUF_LEN(mm) = sizeof(*phd); 563668beeca578347438d9c434680197647ed551935ft SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); 56378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_NEXT(mm)) { 5638290e3870bdc4b436f18bfe30e6c243205fc29702t if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) { 56394df11f5004bbb4c768851ee41149ba6982c60f29tuexen sctp_m_freem(mm); 56404df11f5004bbb4c768851ee41149ba6982c60f29tuexen } else { 56418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MBUF_LOGGING 56424df11f5004bbb4c768851ee41149ba6982c60f29tuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 56434df11f5004bbb4c768851ee41149ba6982c60f29tuexen struct mbuf *mat; 56444df11f5004bbb4c768851ee41149ba6982c60f29tuexen 5645208d5309857156b26b753ba8cb35813775f49c5btuexen for (mat = SCTP_BUF_NEXT(mm); mat; mat = SCTP_BUF_NEXT(mat)) { 56464df11f5004bbb4c768851ee41149ba6982c60f29tuexen if (SCTP_BUF_IS_EXTENDED(mat)) { 56474df11f5004bbb4c768851ee41149ba6982c60f29tuexen sctp_log_mb(mat, SCTP_MBUF_ICOPY); 56484df11f5004bbb4c768851ee41149ba6982c60f29tuexen } 56498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 56524df11f5004bbb4c768851ee41149ba6982c60f29tuexen sctp_queue_op_err(stcb, mm); 56534df11f5004bbb4c768851ee41149ba6982c60f29tuexen } 56548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 56558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(mm); 56568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ch->chunk_type & 0x80) == 0) { 56608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* discard this packet */ 56618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 56628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 56638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* else skip this bad chunk and continue... */ 56648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 56658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* switch (ch->chunk_type) */ 56668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen next_chunk: 56698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the next chunk */ 56708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset += SCTP_SIZE32(chk_length); 56718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (*offset >= length) { 56728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no more data left in the mbuf chain */ 56738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 56748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 56768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_chunkhdr), chunk_buf); 56778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ch == NULL) { 56788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 56798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 56808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *offset = length; 56828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 56838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* while */ 56858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asconf_cnt > 0 && stcb != NULL) { 56878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_asconf_ack(stcb); 56888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 56908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 56918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 56948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __GNUC__ 56958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen__attribute__((noinline)) 56968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 56978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 56988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_validate_no_locks(struct sctp_inpcb *inp) 56998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 57008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __APPLE__ 57018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *lstcb; 570215aed6e434dc1aac416f14635bb78920317d60e7t 57038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) { 57048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mtx_owned(&lstcb->tcb_mtx)) { 57058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Own lock on stcb at return from input"); 57068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mtx_owned(&inp->inp_create_mtx)) { 57098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Own create lock on inp"); 57108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mtx_owned(&inp->inp_mtx)) { 57128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Own inp lock on inp"); 57138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 57158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 57168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 57178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 57188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 57198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * common input chunk processing (v4 and v6) 57208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 57218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 5722e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int length, 5723e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, 5724e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sctphdr *sh, struct sctp_chunkhdr *ch, 572566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if !defined(SCTP_WITH_NO_CSUM) 572666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen uint8_t compute_crc, 572766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 572866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen uint8_t ecn_bits, 572951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 573051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid, uint32_t mflowid, 573151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 573251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint32_t vrf_id, uint16_t port) 57338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 57348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t high_tsn; 57358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int fwd_tsn_seen = 0, data_processed = 0; 57368f9e45fea288542b24a6bda01269c6fc184d991at struct mbuf *m = *mm, *op_err; 57378f9e45fea288542b24a6bda01269c6fc184d991at char msg[SCTP_DIAG_INFO_LEN]; 57388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int un_sent; 5739b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int cnt_ctrl_ready = 0; 57404a19dac3955f03ff398400d269bdca84b113c85btuexen struct sctp_inpcb *inp = NULL, *inp_decr = NULL; 574166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen struct sctp_tcb *stcb = NULL; 574266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen struct sctp_nets *net = NULL; 57438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 57448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvdatagrams); 57458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED 57468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_audit_log(0xE0, 1); 57478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auditing(0, inp, stcb, net); 57488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 574966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if !defined(SCTP_WITH_NO_CSUM) 575066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (compute_crc != 0) { 575166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen uint32_t check, calc_check; 575266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen 575366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen check = sh->checksum; 575466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sh->checksum = 0; 575566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen calc_check = sctp_calculate_cksum(m, iphlen); 575666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sh->checksum = check; 575766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (calc_check != check) { 575866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n", 5759ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t calc_check, check, (void *)m, length, iphlen); 576066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen stcb = sctp_findassociation_addr(m, offset, src, dst, 576166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sh, ch, &inp, &net, vrf_id); 576248830a703639020b04dbea0128bc37fd8a8ab35et#if defined(INET) || defined(INET6) 576366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if ((net != NULL) && (port != 0)) { 576466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (net->port == 0) { 576566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 576666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 576766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen net->port = port; 576866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 57696c632b3f6e570981666f8a3ff4be34eaf1735835t#endif 577066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if defined(__FreeBSD__) 577166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if ((net != NULL) && (use_mflowid != 0)) { 577266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen net->flowid = mflowid; 577366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#ifdef INVARIANTS 577466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen net->flowidset = 1; 577566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 577666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 577766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 577866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if ((inp != NULL) && (stcb != NULL)) { 577966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); 578066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); 578166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } else if ((inp != NULL) && (stcb == NULL)) { 578266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen inp_decr = inp; 578366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 578466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_STAT_INCR(sctps_badsum); 578566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors); 578666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 578766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 578866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 578966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 579066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen /* Destination port of 0 is illegal, based on RFC4960. */ 579166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (sh->dest_port == 0) { 579266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_STAT_INCR(sctps_hdrops); 579366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 579466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 579566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen stcb = sctp_findassociation_addr(m, offset, src, dst, 579666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sh, ch, &inp, &net, vrf_id); 579748830a703639020b04dbea0128bc37fd8a8ab35et#if defined(INET) || defined(INET6) 579866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if ((net != NULL) && (port != 0)) { 579966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (net->port == 0) { 580066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 580166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 580266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen net->port = port; 580366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 58046c632b3f6e570981666f8a3ff4be34eaf1735835t#endif 580566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if defined(__FreeBSD__) 580666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if ((net != NULL) && (use_mflowid != 0)) { 580766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen net->flowid = mflowid; 580866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#ifdef INVARIANTS 580966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen net->flowidset = 1; 581066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 581166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 581266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 581366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (inp == NULL) { 581466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_STAT_INCR(sctps_noport); 5815b06edc654b01523d6cdf646804e9dd5903a5cc68t#if defined(__FreeBSD__) && (((__FreeBSD_version < 900000) && (__FreeBSD_version >= 804000)) || (__FreeBSD_version > 900000)) 581666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) { 581766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 581866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 581966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 582066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 582166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sctp_send_shutdown_complete2(src, dst, sh, 582266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if defined(__FreeBSD__) 582366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen use_mflowid, mflowid, 582466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 582566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen vrf_id, port); 582666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 582766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 582866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) { 582966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 583066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 583166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) { 583266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || 583366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && 583466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen (ch->chunk_type != SCTP_INIT))) { 58358f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 58368f9e45fea288542b24a6bda01269c6fc184d991at "Out of the blue"); 583766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sctp_send_abort(m, iphlen, src, dst, 58388f9e45fea288542b24a6bda01269c6fc184d991at sh, 0, op_err, 583966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if defined(__FreeBSD__) 584066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen use_mflowid, mflowid, 584166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 584266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen vrf_id, port); 584366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 584466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 584566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 584666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } else if (stcb == NULL) { 584766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen inp_decr = inp; 584866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 584966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#ifdef IPSEC 585066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen /*- 585166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen * I very much doubt any of the IPSEC stuff will work but I have no 585266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen * idea, so I will leave it in place. 585366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen */ 585466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (inp != NULL) { 585566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen switch (dst->sa_family) { 585666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#ifdef INET 585766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen case AF_INET: 585866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (ipsec4_in_reject(m, &inp->ip_inp.inp)) { 5859e9a6e49099bfee0c316e89efc4c9d2211af729f3t#if defined(__FreeBSD__) && (__FreeBSD_version > 1000036) 5860ebdc22cd2539b3e5ae3b11100cc14e1306640b8at IPSECSTAT_INC(ips_in_polvio); 5861e9a6e49099bfee0c316e89efc4c9d2211af729f3t#else 586266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen MODULE_GLOBAL(ipsec4stat).in_polvio++; 5863e9a6e49099bfee0c316e89efc4c9d2211af729f3t#endif 586466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_STAT_INCR(sctps_hdrops); 586566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 586666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 586766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen break; 586866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 586966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#ifdef INET6 587066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen case AF_INET6: 587166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (ipsec6_in_reject(m, &inp->ip_inp.inp)) { 5872e9a6e49099bfee0c316e89efc4c9d2211af729f3t#if defined(__FreeBSD__) && (__FreeBSD_version > 1000036) 5873ebdc22cd2539b3e5ae3b11100cc14e1306640b8at IPSEC6STAT_INC(ips_in_polvio); 5874e9a6e49099bfee0c316e89efc4c9d2211af729f3t#else 587566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen MODULE_GLOBAL(ipsec6stat).in_polvio++; 5876e9a6e49099bfee0c316e89efc4c9d2211af729f3t#endif 587766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_STAT_INCR(sctps_hdrops); 587866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 587966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 588066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen break; 588166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 588266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen default: 588366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen break; 588466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 588566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 588666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 58878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n", 5888ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)m, iphlen, offset, length, (void *)stcb); 58898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 58908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* always clear this before beginning a packet */ 58918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.authenticated = 0; 58928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.seen_a_sack_this_pkt = 0; 58938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, "stcb:%p state:%x\n", 5894ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)stcb, stcb->asoc.state); 58958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 58968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) || 58978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) { 58988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 58998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If we hit here, we had a ref count 59008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * up when the assoc was aborted and the 59018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * timer is clearing out the assoc, we should 59028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOT respond to any packet.. its OOTB. 59038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5904e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_TCB_UNLOCK(stcb); 590566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen stcb = NULL; 59068f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 59078f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 59088f9e45fea288542b24a6bda01269c6fc184d991at msg); 59098f9e45fea288542b24a6bda01269c6fc184d991at sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 591051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 591151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 591251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 5913e2828360ea9cf8951730d46f5c14626c9425cb30t vrf_id, port); 591466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 59158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IS_SCTP_CONTROL(ch)) { 59198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* process the control portion of the SCTP packet */ 59208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore NO_NULL_CHK */ 5921e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen stcb = sctp_process_control(m, iphlen, &offset, length, 5922e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, ch, 592351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen inp, stcb, &net, &fwd_tsn_seen, 592451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 5925e2828360ea9cf8951730d46f5c14626c9425cb30t use_mflowid, mflowid, 592651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 592751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 59288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb) { 59298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This covers us if the cookie-echo was there 59308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and it changes our INP. 59318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5932e2828360ea9cf8951730d46f5c14626c9425cb30t inp = stcb->sctp_ep; 593348830a703639020b04dbea0128bc37fd8a8ab35et#if defined(INET) || defined(INET6) 59348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((net) && (port)) { 59358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->port == 0) { 59360ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 59378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->port = port; 59398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59406c632b3f6e570981666f8a3ff4be34eaf1735835t#endif 59418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 59438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 59448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * no control chunks, so pre-process DATA chunks (these 59458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * checks are taken care of by control processing) 59468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 59478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 59498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if DATA only packet, and auth is required, then punt... 59508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * can't have authenticated without any AUTH (control) 59518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * chunks 59528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 59538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb != NULL) && 5954fb3816eaffe5878bb1286adb120fd160da178a05t (stcb->asoc.auth_supported == 1) && 59558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) { 59568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* "silently" ignore */ 59578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvauthmissing); 595866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 59598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 59618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* out of the blue DATA chunk */ 59628f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 59638f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 59648f9e45fea288542b24a6bda01269c6fc184d991at msg); 59658f9e45fea288542b24a6bda01269c6fc184d991at sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 596651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 596751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 596851e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 59698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id, port); 597066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 59718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) { 59738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* v_tag mismatch! */ 59748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_badvtag); 597566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 59768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 59808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 59818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * no valid TCB for this packet, or we found it's a bad 59828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * packet while processing control, or we're done with this 59838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * packet (done or skip rest of data), so we drop it... 59848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 598566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 59868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 59898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * DATA chunk processing 59908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 59918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* plow through the data chunks while length > offset */ 59928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 59948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Rest should be DATA only. Check authentication state if AUTH for 59958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * DATA is required. 59968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 59978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((length > offset) && 59988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb != NULL) && 5999fb3816eaffe5878bb1286adb120fd160da178a05t (stcb->asoc.auth_supported == 1) && 60008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) && 60018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen !stcb->asoc.authenticated) { 60028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* "silently" ignore */ 60038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvauthmissing); 60048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_AUTH1, 60058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "Data chunk requires AUTH, skipped\n"); 60068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto trigger_send; 60078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (length > offset) { 60098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int retval; 60108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 60118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 60128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * First check to make sure our state is correct. We would 60138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not get here unless we really did have a tag, so we don't 60148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * abort if this happens, just dump the chunk silently. 60158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 60168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (SCTP_GET_STATE(&stcb->asoc)) { 60178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_COOKIE_ECHOED: 60188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 60198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we consider data with valid tags in this state 60208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * shows us the cookie-ack was lost. Imply it was 60218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * there. 60228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 60238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 60248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 60258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count, 60268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 60278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_INPUT, 60288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __LINE__); 60298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.overall_error_count = 0; 60318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net); 60328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 60338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_COOKIE_WAIT: 60348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 60358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We consider OOTB any data sent during asoc setup. 60368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 60378f9e45fea288542b24a6bda01269c6fc184d991at snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 60388f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 60398f9e45fea288542b24a6bda01269c6fc184d991at msg); 60408f9e45fea288542b24a6bda01269c6fc184d991at sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 604151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 604251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 604351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 60448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id, port); 604566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 60468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NOTREACHED*/ 60478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 60488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_EMPTY: /* should not happen */ 60498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_INUSE: /* should not happen */ 60508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_SHUTDOWN_RECEIVED: /* This is a peer error */ 60518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_SHUTDOWN_ACK_SENT: 60528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 605366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 60548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NOTREACHED*/ 60558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 60568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_OPEN: 60578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STATE_SHUTDOWN_SENT: 60588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 60598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* plow through the data chunks while length > offset */ 6061e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen retval = sctp_process_data(mm, iphlen, &offset, length, 6062e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src, dst, sh, 606351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen inp, stcb, net, &high_tsn, 606451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 606551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 606651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 606751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 60688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (retval == 2) { 60698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 60708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * The association aborted, NO UNLOCK needed since 60718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the association is destroyed. 60728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 607366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen stcb = NULL; 607466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 60758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen data_processed = 1; 60778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 60788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Anything important needs to have been m_copy'ed in 60798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process_data 60808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 60818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 60838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* take care of ecn */ 6084b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if ((data_processed == 1) && 6085aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t (stcb->asoc.ecn_supported == 1) && 60868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) { 60878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yep, we need to add a ECNE */ 60888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_ecn_echo(stcb, net, high_tsn); 60898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 60918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((data_processed == 0) && (fwd_tsn_seen)) { 60928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int was_a_gap; 60938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t highest_tsn; 60948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 60958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(stcb->asoc.highest_tsn_inside_nr_map, stcb->asoc.highest_tsn_inside_map)) { 60968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen highest_tsn = stcb->asoc.highest_tsn_inside_nr_map; 60978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 60988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen highest_tsn = stcb->asoc.highest_tsn_inside_map; 60998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn); 61018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.send_sack = 1; 61020ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_sack_check(stcb, was_a_gap); 61038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (fwd_tsn_seen) { 61048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.send_sack = 1; 61058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* trigger send of any chunks in queue... */ 61078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexentrigger_send: 61088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED 61098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_audit_log(0xE0, 2); 61108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auditing(1, inp, stcb, net); 61118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT1, 61138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen "Check for chunk output prw:%d tqe:%d tf=%d\n", 61148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_rwnd, 61158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_EMPTY(&stcb->asoc.control_send_queue), 61168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.total_flight); 61178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight); 61188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 61198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq; 61208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cnt_ctrl_ready || 61228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((un_sent) && 61238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.peers_rwnd > 0 || 61248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) { 61258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "Calling chunk OUTPUT\n"); 61268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 61278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "chunk OUTPUT returns\n"); 61288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED 61308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_audit_log(0xE0, 3); 61318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auditing(2, inp, stcb, net); 61328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 613366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen out: 613466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (stcb != NULL) { 613566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_TCB_UNLOCK(stcb); 613666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 613766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (inp_decr != NULL) { 613866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen /* reduce ref-count */ 613966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_INP_WLOCK(inp_decr); 614066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_INP_DECR_REF(inp_decr); 614166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_INP_WUNLOCK(inp_decr); 614266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 61438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 614466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (inp != NULL) { 614566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sctp_validate_no_locks(inp); 614666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } 61478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 61498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 61508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 61518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if 0 61528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 61538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_print_mbuf_chain(struct mbuf *m) 61548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 6155b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen for (; m; m = SCTP_BUF_NEXT(m)) { 6156ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t SCTP_PRINTF("%p: m_len = %ld\n", (void *)m, SCTP_BUF_LEN(m)); 61578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_IS_EXTENDED(m)) 6158ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t SCTP_PRINTF("%p: extend_size = %d\n", (void *)m, SCTP_BUF_EXTEND_SIZE(m)); 61598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 61618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 61638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 6164b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#if !defined(__Userspace__) 6165b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) 61668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 61678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) 6168b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#elif defined(__Panda__) 61698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 61708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_input(pakhandle_type i_pak) 61718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 61728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 61738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __STDC__ 61748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_input(struct mbuf *i_pak,...) 61758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 61768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_input(i_pak, va_alist) 61778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *i_pak; 61788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 61818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m; 61828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int iphlen; 61838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id = 0; 61848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t ecn_bits; 6185e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr_in src, dst; 61868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct ip *ip; 61878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctphdr *sh; 6188923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen struct sctp_chunkhdr *ch; 6189923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen int length, offset; 619066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if !defined(SCTP_WITH_NO_CSUM) 619166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen uint8_t compute_crc; 619266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 619351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 619451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint32_t mflowid; 619551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen uint8_t use_mflowid; 619651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 6197b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)) 61988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t port = 0; 61998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 62008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 6201923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#if defined(__Panda__) 6202923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen /* This is Evil, but its the only way to make panda work right. */ 6203923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen iphlen = sizeof(struct ip); 6204923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#else 6205923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen iphlen = off; 62068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 62078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) { 62088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RELEASE_PKT(i_pak); 62098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 62108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m = SCTP_HEADER_TO_CHAIN(i_pak); 62128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __Panda__ 62138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DETACH_HEADER_FROM_CHAIN(i_pak); 62148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_RELEASE_HEADER(i_pak); 62158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 62168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MBUF_LOGGING 62178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Log in any input mbufs */ 62188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 6219208d5309857156b26b753ba8cb35813775f49c5btuexen struct mbuf *mat; 6220208d5309857156b26b753ba8cb35813775f49c5btuexen 6221208d5309857156b26b753ba8cb35813775f49c5btuexen for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) { 62228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_IS_EXTENDED(mat)) { 62238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_mb(mat, SCTP_MBUF_INPUT); 62248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 62281b50943bdc80bbed39e89acdb49bd3b3f30c528ctuexen#ifdef SCTP_PACKET_LOGGING 6229923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { 62301b50943bdc80bbed39e89acdb49bd3b3f30c528ctuexen sctp_packet_log(m); 6231923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen } 62328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 623351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 623432ce34e90f7862d56c81f432a802a00110f7b427t#if __FreeBSD_version > 1000049 623532ce34e90f7862d56c81f432a802a00110f7b427t SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 623632ce34e90f7862d56c81f432a802a00110f7b427t "sctp_input(): Packet of length %d received on %s with csum_flags 0x%b.\n", 623732ce34e90f7862d56c81f432a802a00110f7b427t m->m_pkthdr.len, 623832ce34e90f7862d56c81f432a802a00110f7b427t if_name(m->m_pkthdr.rcvif), 623932ce34e90f7862d56c81f432a802a00110f7b427t (int)m->m_pkthdr.csum_flags, CSUM_BITS); 62408d509612af0dc2e1895434112897cf049b463063t#elif __FreeBSD_version >= 800000 624166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 624266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", 624366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.len, 624466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if_name(m->m_pkthdr.rcvif), 624566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.csum_flags); 624666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#else 624766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 624866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", 624966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.len, 625066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.rcvif->if_xname, 625166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.csum_flags); 625266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 625366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 625466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if defined(__APPLE__) 625566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 625666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen "sctp_input(): Packet of length %d received on %s%d with csum_flags 0x%x.\n", 625766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.len, 625866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.rcvif->if_name, 625966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.rcvif->if_unit, 626066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.csum_flags); 626166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 626266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if defined(__Windows__) 626366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 626466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", 626566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.len, 626666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.rcvif->if_xname, 626766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen m->m_pkthdr.csum_flags); 626866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 626966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if defined(__FreeBSD__) 627051e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen if (m->m_flags & M_FLOWID) { 627151e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen mflowid = m->m_pkthdr.flowid; 627251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid = 1; 627351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen } else { 627451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen mflowid = 0; 627551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid = 0; 627651e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen } 627751e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 6278923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen SCTP_STAT_INCR(sctps_recvpackets); 6279923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 6280923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen /* Get IP, SCTP, and first chunk header together in the first mbuf. */ 6281923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); 62828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_LEN(m) < offset) { 6283e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen if ((m = m_pullup(m, offset)) == NULL) { 62848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_hdrops); 62858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 62868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6288e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen ip = mtod(m, struct ip *); 6289923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen sh = (struct sctphdr *)((caddr_t)ip + iphlen); 6290923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 6291923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen offset -= sizeof(struct sctp_chunkhdr); 6292e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen memset(&src, 0, sizeof(struct sockaddr_in)); 6293e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src.sin_family = AF_INET; 62947b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 6295e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src.sin_len = sizeof(struct sockaddr_in); 6296e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#endif 6297e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src.sin_port = sh->src_port; 6298e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen src.sin_addr = ip->ip_src; 6299e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen memset(&dst, 0, sizeof(struct sockaddr_in)); 6300e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen dst.sin_family = AF_INET; 63017b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 6302e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen dst.sin_len = sizeof(struct sockaddr_in); 6303e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#endif 6304e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen dst.sin_port = sh->dest_port; 6305e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen dst.sin_addr = ip->ip_dst; 63068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Windows__) 63078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen NTOHS(ip->ip_len); 63088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 63090ac02f34d6041cd0018437596a5a9a94685e6919tuexen#if defined(__Userspace_os_Linux) || defined(__Userspace_os_Windows) 631081616c6a3e184f46276632dd15aa489cd06d94dftuexen ip->ip_len = ntohs(ip->ip_len); 63110af84c59aeb7cc1995f82ef737987d970c345cc7tuexen#endif 63124bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#if defined(__FreeBSD__) 63134bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#if __FreeBSD_version >= 1000000 63144bda18bd6192b29406d04eeb576f5d5d7bd32fc7t length = ntohs(ip->ip_len); 63154bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#else 63164bda18bd6192b29406d04eeb576f5d5d7bd32fc7t length = ip->ip_len + iphlen; 63174bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#endif 63184bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#elif defined(__APPLE__) 6319923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen length = ip->ip_len + iphlen; 6320923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#elif defined(__Userspace__) 6321923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#if defined(__Userspace_os_Linux) || defined(__Userspace_os_Windows) 6322923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen length = ip->ip_len; 6323923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#else 6324923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen length = ip->ip_len + iphlen; 6325923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#endif 6326923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#else 6327923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen length = ip->ip_len; 6328923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#endif 6329923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen /* Validate mbuf chain length with IP payload length. */ 633066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (SCTP_HEADER_LEN(m) != length) { 6331923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen SCTPDBG(SCTP_DEBUG_INPUT1, 633266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m)); 63338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_hdrops); 633466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 63358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* SCTP does not allow broadcasts or multicasts */ 6337e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { 633866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 63398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6340e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen if (SCTP_IS_IT_BROADCAST(dst.sin_addr, m)) { 634166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen goto out; 63428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 634366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen ecn_bits = ip->ip_tos; 63448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_WITH_NO_CSUM) 63458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvnocrc); 63468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 63478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000 63488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { 63498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvhwcrc); 635066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen compute_crc = 0; 635166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } else { 635266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#else 635366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen if (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && 6354e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen ((src.sin_addr.s_addr == dst.sin_addr.s_addr) || 6355923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen (SCTP_IS_IT_LOOPBACK(m)))) { 63568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_recvnocrc); 635766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen compute_crc = 0; 635866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen } else { 635951e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 636066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen SCTP_STAT_INCR(sctps_recvswcrc); 636166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen compute_crc = 1; 63628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6364e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sctp_common_input_processing(&m, iphlen, offset, length, 6365e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen (struct sockaddr *)&src, 6366e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen (struct sockaddr *)&dst, 636766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen sh, ch, 636866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if !defined(SCTP_WITH_NO_CSUM) 636966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen compute_crc, 637066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif 637166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen ecn_bits, 637251e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#if defined(__FreeBSD__) 637351e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen use_mflowid, mflowid, 637451e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen#endif 637551e1e2f0655e8df3aac73911a52e1e558d74ad63tuexen vrf_id, port); 637666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen out: 63778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m) { 63788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(m); 63798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 63818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 63828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 63848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenextern int *sctp_cpuarry; 63858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 63868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 638761a075e65a009a719c4265bfc4bfc433962ffc3ft#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 638861a075e65a009a719c4265bfc4bfc433962ffc3ftint 638961a075e65a009a719c4265bfc4bfc433962ffc3ftsctp_input(struct mbuf **mp, int *offp, int proto SCTP_UNUSED) 639061a075e65a009a719c4265bfc4bfc433962ffc3ft{ 639161a075e65a009a719c4265bfc4bfc433962ffc3ft struct mbuf *m; 639261a075e65a009a719c4265bfc4bfc433962ffc3ft int off; 639361a075e65a009a719c4265bfc4bfc433962ffc3ft 639461a075e65a009a719c4265bfc4bfc433962ffc3ft m = *mp; 639561a075e65a009a719c4265bfc4bfc433962ffc3ft off = *offp; 639661a075e65a009a719c4265bfc4bfc433962ffc3ft#else 63978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 63988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_input(struct mbuf *m, int off) 63998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 640061a075e65a009a719c4265bfc4bfc433962ffc3ft#endif 64018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 64028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mp_ncpus > 1) { 640361a075e65a009a719c4265bfc4bfc433962ffc3ft struct ip *ip; 640461a075e65a009a719c4265bfc4bfc433962ffc3ft struct sctphdr *sh; 640561a075e65a009a719c4265bfc4bfc433962ffc3ft int offset; 640661a075e65a009a719c4265bfc4bfc433962ffc3ft int cpu_to_use; 640761a075e65a009a719c4265bfc4bfc433962ffc3ft uint32_t flowid, tag; 640861a075e65a009a719c4265bfc4bfc433962ffc3ft 64098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (m->m_flags & M_FLOWID) { 64108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen flowid = m->m_pkthdr.flowid; 64118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 64128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No flow id built by lower layers 64138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * fix it so we create one. 64148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 6415e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen offset = off + sizeof(struct sctphdr); 64168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_LEN(m) < offset) { 6417e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen if ((m = m_pullup(m, offset)) == NULL) { 64188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_hdrops); 641961a075e65a009a719c4265bfc4bfc433962ffc3ft#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 642061a075e65a009a719c4265bfc4bfc433962ffc3ft return (IPPROTO_DONE); 642161a075e65a009a719c4265bfc4bfc433962ffc3ft#else 64228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 642361a075e65a009a719c4265bfc4bfc433962ffc3ft#endif 64248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 64258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6426e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen ip = mtod(m, struct ip *); 64278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sh = (struct sctphdr *)((caddr_t)ip + off); 64288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tag = htonl(sh->v_tag); 64298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port); 64308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->m_pkthdr.flowid = flowid; 64318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->m_flags |= M_FLOWID; 64328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 64338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cpu_to_use = sctp_cpuarry[flowid % mp_ncpus]; 64348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_queue_to_mcore(m, off, cpu_to_use); 643561a075e65a009a719c4265bfc4bfc433962ffc3ft#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 643661a075e65a009a719c4265bfc4bfc433962ffc3ft return (IPPROTO_DONE); 643761a075e65a009a719c4265bfc4bfc433962ffc3ft#else 64388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 643961a075e65a009a719c4265bfc4bfc433962ffc3ft#endif 644032a191a90b5c914a02047389c5b3197e08fc9841tuexen } 64418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 64428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_input_with_port(m, off, 0); 644361a075e65a009a719c4265bfc4bfc433962ffc3ft#if defined(__FreeBSD__) && __FreeBSD_version >= 1100020 644461a075e65a009a719c4265bfc4bfc433962ffc3ft return (IPPROTO_DONE); 644561a075e65a009a719c4265bfc4bfc433962ffc3ft#endif 64468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 64478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6448b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif 6449