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_pcb.c 271230 2014-09-07 18:05:37Z tuexen $"); 368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h> 398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__ 408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/proc.h> 418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h> 438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h> 448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h> 458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h> 468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp.h> 478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_header.h> 488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_asconf.h> 498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_output.h> 508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_timer.h> 518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_bsd_addr.h> 52f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 803000 538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_dtrace_define.h> 54b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif 5548830a703639020b04dbea0128bc37fd8a8ab35et#if defined(INET) || defined(INET6) 560ac02f34d6041cd0018437596a5a9a94685e6919tuexen#if !defined(__Userspace_os_Windows) 578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/udp.h> 5881616c6a3e184f46276632dd15aa489cd06d94dftuexen#endif 596c632b3f6e570981666f8a3ff4be34eaf1735835t#endif 608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 611a0a058c2e170a7749bd410bdeff477bbd75a615tuexen#if defined(__Userspace__) 621a0a058c2e170a7749bd410bdeff477bbd75a615tuexen#include "user_ip6_var.h" 631a0a058c2e170a7749bd410bdeff477bbd75a615tuexen#else 648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet6/ip6_var.h> 658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 661a0a058c2e170a7749bd410bdeff477bbd75a615tuexen#endif 678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) 688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/sched.h> 698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/smp.h> 707ec5951ec04f35070419877f6b015541f6b9728dtuexen#include <sys/unistd.h> 718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 721a0a058c2e170a7749bd410bdeff477bbd75a615tuexen#if defined(__Userspace__) 731a0a058c2e170a7749bd410bdeff477bbd75a615tuexen#include <user_socketvar.h> 741a0a058c2e170a7749bd410bdeff477bbd75a615tuexen#endif 758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define APPLE_FILE_NO 4 788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenVNET_DEFINE(struct sctp_base_info, system_base_info); 828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_base_info system_base_info; 848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__) 87fcc753d4316c720a771fc1147a9b2bc6340a0469t#if defined(INET) || defined(INET6) 888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct ifaddrs *g_interfaces; 898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 90fcc753d4316c720a771fc1147a9b2bc6340a0469t#endif 918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* FIX: we don't handle multiple link local scopes */ 928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* "scopeless" replacement IN6_ARE_ADDR_EQUAL */ 938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenSCTP6_ARE_ADDR_EQUAL(struct sockaddr_in6 *a, struct sockaddr_in6 *b) 968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_EMBEDDED_V6_SCOPE 98c2ae94ce88da509bd10c652de26407ac5b2ee97ctuexen#if defined(__APPLE__) 998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct in6_addr tmp_a, tmp_b; 1008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tmp_a = a->sin6_addr; 1021ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) 1038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (in6_embedscope(&tmp_a, a, NULL, NULL) != 0) { 1041ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#else 1051ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen if (in6_embedscope(&tmp_a, a, NULL, NULL, NULL) != 0) { 1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 107b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tmp_b = b->sin6_addr; 1101ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) 1118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (in6_embedscope(&tmp_b, b, NULL, NULL) != 0) { 1121ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#else 1131ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen if (in6_embedscope(&tmp_b, b, NULL, NULL, NULL) != 0) { 1148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 115b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 1168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (IN6_ARE_ADDR_EQUAL(&tmp_a, &tmp_b)); 1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(SCTP_KAME) 1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 tmp_a, tmp_b; 1208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&tmp_a, a, sizeof(struct sockaddr_in6)); 1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sa6_embedscope(&tmp_a, MODULE_GLOBAL(ip6_use_defzone)) != 0) { 123b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&tmp_b, b, sizeof(struct sockaddr_in6)); 1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sa6_embedscope(&tmp_b, MODULE_GLOBAL(ip6_use_defzone)) != 0) { 127b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (IN6_ARE_ADDR_EQUAL(&tmp_a.sin6_addr, &tmp_b.sin6_addr)); 1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 1318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct in6_addr tmp_a, tmp_b; 1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tmp_a = a->sin6_addr; 1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (in6_embedscope(&tmp_a, a) != 0) { 135b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tmp_b = b->sin6_addr; 1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (in6_embedscope(&tmp_b, b) != 0) { 139b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (0); 1408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (IN6_ARE_ADDR_EQUAL(&tmp_a, &tmp_b)); 1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 1441a0a058c2e170a7749bd410bdeff477bbd75a615tuexen return (IN6_ARE_ADDR_EQUAL(&(a->sin6_addr), &(b->sin6_addr))); 1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */ 1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 1478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 1488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_fill_pcbinfo(struct sctp_pcbinfo *spcb) 1518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 1528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 1538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We really don't need to lock this, but I will just because it 1548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * does not hurt. 1558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 1568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RLOCK(); 1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen spcb->ep_count = SCTP_BASE_INFO(ipi_count_ep); 1588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen spcb->asoc_count = SCTP_BASE_INFO(ipi_count_asoc); 1598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen spcb->laddr_count = SCTP_BASE_INFO(ipi_count_laddr); 1608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen spcb->raddr_count = SCTP_BASE_INFO(ipi_count_raddr); 1618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen spcb->chk_count = SCTP_BASE_INFO(ipi_count_chunk); 1628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen spcb->readq_count = SCTP_BASE_INFO(ipi_count_readq); 1638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen spcb->stream_oque = SCTP_BASE_INFO(ipi_count_strmoq); 1648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen spcb->free_chunks = SCTP_BASE_INFO(ipi_free_chunks); 1658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 1668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 1678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 1687988ea8f0c067cf3757e798b473b1ae4d34b6dfdt/*- 1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Addresses are added to VRF's (Virtual Router's). For BSD we 1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * have only the default VRF 0. We maintain a hash list of 1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * VRF's. Each VRF has its own list of sctp_ifn's. Each of 1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * these has a list of addresses. When we add a new address 1738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to a VRF we lookup the ifn/ifn_index, if the ifn does 1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not exist we create it and add it to the list of IFN's 1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * within the VRF. Once we have the sctp_ifn, we add the 1768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address to the list. So we look something like: 1778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 1788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * hash-vrf-table 1798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * vrf-> ifn-> ifn -> ifn 1808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * vrf | 1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ... +--ifa-> ifa -> ifa 1828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * vrf 1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We keep these separate lists since the SCTP subsystem will 1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * point to these from its source address selection nets structure. 1868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * When an address is deleted it does not happen right away on 1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the SCTP side, it gets scheduled. What we do when a 1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * delete happens is immediately remove the address from 1898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the master list and decrement the refcount. As our 1908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * addip iterator works through and frees the src address 1918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * selection pointing to the sctp_ifa, eventually the refcount 1928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * will reach 0 and we will delete it. Note that it is assumed 1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that any locking on system level ifn/ifa is done at the 1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * caller of these functions and these routines will only 1958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * lock the SCTP structures as they add or delete things. 1968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 1978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Other notes on VRF concepts. 1988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - An endpoint can be in multiple VRF's 1998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - An association lives within a VRF and only one VRF. 2008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - Any incoming packet we can deduce the VRF for by 2018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * looking at the mbuf/pak inbound (for BSD its VRF=0 :D) 2028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - Any downward send call or connect call must supply the 2038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * VRF via ancillary data or via some sort of set default 2048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * VRF socket option call (again for BSD no brainer since 2058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the VRF is always 0). 2068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - An endpoint may add multiple VRF's to it. 2078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - Listening sockets can accept associations in any 2088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * of the VRF's they are in but the assoc will end up 2098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * in only one VRF (gotten from the packet or connect/send). 2108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 2118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_vrf * 2148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_allocate_vrf(int vrf_id) 2158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 216b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen struct sctp_vrf *vrf = NULL; 2178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrflist *bucket; 2188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* First allocate the VRF structure */ 2208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf = sctp_find_vrf(vrf_id); 2218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf) { 2228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Already allocated */ 2238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (vrf); 2248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(vrf, struct sctp_vrf *, sizeof(struct sctp_vrf), 2268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_VRF); 227e2828360ea9cf8951730d46f5c14626c9425cb30t if (vrf == NULL) { 228e2828360ea9cf8951730d46f5c14626c9425cb30t /* No memory */ 2298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 2308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("No memory for VRF:%d", vrf_id); 2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 2328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* setup the VRF */ 2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(vrf, 0, sizeof(struct sctp_vrf)); 2368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf->vrf_id = vrf_id; 2378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&vrf->ifnlist); 2388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf->total_ifa_count = 0; 2398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf->refcount = 0; 2408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now also setup table ids */ 2418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INIT_VRF_TABLEID(vrf); 2428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Init the HASH of addresses */ 2438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf->vrf_addr_hash = SCTP_HASH_INIT(SCTP_VRF_ADDR_HASH_SIZE, 2448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &vrf->vrf_addr_hashmark); 2458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf->vrf_addr_hash == NULL) { 246e2828360ea9cf8951730d46f5c14626c9425cb30t /* No memory */ 2478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("No memory for VRF:%d", vrf_id); 2498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 2508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(vrf, SCTP_M_VRF); 2518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 2528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Add it to the hash table */ 2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bucket = &SCTP_BASE_INFO(sctp_vrfhash)[(vrf_id & SCTP_BASE_INFO(hashvrfmark))]; 2568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(bucket, vrf, next_vrf); 2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&SCTP_BASE_INFO(ipi_count_vrfs), 1); 2588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (vrf); 2598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 2608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_ifn * 2638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_ifn(void *ifn, uint32_t ifn_index) 2648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifn *sctp_ifnp; 2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifnlist *hash_ifn_head; 2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We assume the lock is held for the addresses 2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if that's wrong problems could occur :-) 2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen hash_ifn_head = &SCTP_BASE_INFO(vrf_ifn_hash)[(ifn_index & SCTP_BASE_INFO(vrf_ifn_hashmark))]; 2728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(sctp_ifnp, hash_ifn_head, next_bucket) { 2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifnp->ifn_index == ifn_index) { 274b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (sctp_ifnp); 2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifnp->ifn_p && ifn && (sctp_ifnp->ifn_p == ifn)) { 277b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (sctp_ifnp); 2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 280b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (NULL); 2818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_vrf * 2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_vrf(uint32_t vrf_id) 2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrflist *bucket; 2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrf *liste; 2897988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bucket = &SCTP_BASE_INFO(sctp_vrfhash)[(vrf_id & SCTP_BASE_INFO(hashvrfmark))]; 2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(liste, bucket, next_vrf) { 2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf_id == liste->vrf_id) { 293b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (liste); 2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2997988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 3018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_free_vrf(struct sctp_vrf *vrf) 3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&vrf->refcount)) { 3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf->vrf_addr_hash) { 3058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(vrf->vrf_addr_hash, vrf->vrf_addr_hashmark); 3068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf->vrf_addr_hash = NULL; 3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We zero'd the count */ 3098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(vrf, next_vrf); 3108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(vrf, SCTP_M_VRF); 3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_vrfs), 1); 3128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3157988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_free_ifn(struct sctp_ifn *sctp_ifnp) 3188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&sctp_ifnp->refcount)) { 3208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We zero'd the count */ 3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifnp->vrf) { 3228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_vrf(sctp_ifnp->vrf); 3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(sctp_ifnp, SCTP_M_IFN); 3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_ifns), 1); 3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3297988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 3318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_update_ifn_mtu(uint32_t ifn_index, uint32_t mtu) 3328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifn *sctp_ifnp; 3348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp = sctp_find_ifn((void *)NULL, ifn_index); 3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifnp != NULL) { 3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->ifn_mtu = mtu; 3388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 3438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_free_ifa(struct sctp_ifa *sctp_ifap) 3448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&sctp_ifap->refcount)) { 3468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We zero'd the count */ 3478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap->ifn_p) { 3488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifn(sctp_ifap->ifn_p); 3498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(sctp_ifap, SCTP_M_IFA); 3518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_ifas), 1); 3528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3557988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_delete_ifn(struct sctp_ifn *sctp_ifnp, int hold_addr_lock) 3588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifn *found; 3608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen found = sctp_find_ifn(sctp_ifnp->ifn_p, sctp_ifnp->ifn_index); 3628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (found == NULL) { 3638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Not in the list.. sorry */ 3648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 3658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (hold_addr_lock == 0) 3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WLOCK(); 3688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(sctp_ifnp, next_bucket); 3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(sctp_ifnp, next_ifn); 3708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DEREGISTER_INTERFACE(sctp_ifnp->ifn_index, 3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->registered_af); 3728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (hold_addr_lock == 0) 3738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WUNLOCK(); 3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Take away the reference, and possibly free it */ 3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifn(sctp_ifnp); 3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 3778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3787988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 3798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_mark_ifa_addr_down(uint32_t vrf_id, struct sockaddr *addr, 3818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen const char *if_name, uint32_t ifn_index) 3828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 3838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrf *vrf; 3847988ea8f0c067cf3757e798b473b1ae4d34b6dfdt struct sctp_ifa *sctp_ifap; 3857988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 3868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RLOCK(); 3878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf = sctp_find_vrf(vrf_id); 3888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf == NULL) { 3898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Can't find vrf_id 0x%x\n", vrf_id); 3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED); 3948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap == NULL) { 3958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Can't find sctp_ifap for address\n"); 3968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 397e3e9f9e744e606ae7383d49fca282260adaed6cetuexen } 3988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap->ifn_p == NULL) { 3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "IFA has no IFN - can't mark unuseable\n"); 4008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (if_name) { 403e3e9f9e744e606ae7383d49fca282260adaed6cetuexen if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) != 0) { 4048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "IFN %s of IFA not the same as %s\n", 405e3e9f9e744e606ae7383d49fca282260adaed6cetuexen sctp_ifap->ifn_p->ifn_name, if_name); 4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 4078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap->ifn_p->ifn_index != ifn_index) { 4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "IFA owned by ifn_index:%d down command for ifn_index:%d - ignored\n", 4118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p->ifn_index, ifn_index); 4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 4138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 415e3e9f9e744e606ae7383d49fca282260adaed6cetuexen 4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->localifa_flags &= (~SCTP_ADDR_VALID); 4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->localifa_flags |= SCTP_ADDR_IFA_UNUSEABLE; 4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out: 4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RUNLOCK(); 4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4227988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_mark_ifa_addr_up(uint32_t vrf_id, struct sockaddr *addr, 4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen const char *if_name, uint32_t ifn_index) 4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrf *vrf; 4287988ea8f0c067cf3757e798b473b1ae4d34b6dfdt struct sctp_ifa *sctp_ifap; 4297988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RLOCK(); 4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf = sctp_find_vrf(vrf_id); 4328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf == NULL) { 4338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Can't find vrf_id 0x%x\n", vrf_id); 4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED); 4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap == NULL) { 4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Can't find sctp_ifap for address\n"); 4408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 441e3e9f9e744e606ae7383d49fca282260adaed6cetuexen } 4428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap->ifn_p == NULL) { 4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "IFA has no IFN - can't mark unuseable\n"); 4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (if_name) { 447e3e9f9e744e606ae7383d49fca282260adaed6cetuexen if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) != 0) { 4488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "IFN %s of IFA not the same as %s\n", 449e3e9f9e744e606ae7383d49fca282260adaed6cetuexen sctp_ifap->ifn_p->ifn_name, if_name); 4508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 4518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap->ifn_p->ifn_index != ifn_index) { 4548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "IFA owned by ifn_index:%d down command for ifn_index:%d - ignored\n", 4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p->ifn_index, ifn_index); 4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 4578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->localifa_flags &= (~SCTP_ADDR_IFA_UNUSEABLE); 4618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->localifa_flags |= SCTP_ADDR_VALID; 4628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out: 4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_RUNLOCK(); 4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4667988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*- 4688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Add an ifa to an ifn. 4698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Register the interface as necessary. 4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: ADDR write lock MUST be held. 4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 4728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_add_ifa_to_ifn(struct sctp_ifn *sctp_ifnp, struct sctp_ifa *sctp_ifap) 4748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 4758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int ifa_af; 4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&sctp_ifnp->ifalist, sctp_ifap, next_ifa); 4788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p = sctp_ifnp; 4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&sctp_ifap->ifn_p->refcount, 1); 4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update address counts */ 4818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->ifa_count++; 4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa_af = sctp_ifap->address.sa.sa_family; 4838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ifa_af) { 4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->num_v4++; 4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->num_v6++; 4928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 4938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 4948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 4958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 4968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifnp->ifa_count == 1) { 4988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* register the new interface */ 4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_REGISTER_INTERFACE(sctp_ifnp->ifn_index, ifa_af); 5008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->registered_af = ifa_af; 5018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 5038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5047988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 5058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*- 5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Remove an ifa from its ifn. 5078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If no more addresses exist, remove the ifn too. Otherwise, re-register 5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the interface based on the remaining address families left. 5098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: ADDR write lock MUST be held. 5108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_remove_ifa_from_ifn(struct sctp_ifa *sctp_ifap) 5138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(sctp_ifap, next_ifa); 5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap->ifn_p) { 5168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update address counts */ 5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p->ifa_count--; 5188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (sctp_ifap->address.sa.sa_family) { 5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 5218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p->num_v4--; 5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 5248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p->num_v6--; 5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 5308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (LIST_EMPTY(&sctp_ifap->ifn_p->ifalist)) { 5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove the ifn, possibly freeing it */ 5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_delete_ifn(sctp_ifap->ifn_p, SCTP_ADDR_LOCKED); 5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 5378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* re-register address family type, if needed */ 5388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sctp_ifap->ifn_p->num_v6 == 0) && 5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_ifap->ifn_p->registered_af == AF_INET6)) { 540b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen SCTP_DEREGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET6); 541b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen SCTP_REGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET); 5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p->registered_af = AF_INET; 5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((sctp_ifap->ifn_p->num_v4 == 0) && 5448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_ifap->ifn_p->registered_af == AF_INET)) { 545b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen SCTP_DEREGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET); 546b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen SCTP_REGISTER_INTERFACE(sctp_ifap->ifn_p->ifn_index, AF_INET6); 5478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p->registered_af = AF_INET6; 5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the ifn refcount */ 5508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifn(sctp_ifap->ifn_p); 5518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p = NULL; 5538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 5558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5567988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 5578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_ifa * 5588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, 5598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t ifn_type, const char *if_name, void *ifa, 5608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *addr, uint32_t ifa_flags, 5618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int dynamic_add) 5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 5638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrf *vrf; 5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifn *sctp_ifnp = NULL; 5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *sctp_ifap = NULL; 5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifalist *hash_addr_head; 5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifnlist *hash_ifn_head; 5688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t hash_of_addr; 5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int new_ifn_af = 0; 5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG 5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "vrf_id 0x%x: adding address: ", vrf_id); 5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_PCB4, addr); 5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 5758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WLOCK(); 5768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp = sctp_find_ifn(ifn, ifn_index); 5778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifnp) { 5788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf = sctp_ifnp->vrf; 5798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 5808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf = sctp_find_vrf(vrf_id); 5818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf == NULL) { 5828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf = sctp_allocate_vrf(vrf_id); 5838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf == NULL) { 5848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WUNLOCK(); 5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifnp == NULL) { 5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* build one and add it, can't hold lock 5918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * until after malloc done though. 5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 5938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WUNLOCK(); 5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(sctp_ifnp, struct sctp_ifn *, 5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_ifn), SCTP_M_IFN); 5968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifnp == NULL) { 5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("No memory for IFN"); 5998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(sctp_ifnp, 0, sizeof(struct sctp_ifn)); 6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->ifn_index = ifn_index; 6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->ifn_p = ifn; 6058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->ifn_type = ifn_type; 6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->refcount = 0; 6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->vrf = vrf; 6088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&vrf->refcount, 1); 6098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->ifn_mtu = SCTP_GATHER_MTU_FROM_IFN_INFO(ifn, ifn_index, addr->sa_family); 6108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (if_name != NULL) { 61166fcc3f11095eec33670d52fe801e60da73d3385tuexen snprintf(sctp_ifnp->ifn_name, SCTP_IFNAMSIZ, "%s", if_name); 6128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 61366fcc3f11095eec33670d52fe801e60da73d3385tuexen snprintf(sctp_ifnp->ifn_name, SCTP_IFNAMSIZ, "%s", "unknown"); 6148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen hash_ifn_head = &SCTP_BASE_INFO(vrf_ifn_hash)[(ifn_index & SCTP_BASE_INFO(vrf_ifn_hashmark))]; 6168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&sctp_ifnp->ifalist); 6178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WLOCK(); 6188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(hash_ifn_head, sctp_ifnp, next_bucket); 6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&vrf->ifnlist, sctp_ifnp, next_ifn); 6208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&SCTP_BASE_INFO(ipi_count_ifns), 1); 6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_ifn_af = 1; 6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED); 6248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap) { 6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Hmm, it already exists? */ 6268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sctp_ifap->ifn_p) && 6278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_ifap->ifn_p->ifn_index == ifn_index)) { 6288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Using existing ifn %s (0x%x) for ifa %p\n", 6298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p->ifn_name, ifn_index, 630ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)sctp_ifap); 6318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (new_ifn_af) { 6328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Remove the created one that we don't want */ 6338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_delete_ifn(sctp_ifnp, SCTP_ADDR_LOCKED); 6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap->localifa_flags & SCTP_BEING_DELETED) { 6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* easy to solve, just switch back to active */ 6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Clearing deleted ifa flag\n"); 6388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->localifa_flags = SCTP_ADDR_VALID; 6398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p = sctp_ifnp; 6408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&sctp_ifap->ifn_p->refcount, 1); 6418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen exit_stage_left: 6438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WUNLOCK(); 6448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (sctp_ifap); 6458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 6468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap->ifn_p) { 6478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 6488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * The last IFN gets the address, remove the 6498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * old one 6508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 6518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Moving ifa %p from %s (0x%x) to %s (0x%x)\n", 652ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)sctp_ifap, sctp_ifap->ifn_p->ifn_name, 6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p->ifn_index, if_name, 6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifn_index); 6558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove the address from the old ifn */ 6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_remove_ifa_from_ifn(sctp_ifap); 6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* move the address over to the new ifn */ 6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_ifa_to_ifn(sctp_ifnp, sctp_ifap); 659e2828360ea9cf8951730d46f5c14626c9425cb30t goto exit_stage_left; 6608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 6618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* repair ifnp which was NULL ? */ 6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->localifa_flags = SCTP_ADDR_VALID; 6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Repairing ifn %p for ifa %p\n", 664ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)sctp_ifnp, (void *)sctp_ifap); 6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_ifa_to_ifn(sctp_ifnp, sctp_ifap); 6668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto exit_stage_left; 6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WUNLOCK(); 6718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(sctp_ifap, struct sctp_ifa *, sizeof(struct sctp_ifa), SCTP_M_IFA); 6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap == NULL) { 6738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 6748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("No memory for IFA"); 6758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 6778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 6788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(sctp_ifap, 0, sizeof(struct sctp_ifa)); 6798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p = sctp_ifnp; 6808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&sctp_ifnp->refcount, 1); 6818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->vrf_id = vrf_id; 6828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifa = ifa; 683f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN 6848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&sctp_ifap->address, addr, addr->sa_len); 6858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 6867988ea8f0c067cf3757e798b473b1ae4d34b6dfdt switch (addr->sa_family) { 6877988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET 6887988ea8f0c067cf3757e798b473b1ae4d34b6dfdt case AF_INET: 6898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&sctp_ifap->address, addr, sizeof(struct sockaddr_in)); 6907988ea8f0c067cf3757e798b473b1ae4d34b6dfdt break; 6917988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif 6927988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET6 6937988ea8f0c067cf3757e798b473b1ae4d34b6dfdt case AF_INET6: 6948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&sctp_ifap->address, addr, sizeof(struct sockaddr_in6)); 6957988ea8f0c067cf3757e798b473b1ae4d34b6dfdt break; 6967988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif 6977988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__) 6987988ea8f0c067cf3757e798b473b1ae4d34b6dfdt case AF_CONN: 6999c7eb7309502064d69dc4d7f7a85d4abf2caac0dt memcpy(&sctp_ifap->address, addr, sizeof(struct sockaddr_conn)); 7007988ea8f0c067cf3757e798b473b1ae4d34b6dfdt break; 7017988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif 7027988ea8f0c067cf3757e798b473b1ae4d34b6dfdt default: 7037988ea8f0c067cf3757e798b473b1ae4d34b6dfdt /* TSNH */ 7047988ea8f0c067cf3757e798b473b1ae4d34b6dfdt break; 7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->localifa_flags = SCTP_ADDR_VALID | SCTP_ADDR_DEFER_USE; 7088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->flags = ifa_flags; 7098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Set scope */ 7108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (sctp_ifap->address.sa.sa_family) { 7118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 7128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 7138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 7157988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 716bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &sctp_ifap->address.sin; 7178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || 7188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (IN4_ISLOOPBACK_ADDRESS(&sin->sin_addr))) { 7198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->src_is_loop = 1; 7208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { 7228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->src_is_priv = 1; 7238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->num_v4++; 7258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (new_ifn_af) 7268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_ifn_af = AF_INET; 7278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 7318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 7328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 7338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ok to use deprecated addresses? */ 7348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 7357988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 736bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &sctp_ifap->address.sin6; 7378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_IFN_IS_IFT_LOOP(sctp_ifap->ifn_p) || 7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))) { 7398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->src_is_loop = 1; 7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 7428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->src_is_priv = 1; 7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->num_v6++; 7458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (new_ifn_af) 7468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_ifn_af = AF_INET6; 7478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 7507988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__) 7517988ea8f0c067cf3757e798b473b1ae4d34b6dfdt case AF_CONN: 7527988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (new_ifn_af) 7537988ea8f0c067cf3757e798b473b1ae4d34b6dfdt new_ifn_af = AF_CONN; 7547988ea8f0c067cf3757e798b473b1ae4d34b6dfdt break; 7557988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif 7568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_ifn_af = 0; 7588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen hash_of_addr = sctp_get_ifa_hash_val(&sctp_ifap->address.sa); 7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sctp_ifap->src_is_priv == 0) && 7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_ifap->src_is_loop == 0)) { 7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->src_is_glob = 1; 7658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WLOCK(); 7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen hash_addr_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_addr_hashmark)]; 7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(hash_addr_head, sctp_ifap, next_bucket); 7698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->refcount = 1; 7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&sctp_ifnp->ifalist, sctp_ifap, next_ifa); 7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->ifa_count++; 7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf->total_ifa_count++; 7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&SCTP_BASE_INFO(ipi_count_ifas), 1); 7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (new_ifn_af) { 7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_REGISTER_INTERFACE(ifn_index, new_ifn_af); 7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifnp->registered_af = new_ifn_af; 7778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WUNLOCK(); 7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (dynamic_add) { 7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Bump up the refcount so that when the timer 7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * completes it will drop back down. 7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *wi; 7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&sctp_ifap->refcount, 1); 7868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 7878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (wi == NULL) { 7888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 7898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Gak, what can we do? We have lost an address 7908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * change can you say HOSED? 7918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Lost an address change?\n"); 7938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Opps, must decrement the count */ 7948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_del_addr_from_vrf(vrf_id, addr, ifn_index, 7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if_name); 7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 7978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INCR_LADDR_COUNT(); 7998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(wi, sizeof(*wi)); 8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&wi->start_time); 8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wi->ifa = sctp_ifap; 8028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wi->action = SCTP_ADD_IP_ADDRESS; 80332a191a90b5c914a02047389c5b3197e08fc9841tuexen 8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_WQ_ADDR_LOCK(); 8058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); 8068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_WQ_ADDR_UNLOCK(); 8078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 8098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_inpcb *)NULL, 8108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_tcb *)NULL, 8118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_nets *)NULL); 8128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 8138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* it's ready for use */ 8148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->localifa_flags &= ~SCTP_ADDR_DEFER_USE; 8158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (sctp_ifap); 8178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 8188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 8208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_del_addr_from_vrf(uint32_t vrf_id, struct sockaddr *addr, 8218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t ifn_index, const char *if_name) 8228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 8238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrf *vrf; 8248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *sctp_ifap = NULL; 8258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WLOCK(); 8278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf = sctp_find_vrf(vrf_id); 8288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (vrf == NULL) { 8298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Can't find vrf_id 0x%x\n", vrf_id); 8308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out_now; 8318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG 8348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "vrf_id 0x%x: deleting address:", vrf_id); 8358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_PCB4, addr); 8368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 8378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap = sctp_find_ifa_by_addr(addr, vrf->vrf_id, SCTP_ADDR_LOCKED); 8388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap) { 8398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Validate the delete */ 8408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap->ifn_p) { 84166fcc3f11095eec33670d52fe801e60da73d3385tuexen int valid = 0; 8428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 8438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * The name has priority over the ifn_index 8448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if its given. We do this especially for 8458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * panda who might recycle indexes fast. 8468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 8478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (if_name) { 84866fcc3f11095eec33670d52fe801e60da73d3385tuexen if (strncmp(if_name, sctp_ifap->ifn_p->ifn_name, SCTP_IFNAMSIZ) == 0) { 84966fcc3f11095eec33670d52fe801e60da73d3385tuexen /* They match its a correct delete */ 85066fcc3f11095eec33670d52fe801e60da73d3385tuexen valid = 1; 8518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!valid) { 8548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* last ditch check ifn_index */ 8558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifn_index == sctp_ifap->ifn_p->ifn_index) { 8568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen valid = 1; 8578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!valid) { 8608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "ifn:%d ifname:%s does not match addresses\n", 8618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifn_index, ((if_name == NULL) ? "NULL" : if_name)); 8628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "ifn:%d ifname:%s - ignoring delete\n", 8638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->ifn_p->ifn_index, sctp_ifap->ifn_p->ifn_name); 8648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WUNLOCK(); 8658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 8668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 868ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t SCTPDBG(SCTP_DEBUG_PCB4, "Deleting ifa %p\n", (void *)sctp_ifap); 8698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifap->localifa_flags &= SCTP_ADDR_VALID; 870368d86efa422ae7e549399f8c35783c0e80232f0t /* 871368d86efa422ae7e549399f8c35783c0e80232f0t * We don't set the flag. This means that the structure will 872368d86efa422ae7e549399f8c35783c0e80232f0t * hang around in EP's that have bound specific to it until 873368d86efa422ae7e549399f8c35783c0e80232f0t * they close. This gives us TCP like behavior if someone 874368d86efa422ae7e549399f8c35783c0e80232f0t * removes an address (or for that matter adds it right back). 875368d86efa422ae7e549399f8c35783c0e80232f0t */ 876368d86efa422ae7e549399f8c35783c0e80232f0t /* sctp_ifap->localifa_flags |= SCTP_BEING_DELETED; */ 8778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf->total_ifa_count--; 8788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(sctp_ifap, next_bucket); 8798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_remove_ifa_from_ifn(sctp_ifap); 8808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG 8828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else { 8838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Del Addr-ifn:%d Could not find address:", 8848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifn_index); 8858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr); 8868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 8878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 8888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out_now: 8908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_WUNLOCK(); 8918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifap) { 8928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *wi; 8938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 8948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 8958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (wi == NULL) { 8968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 8978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Gak, what can we do? We have lost an address 8988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * change can you say HOSED? 8998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB4, "Lost an address change?\n"); 9018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Oops, must decrement the count */ 9038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(sctp_ifap); 9048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INCR_LADDR_COUNT(); 9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(wi, sizeof(*wi)); 9088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&wi->start_time); 9098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wi->ifa = sctp_ifap; 9108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wi->action = SCTP_DEL_IP_ADDRESS; 9118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_WQ_ADDR_LOCK(); 9128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 9138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Should this really be a tailq? As it is we will process the 9148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * newest first :-0 9158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 9168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); 9178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_WQ_ADDR_UNLOCK(); 9188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 9208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_inpcb *)NULL, 9218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_tcb *)NULL, 9228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_nets *)NULL); 9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 9248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 9258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 9268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 9278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 928f57cf83923be449d11806a31f62bcc17e58832d6tstatic int 929f57cf83923be449d11806a31f62bcc17e58832d6tsctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to) 930f57cf83923be449d11806a31f62bcc17e58832d6t{ 931fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t int loopback_scope; 932fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#if defined(INET) 933fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t int ipv4_local_scope, ipv4_addr_legal; 934fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#endif 935fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#if defined(INET6) 936fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t int local_scope, site_scope, ipv6_addr_legal; 937fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#endif 938f57cf83923be449d11806a31f62bcc17e58832d6t#if defined(__Userspace__) 939f57cf83923be449d11806a31f62bcc17e58832d6t int conn_addr_legal; 940f57cf83923be449d11806a31f62bcc17e58832d6t#endif 941f57cf83923be449d11806a31f62bcc17e58832d6t struct sctp_vrf *vrf; 942f57cf83923be449d11806a31f62bcc17e58832d6t struct sctp_ifn *sctp_ifn; 943f57cf83923be449d11806a31f62bcc17e58832d6t struct sctp_ifa *sctp_ifa; 944f57cf83923be449d11806a31f62bcc17e58832d6t 945f57cf83923be449d11806a31f62bcc17e58832d6t loopback_scope = stcb->asoc.scope.loopback_scope; 946fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#if defined(INET) 947f57cf83923be449d11806a31f62bcc17e58832d6t ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; 948fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; 949fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#endif 950fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#if defined(INET6) 951f57cf83923be449d11806a31f62bcc17e58832d6t local_scope = stcb->asoc.scope.local_scope; 952f57cf83923be449d11806a31f62bcc17e58832d6t site_scope = stcb->asoc.scope.site_scope; 953f57cf83923be449d11806a31f62bcc17e58832d6t ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; 954fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#endif 955f57cf83923be449d11806a31f62bcc17e58832d6t#if defined(__Userspace__) 956f57cf83923be449d11806a31f62bcc17e58832d6t conn_addr_legal = stcb->asoc.scope.conn_addr_legal; 957f57cf83923be449d11806a31f62bcc17e58832d6t#endif 958f57cf83923be449d11806a31f62bcc17e58832d6t 959f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_IPI_ADDR_RLOCK(); 960f57cf83923be449d11806a31f62bcc17e58832d6t vrf = sctp_find_vrf(stcb->asoc.vrf_id); 961f57cf83923be449d11806a31f62bcc17e58832d6t if (vrf == NULL) { 962f57cf83923be449d11806a31f62bcc17e58832d6t /* no vrf, no addresses */ 963f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_IPI_ADDR_RUNLOCK(); 964f57cf83923be449d11806a31f62bcc17e58832d6t return (0); 965f57cf83923be449d11806a31f62bcc17e58832d6t } 966f57cf83923be449d11806a31f62bcc17e58832d6t 967f57cf83923be449d11806a31f62bcc17e58832d6t if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 968f57cf83923be449d11806a31f62bcc17e58832d6t LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 969f57cf83923be449d11806a31f62bcc17e58832d6t if ((loopback_scope == 0) && 970f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 971f57cf83923be449d11806a31f62bcc17e58832d6t continue; 972f57cf83923be449d11806a31f62bcc17e58832d6t } 973f57cf83923be449d11806a31f62bcc17e58832d6t LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 974f57cf83923be449d11806a31f62bcc17e58832d6t if (sctp_is_addr_restricted(stcb, sctp_ifa) && 975f57cf83923be449d11806a31f62bcc17e58832d6t (!sctp_is_addr_pending(stcb, sctp_ifa))) { 976f57cf83923be449d11806a31f62bcc17e58832d6t /* We allow pending addresses, where we 977f57cf83923be449d11806a31f62bcc17e58832d6t * have sent an asconf-add to be considered 978f57cf83923be449d11806a31f62bcc17e58832d6t * valid. 979f57cf83923be449d11806a31f62bcc17e58832d6t */ 980f57cf83923be449d11806a31f62bcc17e58832d6t continue; 981f57cf83923be449d11806a31f62bcc17e58832d6t } 9821c63369d5557c6a5b5dbbf5beb95ecda81abc548t if (sctp_ifa->address.sa.sa_family != to->sa_family) { 9831c63369d5557c6a5b5dbbf5beb95ecda81abc548t continue; 9841c63369d5557c6a5b5dbbf5beb95ecda81abc548t } 985f57cf83923be449d11806a31f62bcc17e58832d6t switch (sctp_ifa->address.sa.sa_family) { 986f57cf83923be449d11806a31f62bcc17e58832d6t#ifdef INET 987f57cf83923be449d11806a31f62bcc17e58832d6t case AF_INET: 988f57cf83923be449d11806a31f62bcc17e58832d6t if (ipv4_addr_legal) { 989f57cf83923be449d11806a31f62bcc17e58832d6t struct sockaddr_in *sin, *rsin; 990f57cf83923be449d11806a31f62bcc17e58832d6t 991f57cf83923be449d11806a31f62bcc17e58832d6t sin = &sctp_ifa->address.sin; 992f57cf83923be449d11806a31f62bcc17e58832d6t rsin = (struct sockaddr_in *)to; 993f57cf83923be449d11806a31f62bcc17e58832d6t if ((ipv4_local_scope == 0) && 994f57cf83923be449d11806a31f62bcc17e58832d6t IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 995f57cf83923be449d11806a31f62bcc17e58832d6t continue; 996f57cf83923be449d11806a31f62bcc17e58832d6t } 997998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 998998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, 999998635733088fde643e6d807fa76679c4ceeaa00t &sin->sin_addr) != 0) { 1000998635733088fde643e6d807fa76679c4ceeaa00t continue; 1001998635733088fde643e6d807fa76679c4ceeaa00t } 1002998635733088fde643e6d807fa76679c4ceeaa00t#endif 1003f57cf83923be449d11806a31f62bcc17e58832d6t if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) { 1004f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_IPI_ADDR_RUNLOCK(); 1005f57cf83923be449d11806a31f62bcc17e58832d6t return (1); 1006f57cf83923be449d11806a31f62bcc17e58832d6t } 1007f57cf83923be449d11806a31f62bcc17e58832d6t } 1008f57cf83923be449d11806a31f62bcc17e58832d6t break; 1009f57cf83923be449d11806a31f62bcc17e58832d6t#endif 1010f57cf83923be449d11806a31f62bcc17e58832d6t#ifdef INET6 1011f57cf83923be449d11806a31f62bcc17e58832d6t case AF_INET6: 1012f57cf83923be449d11806a31f62bcc17e58832d6t if (ipv6_addr_legal) { 1013f57cf83923be449d11806a31f62bcc17e58832d6t struct sockaddr_in6 *sin6, *rsin6; 1014f57cf83923be449d11806a31f62bcc17e58832d6t#if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME) 1015f57cf83923be449d11806a31f62bcc17e58832d6t struct sockaddr_in6 lsa6; 1016f57cf83923be449d11806a31f62bcc17e58832d6t#endif 1017f57cf83923be449d11806a31f62bcc17e58832d6t sin6 = &sctp_ifa->address.sin6; 1018f57cf83923be449d11806a31f62bcc17e58832d6t rsin6 = (struct sockaddr_in6 *)to; 1019998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 1020998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred, 1021998635733088fde643e6d807fa76679c4ceeaa00t &sin6->sin6_addr) != 0) { 1022998635733088fde643e6d807fa76679c4ceeaa00t continue; 1023998635733088fde643e6d807fa76679c4ceeaa00t } 1024998635733088fde643e6d807fa76679c4ceeaa00t#endif 1025f57cf83923be449d11806a31f62bcc17e58832d6t if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1026f57cf83923be449d11806a31f62bcc17e58832d6t if (local_scope == 0) 1027f57cf83923be449d11806a31f62bcc17e58832d6t continue; 1028f57cf83923be449d11806a31f62bcc17e58832d6t#if defined(SCTP_EMBEDDED_V6_SCOPE) 1029f57cf83923be449d11806a31f62bcc17e58832d6t if (sin6->sin6_scope_id == 0) { 1030f57cf83923be449d11806a31f62bcc17e58832d6t#ifdef SCTP_KAME 1031f57cf83923be449d11806a31f62bcc17e58832d6t if (sa6_recoverscope(sin6) != 0) 1032f57cf83923be449d11806a31f62bcc17e58832d6t continue; 1033f57cf83923be449d11806a31f62bcc17e58832d6t#else 1034f57cf83923be449d11806a31f62bcc17e58832d6t lsa6 = *sin6; 1035f57cf83923be449d11806a31f62bcc17e58832d6t if (in6_recoverscope(&lsa6, 1036f57cf83923be449d11806a31f62bcc17e58832d6t &lsa6.sin6_addr, 1037f57cf83923be449d11806a31f62bcc17e58832d6t NULL)) 1038f57cf83923be449d11806a31f62bcc17e58832d6t continue; 1039f57cf83923be449d11806a31f62bcc17e58832d6t sin6 = &lsa6; 1040f57cf83923be449d11806a31f62bcc17e58832d6t#endif /* SCTP_KAME */ 1041f57cf83923be449d11806a31f62bcc17e58832d6t } 1042f57cf83923be449d11806a31f62bcc17e58832d6t#endif /* SCTP_EMBEDDED_V6_SCOPE */ 1043f57cf83923be449d11806a31f62bcc17e58832d6t } 1044f57cf83923be449d11806a31f62bcc17e58832d6t if ((site_scope == 0) && 1045f57cf83923be449d11806a31f62bcc17e58832d6t (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { 1046f57cf83923be449d11806a31f62bcc17e58832d6t continue; 1047f57cf83923be449d11806a31f62bcc17e58832d6t } 1048f57cf83923be449d11806a31f62bcc17e58832d6t if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) { 1049f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_IPI_ADDR_RUNLOCK(); 1050f57cf83923be449d11806a31f62bcc17e58832d6t return (1); 1051f57cf83923be449d11806a31f62bcc17e58832d6t } 1052f57cf83923be449d11806a31f62bcc17e58832d6t } 1053f57cf83923be449d11806a31f62bcc17e58832d6t break; 1054f57cf83923be449d11806a31f62bcc17e58832d6t#endif 1055f57cf83923be449d11806a31f62bcc17e58832d6t#if defined(__Userspace__) 1056f57cf83923be449d11806a31f62bcc17e58832d6t case AF_CONN: 1057f57cf83923be449d11806a31f62bcc17e58832d6t if (conn_addr_legal) { 1058f57cf83923be449d11806a31f62bcc17e58832d6t struct sockaddr_conn *sconn, *rsconn; 1059f57cf83923be449d11806a31f62bcc17e58832d6t 1060f57cf83923be449d11806a31f62bcc17e58832d6t sconn = &sctp_ifa->address.sconn; 1061f57cf83923be449d11806a31f62bcc17e58832d6t rsconn = (struct sockaddr_conn *)to; 1062f57cf83923be449d11806a31f62bcc17e58832d6t if (sconn->sconn_addr == rsconn->sconn_addr) { 1063f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_IPI_ADDR_RUNLOCK(); 1064f57cf83923be449d11806a31f62bcc17e58832d6t return (1); 1065f57cf83923be449d11806a31f62bcc17e58832d6t } 1066f57cf83923be449d11806a31f62bcc17e58832d6t } 1067f57cf83923be449d11806a31f62bcc17e58832d6t break; 1068f57cf83923be449d11806a31f62bcc17e58832d6t#endif 1069f57cf83923be449d11806a31f62bcc17e58832d6t default: 1070f57cf83923be449d11806a31f62bcc17e58832d6t /* TSNH */ 1071f57cf83923be449d11806a31f62bcc17e58832d6t break; 1072f57cf83923be449d11806a31f62bcc17e58832d6t } 1073f57cf83923be449d11806a31f62bcc17e58832d6t } 1074f57cf83923be449d11806a31f62bcc17e58832d6t } 1075f57cf83923be449d11806a31f62bcc17e58832d6t } else { 1076f57cf83923be449d11806a31f62bcc17e58832d6t struct sctp_laddr *laddr; 1077f57cf83923be449d11806a31f62bcc17e58832d6t 1078f57cf83923be449d11806a31f62bcc17e58832d6t LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) { 1079f57cf83923be449d11806a31f62bcc17e58832d6t if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { 1080f57cf83923be449d11806a31f62bcc17e58832d6t SCTPDBG(SCTP_DEBUG_PCB1, "ifa being deleted\n"); 1081f57cf83923be449d11806a31f62bcc17e58832d6t continue; 1082f57cf83923be449d11806a31f62bcc17e58832d6t } 1083f57cf83923be449d11806a31f62bcc17e58832d6t if (sctp_is_addr_restricted(stcb, laddr->ifa) && 1084f57cf83923be449d11806a31f62bcc17e58832d6t (!sctp_is_addr_pending(stcb, laddr->ifa))) { 1085f57cf83923be449d11806a31f62bcc17e58832d6t /* We allow pending addresses, where we 1086f57cf83923be449d11806a31f62bcc17e58832d6t * have sent an asconf-add to be considered 1087f57cf83923be449d11806a31f62bcc17e58832d6t * valid. 1088f57cf83923be449d11806a31f62bcc17e58832d6t */ 1089f57cf83923be449d11806a31f62bcc17e58832d6t continue; 1090f57cf83923be449d11806a31f62bcc17e58832d6t } 1091f57cf83923be449d11806a31f62bcc17e58832d6t if (laddr->ifa->address.sa.sa_family != to->sa_family) { 1092f57cf83923be449d11806a31f62bcc17e58832d6t continue; 1093f57cf83923be449d11806a31f62bcc17e58832d6t } 1094f57cf83923be449d11806a31f62bcc17e58832d6t switch (to->sa_family) { 1095f57cf83923be449d11806a31f62bcc17e58832d6t#ifdef INET 1096f57cf83923be449d11806a31f62bcc17e58832d6t case AF_INET: 1097f57cf83923be449d11806a31f62bcc17e58832d6t { 1098f57cf83923be449d11806a31f62bcc17e58832d6t struct sockaddr_in *sin, *rsin; 1099f57cf83923be449d11806a31f62bcc17e58832d6t 1100bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &laddr->ifa->address.sin; 1101f57cf83923be449d11806a31f62bcc17e58832d6t rsin = (struct sockaddr_in *)to; 1102f57cf83923be449d11806a31f62bcc17e58832d6t if (sin->sin_addr.s_addr == rsin->sin_addr.s_addr) { 1103f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_IPI_ADDR_RUNLOCK(); 1104f57cf83923be449d11806a31f62bcc17e58832d6t return (1); 1105f57cf83923be449d11806a31f62bcc17e58832d6t } 1106f57cf83923be449d11806a31f62bcc17e58832d6t break; 1107f57cf83923be449d11806a31f62bcc17e58832d6t } 1108f57cf83923be449d11806a31f62bcc17e58832d6t#endif 1109f57cf83923be449d11806a31f62bcc17e58832d6t#ifdef INET6 1110f57cf83923be449d11806a31f62bcc17e58832d6t case AF_INET6: 1111f57cf83923be449d11806a31f62bcc17e58832d6t { 1112f57cf83923be449d11806a31f62bcc17e58832d6t struct sockaddr_in6 *sin6, *rsin6; 1113f57cf83923be449d11806a31f62bcc17e58832d6t 1114bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &laddr->ifa->address.sin6; 1115f57cf83923be449d11806a31f62bcc17e58832d6t rsin6 = (struct sockaddr_in6 *)to; 1116f57cf83923be449d11806a31f62bcc17e58832d6t if (SCTP6_ARE_ADDR_EQUAL(sin6, rsin6)) { 1117f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_IPI_ADDR_RUNLOCK(); 1118f57cf83923be449d11806a31f62bcc17e58832d6t return (1); 1119f57cf83923be449d11806a31f62bcc17e58832d6t } 1120f57cf83923be449d11806a31f62bcc17e58832d6t break; 1121f57cf83923be449d11806a31f62bcc17e58832d6t } 1122f57cf83923be449d11806a31f62bcc17e58832d6t 1123f57cf83923be449d11806a31f62bcc17e58832d6t#endif 1124f57cf83923be449d11806a31f62bcc17e58832d6t#if defined(__Userspace__) 1125f57cf83923be449d11806a31f62bcc17e58832d6t case AF_CONN: 1126f57cf83923be449d11806a31f62bcc17e58832d6t { 1127f57cf83923be449d11806a31f62bcc17e58832d6t struct sockaddr_conn *sconn, *rsconn; 1128f57cf83923be449d11806a31f62bcc17e58832d6t 1129bfb1bf7e665a02b48026482bf33d05c83dfad73bt sconn = &laddr->ifa->address.sconn; 1130f57cf83923be449d11806a31f62bcc17e58832d6t rsconn = (struct sockaddr_conn *)to; 1131f57cf83923be449d11806a31f62bcc17e58832d6t if (sconn->sconn_addr == rsconn->sconn_addr) { 1132f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_IPI_ADDR_RUNLOCK(); 1133f57cf83923be449d11806a31f62bcc17e58832d6t return (1); 1134f57cf83923be449d11806a31f62bcc17e58832d6t } 1135f57cf83923be449d11806a31f62bcc17e58832d6t break; 1136f57cf83923be449d11806a31f62bcc17e58832d6t } 1137f57cf83923be449d11806a31f62bcc17e58832d6t#endif 1138f57cf83923be449d11806a31f62bcc17e58832d6t default: 1139f57cf83923be449d11806a31f62bcc17e58832d6t /* TSNH */ 1140f57cf83923be449d11806a31f62bcc17e58832d6t break; 1141f57cf83923be449d11806a31f62bcc17e58832d6t } 1142f57cf83923be449d11806a31f62bcc17e58832d6t 1143f57cf83923be449d11806a31f62bcc17e58832d6t } 1144f57cf83923be449d11806a31f62bcc17e58832d6t } 1145f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_IPI_ADDR_RUNLOCK(); 1146f57cf83923be449d11806a31f62bcc17e58832d6t return (0); 1147f57cf83923be449d11806a31f62bcc17e58832d6t} 1148f57cf83923be449d11806a31f62bcc17e58832d6t 1149f57cf83923be449d11806a31f62bcc17e58832d6t 11508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_tcb * 11518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from, 11528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *to, struct sctp_nets **netp, uint32_t vrf_id) 11538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 11548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /**** ASSUMES THE CALLER holds the INP_INFO_RLOCK */ 11558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 11568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If we support the TCP model, then we must now dig through to see 11578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if we can find our endpoint in the list of tcp ep's. 11588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 11598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t lport, rport; 11608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctppcbhead *ephead; 11618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 11628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 11638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 11648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 11658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 11668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int fnd, i; 11678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 11687988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 11698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((to == NULL) || (from == NULL)) { 11708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 11718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 11738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (to->sa_family) { 11748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 11758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 11768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from->sa_family == AF_INET) { 11778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lport = ((struct sockaddr_in *)to)->sin_port; 11788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rport = ((struct sockaddr_in *)from)->sin_port; 11798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 11808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 11818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 11848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 11858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 11868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from->sa_family == AF_INET6) { 11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lport = ((struct sockaddr_in6 *)to)->sin6_port; 11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rport = ((struct sockaddr_in6 *)from)->sin6_port; 11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 11908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 11918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 11928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 11938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 119475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__) 119575cd23222c96d5ebe5a9082c57a263f917f1462btuexen case AF_CONN: 119675cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (from->sa_family == AF_CONN) { 119775cd23222c96d5ebe5a9082c57a263f917f1462btuexen lport = ((struct sockaddr_conn *)to)->sconn_port; 119875cd23222c96d5ebe5a9082c57a263f917f1462btuexen rport = ((struct sockaddr_conn *)from)->sconn_port; 119975cd23222c96d5ebe5a9082c57a263f917f1462btuexen } else { 120075cd23222c96d5ebe5a9082c57a263f917f1462btuexen return (NULL); 120175cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 120275cd23222c96d5ebe5a9082c57a263f917f1462btuexen break; 120375cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 12048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 12068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ephead = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport | rport), SCTP_BASE_INFO(hashtcpmark))]; 12088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 12098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok now for each of the guys in this bucket we must look and see: 12108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * - Does the remote port match. - Does there single association's 12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * addresses match this address (to). If so we update p_ep to point 12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to this ep and return the tcb from it. 12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(inp, ephead, sctp_hash) { 12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(inp); 12168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lport != inp->sctp_lport) { 12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 12228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 12238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1224998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 1225998635733088fde643e6d807fa76679c4ceeaa00t switch (to->sa_family) { 1226998635733088fde643e6d807fa76679c4ceeaa00t#ifdef INET 1227998635733088fde643e6d807fa76679c4ceeaa00t case AF_INET: 1228998635733088fde643e6d807fa76679c4ceeaa00t { 1229998635733088fde643e6d807fa76679c4ceeaa00t struct sockaddr_in *sin; 1230998635733088fde643e6d807fa76679c4ceeaa00t 1231998635733088fde643e6d807fa76679c4ceeaa00t sin = (struct sockaddr_in *)to; 1232998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip4(inp->ip_inp.inp.inp_cred, 1233998635733088fde643e6d807fa76679c4ceeaa00t &sin->sin_addr) != 0) { 1234998635733088fde643e6d807fa76679c4ceeaa00t SCTP_INP_RUNLOCK(inp); 1235998635733088fde643e6d807fa76679c4ceeaa00t continue; 1236998635733088fde643e6d807fa76679c4ceeaa00t } 1237998635733088fde643e6d807fa76679c4ceeaa00t break; 1238998635733088fde643e6d807fa76679c4ceeaa00t } 1239998635733088fde643e6d807fa76679c4ceeaa00t#endif 1240998635733088fde643e6d807fa76679c4ceeaa00t#ifdef INET6 1241998635733088fde643e6d807fa76679c4ceeaa00t case AF_INET6: 1242998635733088fde643e6d807fa76679c4ceeaa00t { 1243998635733088fde643e6d807fa76679c4ceeaa00t struct sockaddr_in6 *sin6; 1244998635733088fde643e6d807fa76679c4ceeaa00t 1245998635733088fde643e6d807fa76679c4ceeaa00t sin6 = (struct sockaddr_in6 *)to; 1246998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip6(inp->ip_inp.inp.inp_cred, 1247998635733088fde643e6d807fa76679c4ceeaa00t &sin6->sin6_addr) != 0) { 1248998635733088fde643e6d807fa76679c4ceeaa00t SCTP_INP_RUNLOCK(inp); 1249998635733088fde643e6d807fa76679c4ceeaa00t continue; 1250998635733088fde643e6d807fa76679c4ceeaa00t } 1251998635733088fde643e6d807fa76679c4ceeaa00t break; 1252998635733088fde643e6d807fa76679c4ceeaa00t } 1253998635733088fde643e6d807fa76679c4ceeaa00t#endif 1254998635733088fde643e6d807fa76679c4ceeaa00t default: 1255998635733088fde643e6d807fa76679c4ceeaa00t SCTP_INP_RUNLOCK(inp); 1256998635733088fde643e6d807fa76679c4ceeaa00t continue; 1257998635733088fde643e6d807fa76679c4ceeaa00t } 1258998635733088fde643e6d807fa76679c4ceeaa00t#endif 12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 0; 12610ac02f34d6041cd0018437596a5a9a94685e6919tuexen for (i = 0; i < inp->num_vrfs; i++) { 12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->m_vrf_ids[i] == vrf_id) { 12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (fnd == 0) { 12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->def_vrf_id != vrf_id) { 12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* check to see if the ep has one of the addresses */ 12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 12798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We are NOT bound all, so look further */ 12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int match = 0; 12818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == NULL) { 12858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", __FUNCTION__); 12868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { 12898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB1, "ifa being deleted\n"); 12908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 12918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa->address.sa.sa_family == 12938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to->sa_family) { 12948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* see if it matches */ 12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 12968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from->sa_family == AF_INET) { 12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *intf_addr, *sin; 12988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen intf_addr = &laddr->ifa->address.sin; 13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = (struct sockaddr_in *)to; 13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == 13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen intf_addr->sin_addr.s_addr) { 13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen match = 1; 13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from->sa_family == AF_INET6) { 13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *intf_addr6; 13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *) 13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen to; 13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen intf_addr6 = &laddr->ifa->address.sin6; 13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP6_ARE_ADDR_EQUAL(sin6, 13188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen intf_addr6)) { 13198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen match = 1; 13208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 13218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 132475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__) 132575cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (from->sa_family == AF_CONN) { 132675cd23222c96d5ebe5a9082c57a263f917f1462btuexen struct sockaddr_conn *intf_addr, *sconn; 132775cd23222c96d5ebe5a9082c57a263f917f1462btuexen 132875cd23222c96d5ebe5a9082c57a263f917f1462btuexen intf_addr = &laddr->ifa->address.sconn; 132975cd23222c96d5ebe5a9082c57a263f917f1462btuexen sconn = (struct sockaddr_conn *)to; 133075cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (sconn->sconn_addr == 133175cd23222c96d5ebe5a9082c57a263f917f1462btuexen intf_addr->sconn_addr) { 133275cd23222c96d5ebe5a9082c57a263f917f1462btuexen match = 1; 133375cd23222c96d5ebe5a9082c57a263f917f1462btuexen break; 133475cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 133575cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 133675cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (match == 0) { 13408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This endpoint does not have this address */ 13418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 13428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 13438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 13468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok if we hit here the ep has the address, does it hold 13478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the tcb? 13488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 1349f57cf83923be449d11806a31f62bcc17e58832d6t /* XXX: Why don't we TAILQ_FOREACH through sctp_asoc_list? */ 13508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb = LIST_FIRST(&inp->sctp_asoc_list); 13518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 13528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 13538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 13548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 1356f57cf83923be449d11806a31f62bcc17e58832d6t if (!sctp_does_stcb_own_this_addr(stcb, to)) { 1357f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_TCB_UNLOCK(stcb); 1358f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_INP_RUNLOCK(inp); 1359f57cf83923be449d11806a31f62bcc17e58832d6t continue; 1360f57cf83923be449d11806a31f62bcc17e58832d6t } 13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->rport != rport) { 13628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remote port does not match. */ 136332a191a90b5c914a02047389c5b3197e08fc9841tuexen SCTP_TCB_UNLOCK(stcb); 13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 13668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 136832a191a90b5c914a02047389c5b3197e08fc9841tuexen SCTP_TCB_UNLOCK(stcb); 13698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 13708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 13718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 1372f57cf83923be449d11806a31f62bcc17e58832d6t if (!sctp_does_stcb_own_this_addr(stcb, to)) { 1373f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_TCB_UNLOCK(stcb); 1374f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_INP_RUNLOCK(inp); 1375f57cf83923be449d11806a31f62bcc17e58832d6t continue; 1376f57cf83923be449d11806a31f62bcc17e58832d6t } 13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Does this TCB have a matching address? */ 13788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 13798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._l_addr.sa.sa_family != from->sa_family) { 13818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not the same family, can't be a match */ 13828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 13838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (from->sa_family) { 13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 13868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin, *rsin; 13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 13908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = (struct sockaddr_in *)&net->ro._l_addr; 13918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin = (struct sockaddr_in *)from; 13928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == 13938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin->sin_addr.s_addr) { 13948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 13958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp != NULL) { 13968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp = net; 13978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 13988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Update the endpoint pointer */ 13998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *inp_p = inp; 14008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 14018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 14028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 14048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 14068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 14078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6, *rsin6; 14108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 14128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin6 = (struct sockaddr_in6 *)from; 14138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP6_ARE_ADDR_EQUAL(sin6, 14148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin6)) { 14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 14168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp != NULL) { 14178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp = net; 14188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Update the endpoint pointer */ 14208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *inp_p = inp; 14218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 14228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 14238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 14258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 142775cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__) 142875cd23222c96d5ebe5a9082c57a263f917f1462btuexen case AF_CONN: 142975cd23222c96d5ebe5a9082c57a263f917f1462btuexen { 143075cd23222c96d5ebe5a9082c57a263f917f1462btuexen struct sockaddr_conn *sconn, *rsconn; 143175cd23222c96d5ebe5a9082c57a263f917f1462btuexen 143275cd23222c96d5ebe5a9082c57a263f917f1462btuexen sconn = (struct sockaddr_conn *)&net->ro._l_addr; 143375cd23222c96d5ebe5a9082c57a263f917f1462btuexen rsconn = (struct sockaddr_conn *)from; 143475cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (sconn->sconn_addr == rsconn->sconn_addr) { 143575cd23222c96d5ebe5a9082c57a263f917f1462btuexen /* found it */ 143675cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (netp != NULL) { 143775cd23222c96d5ebe5a9082c57a263f917f1462btuexen *netp = net; 143875cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 143975cd23222c96d5ebe5a9082c57a263f917f1462btuexen /* Update the endpoint pointer */ 144075cd23222c96d5ebe5a9082c57a263f917f1462btuexen *inp_p = inp; 144175cd23222c96d5ebe5a9082c57a263f917f1462btuexen SCTP_INP_RUNLOCK(inp); 144275cd23222c96d5ebe5a9082c57a263f917f1462btuexen return (stcb); 144375cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 144475cd23222c96d5ebe5a9082c57a263f917f1462btuexen break; 144575cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 144675cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TSNH */ 14498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 14508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 14538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 14548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14587988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 14608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * rules for use 14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 1) If I return a NULL you must decrement any INP ref cnt. 2) If I find an 14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * stcb, both will be locked (locked_tcb and stcb) but decrement will be done 14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (if locked == NULL). 3) Decrement happens on return ONLY if locked == 14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NULL. 14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_tcb * 14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote, 14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets **netp, struct sockaddr *local, struct sctp_tcb *locked_tcb) 14718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 14728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpasochead *head; 14738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 1474b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen struct sctp_tcb *stcb = NULL; 14758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 14768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t rport; 14778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 14788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = *inp_p; 147975cd23222c96d5ebe5a9082c57a263f917f1462btuexen switch (remote->sa_family) { 148075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#ifdef INET 148175cd23222c96d5ebe5a9082c57a263f917f1462btuexen case AF_INET: 14828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rport = (((struct sockaddr_in *)remote)->sin_port); 148375cd23222c96d5ebe5a9082c57a263f917f1462btuexen break; 148475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 148575cd23222c96d5ebe5a9082c57a263f917f1462btuexen#ifdef INET6 148675cd23222c96d5ebe5a9082c57a263f917f1462btuexen case AF_INET6: 14878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rport = (((struct sockaddr_in6 *)remote)->sin6_port); 148875cd23222c96d5ebe5a9082c57a263f917f1462btuexen break; 148975cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 149075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__) 149175cd23222c96d5ebe5a9082c57a263f917f1462btuexen case AF_CONN: 149275cd23222c96d5ebe5a9082c57a263f917f1462btuexen rport = (((struct sockaddr_in6 *)remote)->sin6_port); 149375cd23222c96d5ebe5a9082c57a263f917f1462btuexen break; 149475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 149575cd23222c96d5ebe5a9082c57a263f917f1462btuexen default: 14968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 14978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 14988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 14998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 15008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * UN-lock so we can do proper locking here this occurs when 15018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * called from load_addresses_from_init. 15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&locked_tcb->asoc.refcnt, 1); 15048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(locked_tcb); 15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RLOCK(); 1507875d5dae39dd5ba623e1c27212aa2ac953c2317at if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1508875d5dae39dd5ba623e1c27212aa2ac953c2317at (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 15098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 15108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now either this guy is our listener or it's the 15118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * connector. If it is the one that issued the connect, then 15128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it's only chance is to be the first TCB in the list. If 15138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it is the acceptor, then do the special_lookup to hash 15148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and find the real inp. 15158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_socket) && (inp->sctp_socket->so_qlimit)) { 15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* to is peer addr, from is my addr */ 15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef SCTP_MVRF 15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb = sctp_tcb_special_locate(inp_p, remote, local, 15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netp, inp->def_vrf_id); 15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb != NULL) && (locked_tcb == NULL)) { 15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we have a locked tcb, lower refcount */ 15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 15248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((locked_tcb != NULL) && (locked_tcb != stcb)) { 15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(locked_tcb->sctp_ep); 15278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(locked_tcb); 15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 15298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(locked_tcb->sctp_ep); 15308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 15328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 15338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * MVRF is tricky, we must look in every VRF 15348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the endpoint has. 15358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 1536f57cf83923be449d11806a31f62bcc17e58832d6t int i; 1537f57cf83923be449d11806a31f62bcc17e58832d6t 1538f57cf83923be449d11806a31f62bcc17e58832d6t for (i = 0; i < inp->num_vrfs; i++) { 1539f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_tcb_special_locate(inp_p, remote, local, 1540f57cf83923be449d11806a31f62bcc17e58832d6t netp, inp->m_vrf_ids[i]); 1541f57cf83923be449d11806a31f62bcc17e58832d6t if ((stcb != NULL) && (locked_tcb == NULL)) { 1542f57cf83923be449d11806a31f62bcc17e58832d6t /* we have a locked tcb, lower refcount */ 1543f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_INP_DECR_REF(inp); 1544f57cf83923be449d11806a31f62bcc17e58832d6t break; 1545f57cf83923be449d11806a31f62bcc17e58832d6t } 1546f57cf83923be449d11806a31f62bcc17e58832d6t if ((locked_tcb != NULL) && (locked_tcb != stcb)) { 1547f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_INP_RLOCK(locked_tcb->sctp_ep); 1548f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_TCB_LOCK(locked_tcb); 1549f57cf83923be449d11806a31f62bcc17e58832d6t atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 1550f57cf83923be449d11806a31f62bcc17e58832d6t SCTP_INP_RUNLOCK(locked_tcb->sctp_ep); 1551f57cf83923be449d11806a31f62bcc17e58832d6t break; 15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 15588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(inp); 15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 15608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto null_return; 15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb = LIST_FIRST(&inp->sctp_asoc_list); 15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 15648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto null_return; 15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->rport != rport) { 15698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remote port does not match. */ 15708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 15718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto null_return; 15728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 157432a191a90b5c914a02047389c5b3197e08fc9841tuexen SCTP_TCB_UNLOCK(stcb); 15758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto null_return; 15768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (local && !sctp_does_stcb_own_this_addr(stcb, local)) { 15788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto null_return; 15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now look at the list of remote addresses */ 15828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == (TAILQ_NEXT(net, sctp_next))) { 15858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Corrupt net list"); 15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 15888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._l_addr.sa.sa_family != 15898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen remote->sa_family) { 15908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not the same family */ 15918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 15928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 15938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (remote->sa_family) { 15948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 15958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 15968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 15978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin, *rsin; 15988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 15998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = (struct sockaddr_in *) 16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &net->ro._l_addr; 16018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin = (struct sockaddr_in *)remote; 16028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == 16038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin->sin_addr.s_addr) { 16048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 16058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp != NULL) { 16068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp = net; 16078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb == NULL) { 16098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 16108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (locked_tcb != stcb) { 16118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(locked_tcb); 16128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 16148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 16158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 16188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 16198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 16208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 16228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 16248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 16258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 16268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 16278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6, *rsin6; 16288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 16298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 16308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin6 = (struct sockaddr_in6 *)remote; 16318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP6_ARE_ADDR_EQUAL(sin6, 16328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin6)) { 16338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 16348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp != NULL) { 16358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp = net; 16368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb == NULL) { 16388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 16398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (locked_tcb != stcb) { 16408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(locked_tcb); 16418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 16438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 16448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 16468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 16478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 16488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 16508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 165275cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__) 165375cd23222c96d5ebe5a9082c57a263f917f1462btuexen case AF_CONN: 165475cd23222c96d5ebe5a9082c57a263f917f1462btuexen { 165575cd23222c96d5ebe5a9082c57a263f917f1462btuexen struct sockaddr_conn *sconn, *rsconn; 165675cd23222c96d5ebe5a9082c57a263f917f1462btuexen 165775cd23222c96d5ebe5a9082c57a263f917f1462btuexen sconn = (struct sockaddr_conn *)&net->ro._l_addr; 165875cd23222c96d5ebe5a9082c57a263f917f1462btuexen rsconn = (struct sockaddr_conn *)remote; 165975cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (sconn->sconn_addr == rsconn->sconn_addr) { 166075cd23222c96d5ebe5a9082c57a263f917f1462btuexen /* found it */ 166175cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (netp != NULL) { 166275cd23222c96d5ebe5a9082c57a263f917f1462btuexen *netp = net; 166375cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 166475cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (locked_tcb == NULL) { 166575cd23222c96d5ebe5a9082c57a263f917f1462btuexen SCTP_INP_DECR_REF(inp); 166675cd23222c96d5ebe5a9082c57a263f917f1462btuexen } else if (locked_tcb != stcb) { 166775cd23222c96d5ebe5a9082c57a263f917f1462btuexen SCTP_TCB_LOCK(locked_tcb); 166875cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 166975cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (locked_tcb) { 167075cd23222c96d5ebe5a9082c57a263f917f1462btuexen atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 167175cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 167275cd23222c96d5ebe5a9082c57a263f917f1462btuexen SCTP_INP_WUNLOCK(inp); 167375cd23222c96d5ebe5a9082c57a263f917f1462btuexen SCTP_INP_INFO_RUNLOCK(); 167475cd23222c96d5ebe5a9082c57a263f917f1462btuexen return (stcb); 167575cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 167675cd23222c96d5ebe5a9082c57a263f917f1462btuexen break; 167775cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 167875cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 16798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TSNH */ 16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 16878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(inp); 16888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 16898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto null_return; 16908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &inp->sctp_tcbhash[SCTP_PCBHASH_ALLADDR(rport, 16928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_hashmark)]; 16938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (head == NULL) { 16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto null_return; 16958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(stcb, head, sctp_tcbhash) { 16978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->rport != rport) { 16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remote port does not match */ 16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (local && !sctp_does_stcb_own_this_addr(stcb, local)) { 17078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now look at the list of remote addresses */ 17118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == (TAILQ_NEXT(net, sctp_next))) { 17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Corrupt net list"); 17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._l_addr.sa.sa_family != 17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen remote->sa_family) { 17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not the same family */ 17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (remote->sa_family) { 17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 17268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin, *rsin; 17278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = (struct sockaddr_in *) 17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &net->ro._l_addr; 17308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin = (struct sockaddr_in *)remote; 17318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == 17328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin->sin_addr.s_addr) { 17338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 17348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp != NULL) { 17358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp = net; 17368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb == NULL) { 17388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 17398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (locked_tcb != stcb) { 17408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(locked_tcb); 17418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 17468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 17478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 17508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 17528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 17538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 17548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6, *rsin6; 17568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 17578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *) 17588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &net->ro._l_addr; 17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin6 = (struct sockaddr_in6 *)remote; 17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP6_ARE_ADDR_EQUAL(sin6, 17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rsin6)) { 17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found it */ 17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp != NULL) { 17648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp = net; 17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb == NULL) { 17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (locked_tcb != stcb) { 17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(locked_tcb); 17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 17758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 17768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 17778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 17798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 17808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 178175cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__) 178275cd23222c96d5ebe5a9082c57a263f917f1462btuexen case AF_CONN: 178375cd23222c96d5ebe5a9082c57a263f917f1462btuexen { 178475cd23222c96d5ebe5a9082c57a263f917f1462btuexen struct sockaddr_conn *sconn, *rsconn; 178575cd23222c96d5ebe5a9082c57a263f917f1462btuexen 178675cd23222c96d5ebe5a9082c57a263f917f1462btuexen sconn = (struct sockaddr_conn *)&net->ro._l_addr; 178775cd23222c96d5ebe5a9082c57a263f917f1462btuexen rsconn = (struct sockaddr_conn *)remote; 178875cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (sconn->sconn_addr == rsconn->sconn_addr) { 178975cd23222c96d5ebe5a9082c57a263f917f1462btuexen /* found it */ 179075cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (netp != NULL) { 179175cd23222c96d5ebe5a9082c57a263f917f1462btuexen *netp = net; 179275cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 179375cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (locked_tcb == NULL) { 179475cd23222c96d5ebe5a9082c57a263f917f1462btuexen SCTP_INP_DECR_REF(inp); 179575cd23222c96d5ebe5a9082c57a263f917f1462btuexen } else if (locked_tcb != stcb) { 179675cd23222c96d5ebe5a9082c57a263f917f1462btuexen SCTP_TCB_LOCK(locked_tcb); 179775cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 179875cd23222c96d5ebe5a9082c57a263f917f1462btuexen if (locked_tcb) { 179975cd23222c96d5ebe5a9082c57a263f917f1462btuexen atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 180075cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 180175cd23222c96d5ebe5a9082c57a263f917f1462btuexen SCTP_INP_WUNLOCK(inp); 180275cd23222c96d5ebe5a9082c57a263f917f1462btuexen SCTP_INP_INFO_RUNLOCK(); 180375cd23222c96d5ebe5a9082c57a263f917f1462btuexen return (stcb); 180475cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 180575cd23222c96d5ebe5a9082c57a263f917f1462btuexen break; 180675cd23222c96d5ebe5a9082c57a263f917f1462btuexen } 180775cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 18098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TSNH */ 18108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 18118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexennull_return: 18178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clean up for returning null */ 18188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (locked_tcb) { 18198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(locked_tcb); 18208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&locked_tcb->asoc.refcnt, 1); 18218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 18238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 18248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not found */ 18258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 18268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 18278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18287988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 18298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 18308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Find an association for a specific endpoint using the association id given 18318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * out in the COMM_UP notification 18328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_tcb * 18348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_findasoc_ep_asocid_locked(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int want_lock) 18358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 18368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 18378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Use my the assoc_id to find a endpoint 18388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpasochead *head; 18408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 18418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t id; 18427988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 18438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp == NULL) { 18448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("TSNH ep_associd\n"); 18458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 18468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 18488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("TSNH ep_associd0\n"); 18498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 18508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen id = (uint32_t)asoc_id; 18528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &inp->sctp_asocidhash[SCTP_PCBHASH_ASOC(id, inp->hashasocidmark)]; 18538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (head == NULL) { 18548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid id TSNH */ 18558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("TSNH ep_associd1\n"); 18568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 18578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(stcb, head, sctp_tcbasocidhash) { 18598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.assoc_id == id) { 18608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp != stcb->sctp_ep) { 18618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 18628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * some other guy has the same id active (id 18638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * collision ??). 18648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 18658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("TSNH ep_associd2\n"); 18668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 18678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 18698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (want_lock) { 18728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 18738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_tcb * 18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_findassociation_ep_asocid(struct sctp_inpcb *inp, sctp_assoc_t asoc_id, int want_lock) 18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 18847988ea8f0c067cf3757e798b473b1ae4d34b6dfdt struct sctp_tcb *stcb; 18857988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 18867988ea8f0c067cf3757e798b473b1ae4d34b6dfdt SCTP_INP_RLOCK(inp); 18877988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb = sctp_findasoc_ep_asocid_locked(inp, asoc_id, want_lock); 18887988ea8f0c067cf3757e798b473b1ae4d34b6dfdt SCTP_INP_RUNLOCK(inp); 18897988ea8f0c067cf3757e798b473b1ae4d34b6dfdt return (stcb); 18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 18918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 18937988ea8f0c067cf3757e798b473b1ae4d34b6dfdt/* 18947988ea8f0c067cf3757e798b473b1ae4d34b6dfdt * Endpoint probe expects that the INP_INFO is locked. 18957988ea8f0c067cf3757e798b473b1ae4d34b6dfdt */ 18968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_inpcb * 18978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head, 18988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t lport, uint32_t vrf_id) 18998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 19008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 19018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 19028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 19038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 19048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 19068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 19078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *intf_addr6; 19088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 190966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__) 191066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen struct sockaddr_conn *sconn; 191166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif 19128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 19138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int fnd; 19167988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = NULL; 19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = NULL; 19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19235a5e26a9dd23ccfaf6334584f138e5beb0f2a925t#if defined(__Userspace__) 19245a5e26a9dd23ccfaf6334584f138e5beb0f2a925t sconn = NULL; 19255a5e26a9dd23ccfaf6334584f138e5beb0f2a925t#endif 19268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (nam->sa_family) { 19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = (struct sockaddr_in *)nam; 19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 19318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 19348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)nam; 19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 193766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__) 193866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen case AF_CONN: 193966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen sconn = (struct sockaddr_conn *)nam; 194066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen break; 194166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif 19428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 19438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* unsupported family */ 19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 19478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (head == NULL) 19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 194932a191a90b5c914a02047389c5b3197e08fc9841tuexen 19508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(inp, head, sctp_hash) { 19518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(inp); 19528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 19538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 19548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) && 19578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_lport == lport)) { 19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* got it */ 1959998635733088fde643e6d807fa76679c4ceeaa00t switch (nam->sa_family) { 19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 1961998635733088fde643e6d807fa76679c4ceeaa00t case AF_INET: 1962998635733088fde643e6d807fa76679c4ceeaa00t if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1963998635733088fde643e6d807fa76679c4ceeaa00t SCTP_IPV6_V6ONLY(inp)) { 1964998635733088fde643e6d807fa76679c4ceeaa00t /* IPv4 on a IPv6 socket with ONLY IPv6 set */ 1965998635733088fde643e6d807fa76679c4ceeaa00t SCTP_INP_RUNLOCK(inp); 1966998635733088fde643e6d807fa76679c4ceeaa00t continue; 1967998635733088fde643e6d807fa76679c4ceeaa00t } 1968998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 1969998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip4(inp->ip_inp.inp.inp_cred, 1970998635733088fde643e6d807fa76679c4ceeaa00t &sin->sin_addr) != 0) { 1971998635733088fde643e6d807fa76679c4ceeaa00t SCTP_INP_RUNLOCK(inp); 1972998635733088fde643e6d807fa76679c4ceeaa00t continue; 1973998635733088fde643e6d807fa76679c4ceeaa00t } 1974998635733088fde643e6d807fa76679c4ceeaa00t#endif 1975998635733088fde643e6d807fa76679c4ceeaa00t break; 19768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 19778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 1978998635733088fde643e6d807fa76679c4ceeaa00t case AF_INET6: 1979998635733088fde643e6d807fa76679c4ceeaa00t /* A V6 address and the endpoint is NOT bound V6 */ 1980998635733088fde643e6d807fa76679c4ceeaa00t if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 1981998635733088fde643e6d807fa76679c4ceeaa00t SCTP_INP_RUNLOCK(inp); 1982998635733088fde643e6d807fa76679c4ceeaa00t continue; 1983998635733088fde643e6d807fa76679c4ceeaa00t } 1984998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 1985998635733088fde643e6d807fa76679c4ceeaa00t if (prison_check_ip6(inp->ip_inp.inp.inp_cred, 1986998635733088fde643e6d807fa76679c4ceeaa00t &sin6->sin6_addr) != 0) { 1987998635733088fde643e6d807fa76679c4ceeaa00t SCTP_INP_RUNLOCK(inp); 1988998635733088fde643e6d807fa76679c4ceeaa00t continue; 1989998635733088fde643e6d807fa76679c4ceeaa00t } 1990998635733088fde643e6d807fa76679c4ceeaa00t#endif 1991998635733088fde643e6d807fa76679c4ceeaa00t break; 19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 1993998635733088fde643e6d807fa76679c4ceeaa00t default: 1994998635733088fde643e6d807fa76679c4ceeaa00t break; 1995998635733088fde643e6d807fa76679c4ceeaa00t } 19968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* does a VRF id match? */ 19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 0; 19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < inp->num_vrfs; i++) { 20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->m_vrf_ids[i] == vrf_id) { 20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 20068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->def_vrf_id == vrf_id) 20078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 20088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 20118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!fnd) 20128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 20138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (inp); 20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (nam->sa_family) { 20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 20208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == INADDR_ANY) { 20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't hunt for one that has no address specified */ 20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 20258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 20278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 2028b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't hunt for one that has no address specified */ 20308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 203466e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__) 203566e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen case AF_CONN: 203666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen if (sconn->sconn_addr == NULL) { 203766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen return (NULL); 203866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen } 203966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen break; 204066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif 20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 20428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ok, not bound to all so see if we can find a EP bound to this 20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address. 20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(inp, head, sctp_hash) { 20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(inp); 20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)) { 20558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 20568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok this could be a likely candidate, look at all of its 20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * addresses 20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_lport != lport) { 20638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 20648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 20658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* does a VRF id match? */ 20678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 0; 20688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < inp->num_vrfs; i++) { 20708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->m_vrf_ids[i] == vrf_id) { 20718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->def_vrf_id == vrf_id) 20778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 20788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!fnd) { 20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 20838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == NULL) { 20868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", 20878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __FUNCTION__); 20888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB1, "Ok laddr->ifa:%p is possible, ", 2091ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)laddr->ifa); 20928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { 20938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB1, "Huh IFA being deleted\n"); 20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 20968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa->address.sa.sa_family == nam->sa_family) { 20978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* possible, see if it matches */ 20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (nam->sa_family) { 20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 21008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 2101b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#if defined(__APPLE__) 2102b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (sin == NULL) { 2103b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen /* TSNH */ 2104b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen break; 2105b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } 2106b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen#endif 21078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == 21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen laddr->ifa->address.sin.sin_addr.s_addr) { 21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (inp); 21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen intf_addr6 = &laddr->ifa->address.sin6; 21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP6_ARE_ADDR_EQUAL(sin6, 21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen intf_addr6)) { 21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (inp); 21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 212466e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__) 212566e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen case AF_CONN: 212666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen if (sconn->sconn_addr == laddr->ifa->address.sconn.sconn_addr) { 212766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen SCTP_INP_RUNLOCK(inp); 212866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen return (inp); 212966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen } 213066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen break; 213166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif 21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 21398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_inpcb * 21428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_isport_inuse(struct sctp_inpcb *inp, uint16_t lport, uint32_t vrf_id) 21438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 21448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctppcbhead *head; 21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *t_inp; 21468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int fnd; 21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(lport, 21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(hashmark))]; 21538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(t_inp, head, sctp_hash) { 21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (t_inp->sctp_lport != lport) { 21558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* is it in the VRF in question */ 21588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 0; 21598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 2160b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen for (i = 0; i < inp->num_vrfs; i++) { 21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (t_inp->m_vrf_ids[i] == vrf_id) { 21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (t_inp->def_vrf_id == vrf_id) 21688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 21698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 21708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!fnd) 21718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 21738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This one is in use. */ 21748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* check the v6/v4 binding issue */ 21758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((t_inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 21768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPV6_V6ONLY(t_inp)) { 21778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 21788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* collision in V6 space */ 21798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (t_inp); 21808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 21818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* inp is BOUND_V4 no conflict */ 21828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (t_inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* t_inp is bound v4 and v6, conflict always */ 21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (t_inp); 21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* t_inp is bound only V4 */ 21898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPV6_V6ONLY(inp)) { 21918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no conflict */ 21928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 21938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* else fall through to conflict */ 21958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (t_inp); 21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 22038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_swap_inpcb_for_listen(struct sctp_inpcb *inp) 22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* For 1-2-1 with port reuse */ 22068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctppcbhead *head; 22078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *tinp; 22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE)) { 22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* only works with port reuse on */ 2211b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (-1); 22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) { 22148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(inp->sctp_lport, 22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(hashmark))]; 22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Kick out all non-listeners to the TCP hash */ 22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(tinp, head, sctp_hash) { 22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tinp->sctp_lport != inp->sctp_lport) { 22228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 22238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 22288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (tinp->sctp_socket->so_qlimit) { 22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(tinp); 22348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(tinp, sctp_hash); 22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR(tinp->sctp_lport, SCTP_BASE_INFO(hashtcpmark))]; 22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tinp->sctp_flags |= SCTP_PCB_FLAGS_IN_TCPPOOL; 22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(head, tinp, sctp_hash); 22388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(tinp); 22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(inp); 22418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Pull from where he was */ 22428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(inp, sctp_hash); 22438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags &= ~SCTP_PCB_FLAGS_IN_TCPPOOL; 22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(inp->sctp_lport, SCTP_BASE_INFO(hashmark))]; 22458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(head, inp, sctp_hash); 22468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(inp); 22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 22498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 22508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_inpcb * 22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_pcb_findep(struct sockaddr *nam, int find_tcp_pool, int have_lock, 22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id) 22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * First we check the hash table to see if someone has this port 22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * bound with just the port. 22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctppcbhead *head; 22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int lport; 22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen unsigned int i; 22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 22658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 227066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__) 227166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen struct sockaddr_conn *sconn; 227266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif 22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 22748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (nam->sa_family) { 22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = (struct sockaddr_in *)nam; 2278b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen lport = sin->sin_port; 22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 22808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 22828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)nam; 2284b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen lport = sin6->sin6_port; 22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 228766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__) 228866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen case AF_CONN: 228966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen sconn = (struct sockaddr_conn *)nam; 229066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen lport = sconn->sconn_port; 229166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen break; 229266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif 22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * I could cheat here and just cast to one of the types but we will 22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * do it right. It also provides the check against an Unsupported 22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * type too. 23008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Find the head of the ALLADDR chain */ 23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (have_lock == 0) { 23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RLOCK(); 23048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(lport, 23068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(hashmark))]; 23078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = sctp_endpoint_probe(nam, head, lport, vrf_id); 23088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 23108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If the TCP model exists it could be that the main listening 23118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * endpoint is gone but there still exists a connected socket for this 23128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * guy. If so we can return the first one that we find. This may NOT 23138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * be the correct one so the caller should be wary on the returned INP. 23148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Currently the only caller that sets find_tcp_pool is in bindx where 23158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we are verifying that a user CAN bind the address. He either 23168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * has bound it already, or someone else has, or its open to bind, 23178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * so this is good enough. 23188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp == NULL && find_tcp_pool) { 23208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < SCTP_BASE_INFO(hashtcpmark) + 1; i++) { 23218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_tcpephash)[i]; 23228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = sctp_endpoint_probe(nam, head, lport, vrf_id); 23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp) { 23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp) { 23298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INCR_REF(inp); 23308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (have_lock == 0) { 23328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 23338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (inp); 23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 23368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23377988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 23388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 23398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Find an association for an endpoint with the pointer to whom you want to 23408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * send to and the endpoint pointer. The address can be IPv4 or IPv6. We may 23418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * need to change the *to to some other struct like a mbuf... 23428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_tcb * 2344e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_findassociation_addr_sa(struct sockaddr *from, struct sockaddr *to, 23458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb **inp_p, struct sctp_nets **netp, int find_tcp_pool, 23468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id) 23478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 23488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp = NULL; 2349f57cf83923be449d11806a31f62bcc17e58832d6t struct sctp_tcb *stcb; 23508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RLOCK(); 23528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (find_tcp_pool) { 23538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp_p != NULL) { 2354f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_tcb_special_locate(inp_p, from, to, netp, 2355f57cf83923be449d11806a31f62bcc17e58832d6t vrf_id); 23568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 2357f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_tcb_special_locate(&inp, from, to, netp, 2358f57cf83923be449d11806a31f62bcc17e58832d6t vrf_id); 23598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2360f57cf83923be449d11806a31f62bcc17e58832d6t if (stcb != NULL) { 23618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 2362f57cf83923be449d11806a31f62bcc17e58832d6t return (stcb); 23638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = sctp_pcb_findep(to, 0, 1, vrf_id); 23668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp_p != NULL) { 23678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *inp_p = inp; 23688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 23708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp == NULL) { 23718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 23728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 23738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 23748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ok, we have an endpoint, now lets find the assoc for it (if any) 23758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we now place the source address or from in the to of the find 23768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * endpoint call. Since in reality this chain is used from the 23778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * inbound packet side. 23788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp_p != NULL) { 2380f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_findassociation_ep_addr(inp_p, from, netp, to, 2381f57cf83923be449d11806a31f62bcc17e58832d6t NULL); 23828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 2383f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_findassociation_ep_addr(&inp, from, netp, to, 2384f57cf83923be449d11806a31f62bcc17e58832d6t NULL); 23858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2386f57cf83923be449d11806a31f62bcc17e58832d6t return (stcb); 23878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 23888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 23908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 23918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This routine will grub through the mbuf that is a INIT or INIT-ACK and 23928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * find all addresses that the sender has specified in any address list. Each 23938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address will be used to lookup the TCB and see if one exits. 23948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 23958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_tcb * 23960ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_findassociation_special_addr(struct mbuf *m, int offset, 23978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctphdr *sh, struct sctp_inpcb **inp_p, struct sctp_nets **netp, 2398e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *dst) 23998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 24008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *phdr, parm_buf; 2401fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#if defined(INET) || defined(INET6) 2402d98c5e3ba320c8116f289be1d4067365914bf062t struct sctp_tcb *stcb; 2403fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t uint16_t ptype; 2404fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#endif 2405fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t uint16_t plen; 24068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 24078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in sin4; 24088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 24108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 sin6; 24118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 24148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&sin4, 0, sizeof(sin4)); 24157b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 24168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin4.sin_len = sizeof(sin4); 24178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin4.sin_family = AF_INET; 24198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin4.sin_port = sh->src_port; 24208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 24228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&sin6, 0, sizeof(sin6)); 24237b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN 24248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6.sin6_len = sizeof(sin6); 24258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6.sin6_family = AF_INET6; 24278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6.sin6_port = sh->src_port; 24288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += sizeof(struct sctp_init_chunk); 24318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); 24338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (phdr != NULL) { 24348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now we must see if we want the parameter */ 2435fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#if defined(INET) || defined(INET6) 24368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ptype = ntohs(phdr->param_type); 2437fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#endif 24388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen plen = ntohs(phdr->param_length); 24398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen == 0) { 24408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 24418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 24438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ptype == SCTP_IPV4_ADDRESS && 24448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen plen == sizeof(struct sctp_ipv4addr_param)) { 24458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Get the rest of the address */ 24468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv4addr_param ip4_parm, *p4; 24478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, 24498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_paramhdr *)&ip4_parm, min(plen, sizeof(ip4_parm))); 24508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (phdr == NULL) { 24518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 24528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p4 = (struct sctp_ipv4addr_param *)phdr; 24548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&sin4.sin_addr, &p4->addr, sizeof(p4->addr)); 24558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* look it up */ 2456f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_findassociation_ep_addr(inp_p, 2457e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen (struct sockaddr *)&sin4, netp, dst, NULL); 2458f57cf83923be449d11806a31f62bcc17e58832d6t if (stcb != NULL) { 2459f57cf83923be449d11806a31f62bcc17e58832d6t return (stcb); 24608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 24648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ptype == SCTP_IPV6_ADDRESS && 24658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen plen == sizeof(struct sctp_ipv6addr_param)) { 24668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Get the rest of the address */ 24678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param ip6_parm, *p6; 24688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, 24708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_paramhdr *)&ip6_parm, min(plen,sizeof(ip6_parm))); 24718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (phdr == NULL) { 24728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 24738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p6 = (struct sctp_ipv6addr_param *)phdr; 24758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&sin6.sin6_addr, &p6->addr, sizeof(p6->addr)); 24768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* look it up */ 2477f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_findassociation_ep_addr(inp_p, 2478e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen (struct sockaddr *)&sin6, netp, dst, NULL); 2479f57cf83923be449d11806a31f62bcc17e58832d6t if (stcb != NULL) { 2480f57cf83923be449d11806a31f62bcc17e58832d6t return (stcb); 24818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 24848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += SCTP_SIZE32(plen); 24858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, &parm_buf, 24868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(parm_buf)); 24878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 24888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 24898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 24908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 24918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_tcb * 24928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_findassoc_by_vtag(struct sockaddr *from, struct sockaddr *to, uint32_t vtag, 24938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint16_t rport, 24948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t lport, int skip_src_check, uint32_t vrf_id, uint32_t remote_tag) 24958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 24968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 24978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Use my vtag to hash. If we find it we then verify the source addr 24988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is in the assoc. If all goes well we save a bit on rec of a 24998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * packet. 25008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 25018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpasochead *head; 25028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 25038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 25040ac02f34d6041cd0018437596a5a9a94685e6919tuexen#ifdef SCTP_MVRF 25050ac02f34d6041cd0018437596a5a9a94685e6919tuexen unsigned int i; 25060ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif 25078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 25088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RLOCK(); 25098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(vtag, 25108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(hashasocmark))]; 25118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (head == NULL) { 25128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid vtag */ 25138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 25148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 25158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(stcb, head, sctp_asocs) { 25178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(stcb->sctp_ep); 25188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 25198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(stcb->sctp_ep); 25208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25220ac02f34d6041cd0018437596a5a9a94685e6919tuexen#ifdef SCTP_MVRF 25230ac02f34d6041cd0018437596a5a9a94685e6919tuexen for (i = 0; i < stcb->sctp_ep->num_vrfs; i++) { 25240ac02f34d6041cd0018437596a5a9a94685e6919tuexen if (stcb->sctp_ep->m_vrf_ids[i] == vrf_id) { 25250ac02f34d6041cd0018437596a5a9a94685e6919tuexen break; 25260ac02f34d6041cd0018437596a5a9a94685e6919tuexen } 25270ac02f34d6041cd0018437596a5a9a94685e6919tuexen } 25280ac02f34d6041cd0018437596a5a9a94685e6919tuexen if (i == stcb->sctp_ep->num_vrfs) { 25290ac02f34d6041cd0018437596a5a9a94685e6919tuexen SCTP_INP_RUNLOCK(inp); 25300ac02f34d6041cd0018437596a5a9a94685e6919tuexen continue; 25310ac02f34d6041cd0018437596a5a9a94685e6919tuexen } 25320ac02f34d6041cd0018437596a5a9a94685e6919tuexen#else 25330ac02f34d6041cd0018437596a5a9a94685e6919tuexen if (stcb->sctp_ep->def_vrf_id != vrf_id) { 25340ac02f34d6041cd0018437596a5a9a94685e6919tuexen SCTP_INP_RUNLOCK(stcb->sctp_ep); 25350ac02f34d6041cd0018437596a5a9a94685e6919tuexen continue; 25360ac02f34d6041cd0018437596a5a9a94685e6919tuexen } 25370ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif 25388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 25398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(stcb->sctp_ep); 25408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.my_vtag == vtag) { 25418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* candidate */ 25428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->rport != rport) { 25438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 25448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_ep->sctp_lport != lport) { 25478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 25488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 25518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 25528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* RRS:Need toaddr check here */ 25558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_does_stcb_own_this_addr(stcb, to) == 0) { 25568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Endpoint does not own this address */ 25578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 25588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 25598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (remote_tag) { 25618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If we have both vtags that's all we match on */ 25628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.peer_vtag == remote_tag) { 25638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If both tags match we consider it conclusive 25648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and check NO source/destination addresses 25658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 25668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto conclusive; 25678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (skip_src_check) { 25708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen conclusive: 25718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from) { 2572b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen *netp = sctp_findnet(stcb, from); 25738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 25748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp = NULL; /* unknown */ 25758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp_p) 25778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *inp_p = stcb->sctp_ep; 25788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 25798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 25808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net = sctp_findnet(stcb, from); 25828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net) { 25838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* yep its him. */ 25848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp = net; 25858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_vtagexpress); 25868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *inp_p = stcb->sctp_ep; 25878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 25888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 25898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 25908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 25918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not him, this should only happen in rare 25928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cases so I peg it. 25938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 25948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_vtagbogus); 25958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 25988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 25998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 26008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 26018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 26028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26037988ea8f0c067cf3757e798b473b1ae4d34b6dfdt 26048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 26058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Find an association with the pointer to the inbound IP packet. This can be 26068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a IPv4 or IPv6 packet. 26078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_tcb * 26090ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_findassociation_addr(struct mbuf *m, int offset, 2610e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, 26118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctphdr *sh, struct sctp_chunkhdr *ch, 26128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id) 26138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 26148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int find_tcp_pool; 2615f57cf83923be449d11806a31f62bcc17e58832d6t struct sctp_tcb *stcb; 26168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 26178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sh->v_tag) { 26198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we only go down this path if vtag is non-zero */ 2620f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_findassoc_by_vtag(src, dst, ntohl(sh->v_tag), 2621202f563d266291cbdec3bacf7844172ebfabed95t inp_p, netp, sh->src_port, sh->dest_port, 0, vrf_id, 0); 2622f57cf83923be449d11806a31f62bcc17e58832d6t if (stcb) { 2623f57cf83923be449d11806a31f62bcc17e58832d6t return (stcb); 26248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen find_tcp_pool = 0; 26288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ch->chunk_type != SCTP_INITIATION) && 26298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ch->chunk_type != SCTP_INITIATION_ACK) && 26308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ch->chunk_type != SCTP_COOKIE_ACK) && 26318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ch->chunk_type != SCTP_COOKIE_ECHO)) { 26328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Other chunk types go to the tcp pool. */ 26338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen find_tcp_pool = 1; 26348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp_p) { 2636f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_findassociation_addr_sa(src, dst, inp_p, netp, 2637202f563d266291cbdec3bacf7844172ebfabed95t find_tcp_pool, vrf_id); 26388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = *inp_p; 26398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 2640f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_findassociation_addr_sa(src, dst, &inp, netp, 2641202f563d266291cbdec3bacf7844172ebfabed95t find_tcp_pool, vrf_id); 26428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2643f57cf83923be449d11806a31f62bcc17e58832d6t SCTPDBG(SCTP_DEBUG_PCB1, "stcb:%p inp:%p\n", (void *)stcb, (void *)inp); 2644f57cf83923be449d11806a31f62bcc17e58832d6t if (stcb == NULL && inp) { 26458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Found a EP but not this address */ 26468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ch->chunk_type == SCTP_INITIATION) || 26478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ch->chunk_type == SCTP_INITIATION_ACK)) { 26488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 26498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * special hook, we do NOT return linp or an 26508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * association that is linked to an existing 26518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * association that is under the TCP pool (i.e. no 26528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * listener exists). The endpoint finding routine 26538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * will always find a listener before examining the 26548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * TCP pool. 26558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) { 26578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp_p) { 26588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *inp_p = NULL; 26598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 26618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2662f57cf83923be449d11806a31f62bcc17e58832d6t stcb = sctp_findassociation_special_addr(m, 2663e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen offset, sh, &inp, netp, dst); 26648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp_p != NULL) { 26658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *inp_p = inp; 26668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 26688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2669f57cf83923be449d11806a31f62bcc17e58832d6t SCTPDBG(SCTP_DEBUG_PCB1, "stcb is %p\n", (void *)stcb); 2670f57cf83923be449d11806a31f62bcc17e58832d6t return (stcb); 26718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 26728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 26748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * lookup an association by an ASCONF lookup address. 26758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if the lookup address is 0.0.0.0 or ::0, use the vtag to do the lookup 26768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 26778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_tcb * 26780ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_findassociation_ep_asconf(struct mbuf *m, int offset, 2679e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *dst, struct sctphdr *sh, 2680e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sctp_inpcb **inp_p, struct sctp_nets **netp, uint32_t vrf_id) 26818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 26828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 2683bfb1bf7e665a02b48026482bf33d05c83dfad73bt union sctp_sockstore remote_store; 26848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr parm_buf, *phdr; 26858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int ptype; 26868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int zero_address = 0; 26878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 26888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 26898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 26908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 26918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 26928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 26938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 26948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&remote_store, 0, sizeof(remote_store)); 26958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset + sizeof(struct sctp_asconf_chunk), 26968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &parm_buf, sizeof(struct sctp_paramhdr)); 26978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (phdr == NULL) { 26988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf lookup addr\n", 26998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __FUNCTION__); 27008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return NULL; 27018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ptype = (int)((uint32_t) ntohs(phdr->param_type)); 27038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* get the correlation address */ 27048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ptype) { 27058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 27068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV6_ADDRESS: 27078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 27088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ipv6 address param */ 27098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *p6, p6_buf; 27108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohs(phdr->param_length) != sizeof(struct sctp_ipv6addr_param)) { 27128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return NULL; 27138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p6 = (struct sctp_ipv6addr_param *)sctp_get_next_param(m, 27158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset + sizeof(struct sctp_asconf_chunk), 27168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &p6_buf.ph, sizeof(*p6)); 27178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (p6 == NULL) { 27188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v6 lookup addr\n", 27198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __FUNCTION__); 27208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 27218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2722bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin6 = &remote_store.sin6; 27238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_family = AF_INET6; 27247b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN 27258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_len = sizeof(*sin6); 27268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_port = sh->src_port; 27288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&sin6->sin6_addr, &p6->addr, sizeof(struct in6_addr)); 27298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 27308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen zero_address = 1; 27318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 27328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 27358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV4_ADDRESS: 27368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 27378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ipv4 address param */ 27388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv4addr_param *p4, p4_buf; 27398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohs(phdr->param_length) != sizeof(struct sctp_ipv4addr_param)) { 27418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return NULL; 27428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p4 = (struct sctp_ipv4addr_param *)sctp_get_next_param(m, 27448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset + sizeof(struct sctp_asconf_chunk), 27458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &p4_buf.ph, sizeof(*p4)); 27468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (p4 == NULL) { 27478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v4 lookup addr\n", 27488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __FUNCTION__); 27498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 27508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 2751bfb1bf7e665a02b48026482bf33d05c83dfad73bt sin = &remote_store.sin; 27528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_family = AF_INET; 27537b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 27548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_len = sizeof(*sin); 27558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_port = sh->src_port; 27578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&sin->sin_addr, &p4->addr, sizeof(struct in_addr)); 27588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == INADDR_ANY) 27598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen zero_address = 1; 27608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 27618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 27638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 27648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid address param type */ 27658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return NULL; 27668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (zero_address) { 2769e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen stcb = sctp_findassoc_by_vtag(NULL, dst, ntohl(sh->v_tag), inp_p, 27708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netp, sh->src_port, sh->dest_port, 1, vrf_id, 0); 2771bd5146cae5799edacfa22c798cd1eff1078f02fatuexen if (stcb != NULL) { 2772bd5146cae5799edacfa22c798cd1eff1078f02fatuexen SCTP_INP_DECR_REF(*inp_p); 2773bd5146cae5799edacfa22c798cd1eff1078f02fatuexen } 27748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 27758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb = sctp_findassociation_ep_addr(inp_p, 2776bfb1bf7e665a02b48026482bf33d05c83dfad73bt &remote_store.sa, netp, 2777e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen dst, NULL); 27788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 27798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 27808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 27818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 27838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 27848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * allocate a sctp_inpcb and setup a temporary binding to a port/all 27858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * addresses. This way if we don't get a bind we by default pick a ephemeral 27868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * port with all addresses bound. 27878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 27898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_inpcb_alloc(struct socket *so, uint32_t vrf_id) 27908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 27918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 27928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we get called when a new endpoint starts up. We need to allocate 27938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the sctp_inpcb structure from the zone and init it. Mark it as 27948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * unbound and find a port that we can use as an ephemeral with 27958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INADDR_ANY. If the user binds later no problem we can then add in 27968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the specific addresses. And setup the default parameters for the 27978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * EP. 27988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 27998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i, error; 28008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 28018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_pcb *m; 28028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval time; 28038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sharedkey_t *null_key; 28048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error = 0; 28068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WLOCK(); 28088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_ep), struct sctp_inpcb); 28098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp == NULL) { 28108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Out of SCTP-INPCB structures - no resources\n"); 28118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 28128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); 28138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ENOBUFS); 28148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* zap it */ 28168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(inp, sizeof(*inp)); 28178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* bump generations */ 28198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 28208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_state = INPCB_STATE_INUSE; 28218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* setup socket pointers */ 28238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_socket = so; 28248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_socket = so; 2825998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2826998635733088fde643e6d807fa76679c4ceeaa00t inp->ip_inp.inp.inp_cred = crhold(so->so_cred); 2827998635733088fde643e6d807fa76679c4ceeaa00t#endif 28287ec5951ec04f35070419877f6b015541f6b9728dtuexen#ifdef INET6 2829881279179f74ee26ebf175006ca7ffd7bbafd284tuexen#if !defined(__Userspace__) && !defined(__Windows__) 2830202f563d266291cbdec3bacf7844172ebfabed95t if (INP_SOCKAF(so) == AF_INET6) { 2831202f563d266291cbdec3bacf7844172ebfabed95t if (MODULE_GLOBAL(ip6_auto_flowlabel)) { 2832202f563d266291cbdec3bacf7844172ebfabed95t inp->ip_inp.inp.inp_flags |= IN6P_AUTOFLOWLABEL; 2833202f563d266291cbdec3bacf7844172ebfabed95t } 2834202f563d266291cbdec3bacf7844172ebfabed95t if (MODULE_GLOBAL(ip6_v6only)) { 2835202f563d266291cbdec3bacf7844172ebfabed95t inp->ip_inp.inp.inp_flags |= IN6P_IPV6_V6ONLY; 2836202f563d266291cbdec3bacf7844172ebfabed95t } 28378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28397ec5951ec04f35070419877f6b015541f6b9728dtuexen#endif 28408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_associd_counter = 1; 28418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT; 28428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT; 28438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_cmt_on_off = SCTP_BASE_SYSCTL(sctp_cmt_on_off); 2844aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t inp->ecn_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_ecn_enable); 2845a8657c4fc04fb9cc82100f648810d51ec6ab155at inp->prsctp_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pr_enable); 28460602fd0eeb08e1999c7f28f21c8dde1f4503a03ft inp->auth_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_auth_enable); 2847fb3816eaffe5878bb1286adb120fd160da178a05t inp->asconf_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_asconf_enable); 28482344bfccffeb80545fca6a86e8cda3d56a6f50bft inp->reconfig_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_reconfig_enable); 284944318e900a771ba1a5bafb510c38f33fd5cd8a39t inp->nrsack_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_nrsack_enable); 2850669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t inp->pktdrop_supported = (uint8_t)SCTP_BASE_SYSCTL(sctp_pktdrop_enable); 285132a191a90b5c914a02047389c5b3197e08fc9841tuexen#if defined(__Userspace__) 2852d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen inp->ulp_info = NULL; 285332a191a90b5c914a02047389c5b3197e08fc9841tuexen inp->recv_callback = NULL; 285432a191a90b5c914a02047389c5b3197e08fc9841tuexen inp->send_callback = NULL; 285532a191a90b5c914a02047389c5b3197e08fc9841tuexen inp->send_sb_threshold = 0; 285632a191a90b5c914a02047389c5b3197e08fc9841tuexen#endif 28578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* init the small hash table we use to track asocid <-> tcb */ 28588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark); 28598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_asocidhash == NULL) { 2860998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2861998635733088fde643e6d807fa76679c4ceeaa00t crfree(inp->ip_inp.inp.inp_cred); 2862998635733088fde643e6d807fa76679c4ceeaa00t#endif 28638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 28648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 28658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ENOBUFS); 28668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef IPSEC 28688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__APPLE__)) 28698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 28708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct inpcbpolicy *pcb_sp = NULL; 28718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error = ipsec_init_policy(so, &pcb_sp); 28738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Arrange to share the policy */ 28748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_sp = pcb_sp; 28758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((struct in6pcb *)(&inp->ip_inp.inp))->in6p_sp = pcb_sp; 28768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 28788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not sure what to do for openbsd here */ 28798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error = 0; 28808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 28818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (error != 0) { 2882998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2883998635733088fde643e6d807fa76679c4ceeaa00t crfree(inp->ip_inp.inp.inp_cred); 2884998635733088fde643e6d807fa76679c4ceeaa00t#endif 28858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 28868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 28878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return error; 28888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 28898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* IPSEC */ 28908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INCR_EP_COUNT(); 28918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl); 28928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 28938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 28948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so->so_pcb = (caddr_t)inp; 28958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 2896f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version < 803000 28978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_SO_TYPE(so) == SOCK_DGRAM) || 28988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_SO_TYPE(so) == SOCK_SEQPACKET)) { 28998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 29008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_SO_TYPE(so) == SOCK_SEQPACKET) { 29018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* UDP style socket */ 29038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE | 29048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_UNBOUND); 29058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Be sure it is NON-BLOCKING IO for UDP */ 29068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* SCTP_SET_SO_NBIO(so); */ 29078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_SO_TYPE(so) == SOCK_STREAM) { 29088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TCP style socket */ 29098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | 29108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_UNBOUND); 29118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Be sure we have blocking IO by default */ 29128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CLEAR_SO_NBIO(so); 29138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__) 29148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_SO_TYPE(so) == SOCK_FASTSEQPACKET) { 29158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags = (SCTP_PCB_FLAGS_UDPTYPE | 29168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_UNBOUND); 29178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE); 29188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_SO_TYPE(so) == SOCK_FASTSTREAM) { 29198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | 29208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_UNBOUND); 29218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE); 29228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 29248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 29258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * unsupported socket type (RAW, etc)- in case we missed it 29268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * in protosw 29278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 29288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP); 29298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so->so_pcb = NULL; 2930998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2931998635733088fde643e6d807fa76679c4ceeaa00t crfree(inp->ip_inp.inp.inp_cred); 2932998635733088fde643e6d807fa76679c4ceeaa00t#endif 29338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 29348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EOPNOTSUPP); 29358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_default_frag_interleave) == SCTP_FRAG_LEVEL_1) { 29378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE); 29388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS); 29398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_BASE_SYSCTL(sctp_default_frag_interleave) == SCTP_FRAG_LEVEL_2) { 29408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE); 29418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS); 29428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (SCTP_BASE_SYSCTL(sctp_default_frag_interleave) == SCTP_FRAG_LEVEL_0) { 29438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE); 29448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS); 29458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_tcbhash = SCTP_HASH_INIT(SCTP_BASE_SYSCTL(sctp_pcbtblsize), 29478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &inp->sctp_hashmark); 29488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_tcbhash == NULL) { 29498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Out of SCTP-INPCB->hashinit - no resources\n"); 29508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); 29518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so->so_pcb = NULL; 2952998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2953998635733088fde643e6d807fa76679c4ceeaa00t crfree(inp->ip_inp.inp.inp_cred); 2954998635733088fde643e6d807fa76679c4ceeaa00t#endif 29558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 29568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ENOBUFS); 29578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 29598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->vrf_size = SCTP_DEFAULT_VRF_SIZE; 29608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(inp->m_vrf_ids, uint32_t *, 29618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sizeof(uint32_t) * inp->vrf_size), SCTP_M_MVRF); 29628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->m_vrf_ids == NULL) { 29638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); 29648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so->so_pcb = NULL; 29658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark); 2966998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2967998635733088fde643e6d807fa76679c4ceeaa00t crfree(inp->ip_inp.inp.inp_cred); 2968998635733088fde643e6d807fa76679c4ceeaa00t#endif 29698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 29708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ENOBUFS); 29718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->m_vrf_ids[0] = vrf_id; 29738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->num_vrfs = 1; 29748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->def_vrf_id = vrf_id; 29768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 29778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 29781ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) 29797fbcb406549bdf370031d2ad5befb44e39b95ffft inp->ip_inp.inp.inpcb_mtx = lck_mtx_alloc_init(SCTP_BASE_INFO(sctbinfo).mtx_grp, SCTP_BASE_INFO(sctbinfo).mtx_attr); 29808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->ip_inp.inp.inpcb_mtx == NULL) { 2981ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t SCTP_PRINTF("in_pcballoc: can't alloc mutex! so=%p\n", (void *)so); 29828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 29838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF); 29848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 29858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark); 29868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so->so_pcb = NULL; 2987998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__) 2988998635733088fde643e6d807fa76679c4ceeaa00t crfree(inp->ip_inp.inp.inp_cred); 2989998635733088fde643e6d807fa76679c4ceeaa00t#endif 29908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 29917fbcb406549bdf370031d2ad5befb44e39b95ffft SCTP_UNLOCK_EXC(SCTP_BASE_INFO(sctbinfo).ipi_lock); 29928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM); 29938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ENOMEM); 29948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 29957fbcb406549bdf370031d2ad5befb44e39b95ffft#elif defined(APPLE_LION) || defined(APPLE_MOUNTAINLION) 29967fbcb406549bdf370031d2ad5befb44e39b95ffft lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(sctbinfo).mtx_grp, SCTP_BASE_INFO(sctbinfo).mtx_attr); 29971ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#else 29987fbcb406549bdf370031d2ad5befb44e39b95ffft lck_mtx_init(&inp->ip_inp.inp.inpcb_mtx, SCTP_BASE_INFO(sctbinfo).ipi_lock_grp, SCTP_BASE_INFO(sctbinfo).ipi_lock_attr); 29998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WLOCK(); 30028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_LOCK_INIT(inp); 30038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) 30048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen INP_LOCK_INIT(&inp->ip_inp.inp, "inp", "sctpinp"); 30058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_READ_INIT(inp); 30078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_CREATE_LOCK_INIT(inp); 30088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* lock the new ep */ 30098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(inp); 30108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add it to the info area */ 30128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&SCTP_BASE_INFO(listhead), inp, sctp_list); 30138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 30147fbcb406549bdf370031d2ad5befb44e39b95ffft inp->ip_inp.inp.inp_pcbinfo = &SCTP_BASE_INFO(sctbinfo); 30157fbcb406549bdf370031d2ad5befb44e39b95ffft#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION) 30167fbcb406549bdf370031d2ad5befb44e39b95ffft LIST_INSERT_HEAD(SCTP_BASE_INFO(sctbinfo).listhead, &inp->ip_inp.inp, inp_list); 30177fbcb406549bdf370031d2ad5befb44e39b95ffft#else 30187fbcb406549bdf370031d2ad5befb44e39b95ffft LIST_INSERT_HEAD(SCTP_BASE_INFO(sctbinfo).ipi_listhead, &inp->ip_inp.inp, inp_list); 30197fbcb406549bdf370031d2ad5befb44e39b95ffft#endif 30208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 30228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INIT(&inp->read_queue); 30248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&inp->sctp_addr_list); 30258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&inp->sctp_asoc_list); 30278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TRACK_FREED_ASOCS 30298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TEMP CODE */ 30308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&inp->sctp_asoc_free_list); 30318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 30328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Init the timer structure for signature change */ 30338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&inp->sctp_ep.signature_change.timer); 30348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_ep.signature_change.type = SCTP_TIMER_TYPE_NEWCOOKIE; 30358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now init the actual endpoint default data */ 30378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m = &inp->sctp_ep; 30388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* setup the base timeout information */ 30408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_timeoutticks[SCTP_TIMER_SEND] = SEC_TO_TICKS(SCTP_SEND_SEC); /* needed ? */ 30418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_timeoutticks[SCTP_TIMER_INIT] = SEC_TO_TICKS(SCTP_INIT_SEC); /* needed ? */ 30428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default)); 30438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default)); 30448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_timeoutticks[SCTP_TIMER_PMTU] = SEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default)); 30458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN] = SEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default)); 30468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_timeoutticks[SCTP_TIMER_SIGNATURE] = SEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_secret_lifetime_default)); 30478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* all max/min max are in ms */ 30488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_maxrto = SCTP_BASE_SYSCTL(sctp_rto_max_default); 30498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_minrto = SCTP_BASE_SYSCTL(sctp_rto_min_default); 30508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->initial_rto = SCTP_BASE_SYSCTL(sctp_rto_initial_default); 30518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->initial_init_rto_max = SCTP_BASE_SYSCTL(sctp_init_rto_max_default); 30528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_sack_freq = SCTP_BASE_SYSCTL(sctp_sack_freq_default); 30538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->max_init_times = SCTP_BASE_SYSCTL(sctp_init_rtx_max_default); 30548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->max_send_times = SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default); 30558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->def_net_failure = SCTP_BASE_SYSCTL(sctp_path_rtx_max_default); 30568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->def_net_pf_threshold = SCTP_BASE_SYSCTL(sctp_path_pf_threshold); 30578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_sws_sender = SCTP_SWS_SENDER_DEF; 30588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_sws_receiver = SCTP_SWS_RECEIVER_DEF; 30598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->max_burst = SCTP_BASE_SYSCTL(sctp_max_burst_default); 30608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->fr_max_burst = SCTP_BASE_SYSCTL(sctp_fr_max_burst_default); 30618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_default_cc_module = SCTP_BASE_SYSCTL(sctp_default_cc_module); 30638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->sctp_default_ss_module = SCTP_BASE_SYSCTL(sctp_default_ss_module); 3064f72906cec69866943ecd6c46cc74c87a8b5e9d5ft m->max_open_streams_intome = SCTP_BASE_SYSCTL(sctp_nr_incoming_streams_default); 30658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* number of streams to pre-open on a association */ 30668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->pre_open_stream_count = SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default); 30678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Add adaptation cookie */ 30699a8642036bc992ec39f872443a35f8c545cc28c4t m->adaptation_layer_indicator = 0; 30709a8642036bc992ec39f872443a35f8c545cc28c4t m->adaptation_layer_indicator_provided = 0; 30718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* seed random number generator */ 30738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->random_counter = 1; 30748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->store_at = SCTP_SIGNATURE_SIZE; 30758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_READ_RANDOM(m->random_numbers, sizeof(m->random_numbers)); 30768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_fill_random_store(m); 30778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Minimum cookie size */ 30798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->size_of_a_cookie = (sizeof(struct sctp_init_msg) * 2) + 30808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_state_cookie); 30818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->size_of_a_cookie += SCTP_SIGNATURE_SIZE; 30828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Setup the initial secret */ 30848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&time); 30858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->time_of_secret_change = time.tv_sec; 30868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) { 30888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->secret_key[0][i] = sctp_select_initial_TSN(m); 30898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 30908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL); 30918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 30928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* How long is a cookie good for ? */ 30938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->def_cookie_life = MSEC_TO_TICKS(SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default)); 30948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 30958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Initialize authentication parameters 30968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 30978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->local_hmacs = sctp_default_supported_hmaclist(); 30988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->local_auth_chunks = sctp_alloc_chunklist(); 3099fb3816eaffe5878bb1286adb120fd160da178a05t if (inp->asconf_supported) { 3100fb3816eaffe5878bb1286adb120fd160da178a05t sctp_auth_add_chunk(SCTP_ASCONF, m->local_auth_chunks); 3101fb3816eaffe5878bb1286adb120fd160da178a05t sctp_auth_add_chunk(SCTP_ASCONF_ACK, m->local_auth_chunks); 3102fb3816eaffe5878bb1286adb120fd160da178a05t } 31038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->default_dscp = 0; 31048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 31058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->default_flowlabel = 0; 31068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 3107153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen m->port = 0; /* encapsulation disabled by default */ 31088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&m->shared_keys); 31098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add default NULL key as key id 0 */ 31108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen null_key = sctp_alloc_sharedkey(); 31118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_insert_sharedkey(&m->shared_keys, null_key); 31128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 31138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 31148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, NULL, 12); 31158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 31168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (error); 31178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 31188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 31218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp, 31228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb) 31238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 31248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 31258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t lport, rport; 31268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctppcbhead *head; 31278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr, *oladdr; 31288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 31308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 31318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WLOCK(); 31328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(old_inp); 31338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(new_inp); 31348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 31358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&stcb->asoc.refcnt, 1); 31368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_inp->sctp_ep.time_of_secret_change = 31388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_inp->sctp_ep.time_of_secret_change; 31398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(new_inp->sctp_ep.secret_key, old_inp->sctp_ep.secret_key, 31408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(old_inp->sctp_ep.secret_key)); 31418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_inp->sctp_ep.current_secret_number = 31428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_inp->sctp_ep.current_secret_number; 31438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_inp->sctp_ep.last_secret_number = 31448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen old_inp->sctp_ep.last_secret_number; 31458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_inp->sctp_ep.size_of_a_cookie = old_inp->sctp_ep.size_of_a_cookie; 31468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* make it so new data pours into the new socket */ 31488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_socket = new_inp->sctp_socket; 31498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep = new_inp; 31508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Copy the port across */ 31528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lport = new_inp->sctp_lport = old_inp->sctp_lport; 31538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rport = stcb->rport; 31548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Pull the tcb from the old association */ 31558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_tcbhash); 31568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_tcblist); 31578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.in_asocid_hash) { 31588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_tcbasocidhash); 31598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now insert the new_inp into the TCP connected hash */ 31618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport | rport), SCTP_BASE_INFO(hashtcpmark))]; 31628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(head, new_inp, sctp_hash); 31648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its safe to access */ 31658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_inp->sctp_flags &= ~SCTP_PCB_FLAGS_UNBOUND; 31668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now move the tcb into the endpoint list */ 31688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&new_inp->sctp_asoc_list, stcb, sctp_tcblist); 31698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 31708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Question, do we even need to worry about the ep-hash since we 31718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * only have one connection? Probably not :> so lets get rid of it 31728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and not suck up any kernel memory in that. 31738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 31748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.in_asocid_hash) { 31758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpasochead *lhd; 31768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lhd = &new_inp->sctp_asocidhash[SCTP_PCBHASH_ASOC(stcb->asoc.assoc_id, 31778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_inp->hashasocidmark)]; 31788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(lhd, stcb, sctp_tcbasocidhash); 31798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Ok. Let's restart timer. */ 31818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 31828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, new_inp, 31838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, net); 31848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 31868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 31878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (new_inp->sctp_tcbhash != NULL) { 31888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(new_inp->sctp_tcbhash, new_inp->sctp_hashmark); 31898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_inp->sctp_tcbhash = NULL; 31908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 31918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((new_inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 31928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Subset bound, so copy in the laddr list from the old_inp */ 31938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(oladdr, &old_inp->sctp_addr_list, sctp_nxt_addr) { 31948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen laddr = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 31958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr == NULL) { 31968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 31978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Gak, what can we do? This assoc is really 31988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * HOSED. We probably should send an abort 31998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * here. 32008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB1, "Association hosed in TCP model, out of laddr memory\n"); 32028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 32038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INCR_LADDR_COUNT(); 32058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(laddr, sizeof(*laddr)); 32068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&laddr->start_time); 32078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen laddr->ifa = oladdr->ifa; 32088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&laddr->ifa->refcount, 1); 32098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&new_inp->sctp_addr_list, laddr, 32108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_nxt_addr); 32118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_inp->laddr_count++; 32128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (oladdr == stcb->asoc.last_used_address) { 32138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.last_used_address = laddr; 32148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now any running timers need to be adjusted 32188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since we really don't care if they are running 32198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * or not just blast in the new_inp into all of 32208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * them. 32218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.dack_timer.ep = (void *)new_inp; 32248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.asconf_timer.ep = (void *)new_inp; 32258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.strreset_timer.ep = (void *)new_inp; 32268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.shut_guard_timer.ep = (void *)new_inp; 32278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.autoclose_timer.ep = (void *)new_inp; 32288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.delayed_event_timer.ep = (void *)new_inp; 32298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.delete_prim_timer.ep = (void *)new_inp; 32308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now what about the nets? */ 32318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 32328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->pmtu_timer.ep = (void *)new_inp; 32338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->hb_timer.ep = (void *)new_inp; 32348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->rxt_timer.ep = (void *)new_inp; 32358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(new_inp); 32378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(old_inp); 32388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 32398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__)) 32428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 32438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Don't know why, but without this there is an unknown reference when 32448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * compiling NetBSD... hmm 32458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 32468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenextern void in6_sin6_2_sin(struct sockaddr_in *, struct sockaddr_in6 *sin6); 32478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 32488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* sctp_ifap is used to bypass normal local address validation checks */ 32518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 32528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 32538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_inpcb_bind(struct socket *so, struct sockaddr *addr, 3254699cf36232a54435c0fe7e3457ab7912547698e4t struct sctp_ifa *sctp_ifap, struct thread *p) 32558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__) 32568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_inpcb_bind(struct socket *so, struct sockaddr *addr, 3257699cf36232a54435c0fe7e3457ab7912547698e4t struct sctp_ifa *sctp_ifap, PKTHREAD p) 32588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 32598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_inpcb_bind(struct socket *so, struct sockaddr *addr, 3260699cf36232a54435c0fe7e3457ab7912547698e4t struct sctp_ifa *sctp_ifap, struct proc *p) 32618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 32628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 32638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* bind a ep to a socket address */ 32648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctppcbhead *head; 32658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp, *inp_tmp; 32660145a0c60c78b6c0b19d4714fdbf316c78ddac9at#if defined(INET) || (defined(INET6) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__APPLE__) 32678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct inpcb *ip_inp; 3268fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#endif 32698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int port_reuse_active = 0; 32708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int bindall; 32718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 32728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 32738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 32748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t lport; 32758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int error; 32768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t vrf_id; 32778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 32788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lport = 0; 32798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bindall = 1; 32808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = (struct sctp_inpcb *)so->so_pcb; 32810145a0c60c78b6c0b19d4714fdbf316c78ddac9at#if defined(INET) || (defined(INET6) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__APPLE__) 32828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ip_inp = (struct inpcb *)so->so_pcb; 3283fdb25d424e4a8793c59ed557f48c4d3bcd9d6f60t#endif 32848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG 32858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr) { 32869ac77419b79fa1b61bed4326c4ef825a19335704t SCTPDBG(SCTP_DEBUG_PCB1, "Bind called port: %d\n", 32878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(((struct sockaddr_in *)addr)->sin_port)); 32889ac77419b79fa1b61bed4326c4ef825a19335704t SCTPDBG(SCTP_DEBUG_PCB1, "Addr: "); 32898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_PCB1, addr); 32908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 32928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) { 32938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* already did a bind, subsequent binds NOT allowed ! */ 32948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 32958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 32968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 32978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 32988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 32998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (p == NULL) 33008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("null proc/thread"); 33018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr != NULL) { 33048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (addr->sa_family) { 33058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 33068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 33078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 33088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 33098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* IPV6_V6ONLY socket? */ 33118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_IPV6_V6ONLY(ip_inp)) { 33128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 33138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 33148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3315f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN 33168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr->sa_len != sizeof(*sin)) { 33178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 33188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 33198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = (struct sockaddr_in *)addr; 33238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lport = sin->sin_port; 33248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000 3325699cf36232a54435c0fe7e3457ab7912547698e4t /* 3326699cf36232a54435c0fe7e3457ab7912547698e4t * For LOOPBACK the prison_local_ip4() call will transmute the ip address 3327699cf36232a54435c0fe7e3457ab7912547698e4t * to the proper value. 3328699cf36232a54435c0fe7e3457ab7912547698e4t */ 3329699cf36232a54435c0fe7e3457ab7912547698e4t if (p && (error = prison_local_ip4(p->td_ucred, &sin->sin_addr)) != 0) { 3330699cf36232a54435c0fe7e3457ab7912547698e4t SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); 3331699cf36232a54435c0fe7e3457ab7912547698e4t return (error); 3332699cf36232a54435c0fe7e3457ab7912547698e4t } 33338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr != INADDR_ANY) { 33358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bindall = 0; 33368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 33388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 33418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 33428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 33438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Only for pure IPv6 Address. (No IPv4 Mapped!) */ 33448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 33458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 33468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)addr; 33478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3348f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN 33498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr->sa_len != sizeof(*sin6)) { 33508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 33518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 33528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lport = sin6->sin6_port; 33558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000 3356699cf36232a54435c0fe7e3457ab7912547698e4t /* 3357699cf36232a54435c0fe7e3457ab7912547698e4t * For LOOPBACK the prison_local_ip6() call will transmute the ipv6 address 3358699cf36232a54435c0fe7e3457ab7912547698e4t * to the proper value. 3359699cf36232a54435c0fe7e3457ab7912547698e4t */ 3360699cf36232a54435c0fe7e3457ab7912547698e4t if (p && (error = prison_local_ip6(p->td_ucred, &sin6->sin6_addr, 3361699cf36232a54435c0fe7e3457ab7912547698e4t (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) { 3362699cf36232a54435c0fe7e3457ab7912547698e4t SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); 3363699cf36232a54435c0fe7e3457ab7912547698e4t return (error); 3364699cf36232a54435c0fe7e3457ab7912547698e4t } 33658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 33678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bindall = 0; 33688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_EMBEDDED_V6_SCOPE 33698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* KAME hack: embed scopeid */ 33708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_KAME) 33718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)) != 0) { 33728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 33738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 33748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3375c2ae94ce88da509bd10c652de26407ac5b2ee97ctuexen#elif defined(__APPLE__) 33761ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) 33771ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen if (in6_embedscope(&sin6->sin6_addr, sin6, ip_inp, NULL) != 0) { 33788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 33791ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen if (in6_embedscope(&sin6->sin6_addr, sin6, ip_inp, NULL, NULL) != 0) { 33808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 33828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 33838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__FreeBSD__) 33858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error = scope6_check_id(sin6, MODULE_GLOBAL(ip6_use_defzone)); 33868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (error != 0) { 33878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); 33888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (error); 33898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 33918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (in6_embedscope(&sin6->sin6_addr, sin6) != 0) { 33928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 33938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 33948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 33968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */ 33978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 33988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef SCOPEDROUTING 33998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* this must be cleared for ifa_ifwithaddr() */ 34008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_scope_id = 0; 34018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCOPEDROUTING */ 34028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 34038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 340566e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__) 340666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen case AF_CONN: 340766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen { 340866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen struct sockaddr_conn *sconn; 340997cea5cc338ede48b21cb4f89151b8daf47a5d93t 3410f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN 341166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen if (addr->sa_len != sizeof(struct sockaddr_conn)) { 341266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 341366e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen return (EINVAL); 341466e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen } 341566e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif 341666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen sconn = (struct sockaddr_conn *)addr; 341766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen lport = sconn->sconn_port; 341866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen if (sconn->sconn_addr != NULL) { 341966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen bindall = 0; 342066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen } 342166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen break; 342266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen } 342366e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif 34248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 34258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EAFNOSUPPORT); 34268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EAFNOSUPPORT); 34278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WLOCK(); 34308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(inp); 34318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Setup a vrf_id to be the default for the non-bind-all case. */ 3432699cf36232a54435c0fe7e3457ab7912547698e4t vrf_id = inp->def_vrf_id; 34338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 34348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* increase our count due to the unlock we do */ 34358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INCR_REF(inp); 34368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lport) { 34378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 343897cea5cc338ede48b21cb4f89151b8daf47a5d93t * Did the caller specify a port? if so we must see if an ep 34398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * already has this one bound. 34408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* got to be root to get at low ports */ 34428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__Windows__) 34438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ntohs(lport) < IPPORT_RESERVED) { 34448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (p && (error = 34458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__ 34468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version > 602000 34478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen priv_check(p, PRIV_NETINET_RESERVEDPORT) 34488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif __FreeBSD_version >= 500000 34498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen suser_cred(p->td_ucred, 0) 34508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 34518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen suser(p) 34528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 34538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__APPLE__) 34548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen suser(p->p_ucred, &p->p_acflag) 34558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Userspace__) /* must be true to use raw socket */ 3456699cf36232a54435c0fe7e3457ab7912547698e4t 1 34578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 34588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen suser(p, 0) 34598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 34608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen )) { 34618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 34628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 34638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 34648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (error); 34658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__) 34678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!SCTP_IS_PRIVILEDGED(so)) { 34688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 34698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 34708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 34718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EACCES); 34728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EACCES); 34738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 34758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 34768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* __Windows__ */ 34778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 34788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (bindall) { 34798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 3480b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen for (i = 0; i < inp->num_vrfs; i++) { 34818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id = inp->m_vrf_ids[i]; 34828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 34838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id = inp->def_vrf_id; 34848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 34858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp_tmp = sctp_pcb_findep(addr, 0, 1, vrf_id); 34868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp_tmp != NULL) { 34878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 34888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * lock guy returned and lower count 34898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * note that we are not bound so 34908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * inp_tmp should NEVER be inp. And 34918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it is this inp (inp_tmp) that gets 34928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the reference bump, so we must 34938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * lower it. 34948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 34958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp_tmp); 34968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* unlock info */ 34978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) && 34988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_is_feature_on(inp_tmp, SCTP_PCB_FLAGS_PORTREUSE))) { 34998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Ok, must be one-2-one and allowing port re-use */ 35008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen port_reuse_active = 1; 35018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto continue_anyway; 35028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 35048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 35058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE); 35068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EADDRINUSE); 35078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 35098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 35118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 35128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp_tmp = sctp_pcb_findep(addr, 0, 1, vrf_id); 35138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp_tmp != NULL) { 35148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 35158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * lock guy returned and lower count note 35168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that we are not bound so inp_tmp should 35178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NEVER be inp. And it is this inp (inp_tmp) 35188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that gets the reference bump, so we must 35198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * lower it. 35208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 35218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp_tmp); 35228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* unlock info */ 35238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) && 35248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_is_feature_on(inp_tmp, SCTP_PCB_FLAGS_PORTREUSE))) { 35258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Ok, must be one-2-one and allowing port re-use */ 35268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen port_reuse_active = 1; 35278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto continue_anyway; 35288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 35308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 35318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE); 35328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EADDRINUSE); 35338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue_anyway: 35368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(inp); 35378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (bindall) { 35388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* verify that no lport is not used by a singleton */ 353997cea5cc338ede48b21cb4f89151b8daf47a5d93t if ((port_reuse_active == 0) && 354097cea5cc338ede48b21cb4f89151b8daf47a5d93t (inp_tmp = sctp_isport_inuse(inp, lport, vrf_id))) { 35418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Sorry someone already has this one bound */ 35428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) && 35438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_is_feature_on(inp_tmp, SCTP_PCB_FLAGS_PORTREUSE))) { 35448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen port_reuse_active = 1; 35458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 35468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 35478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 35488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 35498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE); 35508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EADDRINUSE); 35518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 35548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 35558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t first, last, candidate; 3556699cf36232a54435c0fe7e3457ab7912547698e4t uint16_t count; 35578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int done; 35588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 35598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Windows__) 35608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen first = 1; 35618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last = 0xffff; 35628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 35638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__) 3564699cf36232a54435c0fe7e3457ab7912547698e4t /* TODO ensure uid is 0, etc... */ 35658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__FreeBSD__) || defined(__APPLE__) 3566699cf36232a54435c0fe7e3457ab7912547698e4t if (ip_inp->inp_flags & INP_HIGHPORT) { 3567699cf36232a54435c0fe7e3457ab7912547698e4t first = MODULE_GLOBAL(ipport_hifirstauto); 3568699cf36232a54435c0fe7e3457ab7912547698e4t last = MODULE_GLOBAL(ipport_hilastauto); 3569699cf36232a54435c0fe7e3457ab7912547698e4t } else if (ip_inp->inp_flags & INP_LOWPORT) { 35708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (p && (error = 35718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__ 35728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version > 602000 35738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen priv_check(p, PRIV_NETINET_RESERVEDPORT) 35748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif __FreeBSD_version >= 500000 35758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen suser_cred(p->td_ucred, 0) 35768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 35778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen suser(p) 35788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 35798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__APPLE__) 35808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen suser(p->p_ucred, &p->p_acflag) 35818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 35828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen suser(p, 0) 35838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 35848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen )) { 35858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 35868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 35878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 35888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, error); 35898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (error); 35908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 3591699cf36232a54435c0fe7e3457ab7912547698e4t first = MODULE_GLOBAL(ipport_lowfirstauto); 3592699cf36232a54435c0fe7e3457ab7912547698e4t last = MODULE_GLOBAL(ipport_lowlastauto); 3593699cf36232a54435c0fe7e3457ab7912547698e4t } else { 35948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 3595e2828360ea9cf8951730d46f5c14626c9425cb30t first = MODULE_GLOBAL(ipport_firstauto); 3596e2828360ea9cf8951730d46f5c14626c9425cb30t last = MODULE_GLOBAL(ipport_lastauto); 35978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) 3598699cf36232a54435c0fe7e3457ab7912547698e4t } 35998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 36008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* __Windows__ */ 36018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (first > last) { 36028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t temp; 36038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen temp = first; 36058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen first = last; 36068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen last = temp; 36078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen count = last - first + 1; /* number of candidates */ 36098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen candidate = first + sctp_select_initial_TSN(&inp->sctp_ep) % (count); 36108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 36118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen done = 0; 36128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (!done) { 36138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 3614b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen for (i = 0; i < inp->num_vrfs; i++) { 36158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_isport_inuse(inp, htons(candidate), inp->m_vrf_ids[i]) != NULL) { 36168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 36178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (i == inp->num_vrfs) { 36208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen done = 1; 36218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 36238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_isport_inuse(inp, htons(candidate), inp->def_vrf_id) == NULL) { 36248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen done = 1; 36258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 36278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!done) { 36288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (--count == 0) { 36298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 36308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 36318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 36328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRINUSE); 36338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EADDRINUSE); 36348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (candidate == last) 36368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen candidate = first; 36378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 36388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen candidate = candidate + 1; 36398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lport = htons(candidate); 36428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 36448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & (SCTP_PCB_FLAGS_SOCKET_GONE | 36458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 36468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 36478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this really should not happen. The guy did a non-blocking 36488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * bind and then did a close at the same time. 36498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 36508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 36518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 36528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 36538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 36548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ok we look clear to give out this port, so lets setup the binding */ 36568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (bindall) { 36578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* binding to all addresses, so just set in the proper flags */ 36588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags |= SCTP_PCB_FLAGS_BOUNDALL; 36598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set the automatic addr changes from kernel flag */ 36608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) { 36618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF); 36628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTO_ASCONF); 36638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 36648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF); 36658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF); 36668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_multiple_asconfs) == 0) { 36688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_off(inp, SCTP_PCB_FLAGS_MULTIPLE_ASCONFS); 36698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 36708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_on(inp, SCTP_PCB_FLAGS_MULTIPLE_ASCONFS); 36718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set the automatic mobility_base from kernel 36738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen flag (by micchie) 36748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 36758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_mobility_base) == 0) { 36768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_off(inp, SCTP_MOBILITY_BASE); 36778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 367897cea5cc338ede48b21cb4f89151b8daf47a5d93t } else { 36798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_on(inp, SCTP_MOBILITY_BASE); 36808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 36818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set the automatic mobility_fasthandoff from kernel 36838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen flag (by micchie) 36848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 36858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff) == 0) { 36868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_off(inp, SCTP_MOBILITY_FASTHANDOFF); 36878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 368897cea5cc338ede48b21cb4f89151b8daf47a5d93t } else { 36898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_on(inp, SCTP_MOBILITY_FASTHANDOFF); 36908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_off(inp, SCTP_MOBILITY_PRIM_DELETED); 36918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 36928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 36938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 36948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * bind specific, make sure flags is off and add a new 36958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address structure to the sctp_addr_list inside the ep 36968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * structure. 36978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 36988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We will need to allocate one and insert it at the head. The 36998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * socketopt call can just insert new addresses in there as 37008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * well. It will also have to do the embed scope kame hack 37018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * too (before adding). 37028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 37038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *ifa; 3704bfb1bf7e665a02b48026482bf33d05c83dfad73bt union sctp_sockstore store; 37058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 3706bfb1bf7e665a02b48026482bf33d05c83dfad73bt memset(&store, 0, sizeof(store)); 37078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (addr->sa_family) { 3708e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET 37098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 3710bfb1bf7e665a02b48026482bf33d05c83dfad73bt memcpy(&store.sin, addr, sizeof(struct sockaddr_in)); 3711bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin.sin_port = 0; 37128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 3713e857b728270b80432f048a8de3c84aa9089dd06btuexen#endif 3714e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET6 37158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 3716bfb1bf7e665a02b48026482bf33d05c83dfad73bt memcpy(&store.sin6, addr, sizeof(struct sockaddr_in6)); 3717bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sin6.sin6_port = 0; 37188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 3719e857b728270b80432f048a8de3c84aa9089dd06btuexen#endif 37206a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#if defined(__Userspace__) 37216a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen case AF_CONN: 3722bfb1bf7e665a02b48026482bf33d05c83dfad73bt memcpy(&store.sconn, addr, sizeof(struct sockaddr_conn)); 3723bfb1bf7e665a02b48026482bf33d05c83dfad73bt store.sconn.sconn_port = 0; 37246a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen break; 37256a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 37268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 37278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 37288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 37308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * first find the interface with the bound address need to 37318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * zero out the port to find the address! yuck! can't do 37328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this earlier since need port for sctp_pcb_findep() 37338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 373497cea5cc338ede48b21cb4f89151b8daf47a5d93t if (sctp_ifap != NULL) { 37358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ifa = sctp_ifap; 373697cea5cc338ede48b21cb4f89151b8daf47a5d93t } else { 37378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Note for BSD we hit here always other 37388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * O/S's will pass things in via the 37398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_ifap argument (Panda). 37408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 3741bfb1bf7e665a02b48026482bf33d05c83dfad73bt ifa = sctp_find_ifa_by_addr(&store.sa, 37428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_id, SCTP_ADDR_NOT_LOCKED); 37438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa == NULL) { 37458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't find an interface with that address */ 37468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 37478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 37488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EADDRNOTAVAIL); 37498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EADDRNOTAVAIL); 37508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 37528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr->sa_family == AF_INET6) { 37538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* GAK, more FIXME IFA lock? */ 37548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 37558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't bind a non-existent addr. */ 37568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 37578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 37588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 37598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 37608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 37638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we're not bound all */ 37648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUNDALL; 37658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* allow bindx() to send ASCONF's for binding changes */ 37668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF); 37678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clear automatic addr changes from kernel flag */ 37688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTO_ASCONF); 37698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 37708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add this address to the endpoint list */ 37718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error = sctp_insert_laddr(&inp->sctp_addr_list, ifa, 0); 37728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (error != 0) { 37738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 37748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 37758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (error); 37768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->laddr_count++; 37788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* find the bucket */ 37800ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen if (port_reuse_active) { 37818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Put it into tcp 1-2-1 hash */ 37828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR(lport, SCTP_BASE_INFO(hashtcpmark))]; 37838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags |= SCTP_PCB_FLAGS_IN_TCPPOOL; 3784699cf36232a54435c0fe7e3457ab7912547698e4t } else { 37858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_ephash)[SCTP_PCBHASH_ALLADDR(lport, SCTP_BASE_INFO(hashmark))]; 37868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 37878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* put it in the bucket */ 37888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(head, inp, sctp_hash); 37898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB1, "Main hash to bind at head:%p, bound port:%d - in tcp_pool=%d\n", 3790ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)head, ntohs(lport), port_reuse_active); 37918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set in the port */ 37928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_lport = lport; 37938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 37948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* turn off just the unbound flag */ 37958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags &= ~SCTP_PCB_FLAGS_UNBOUND; 37968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 37978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 37988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 37998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 38008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 38038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_iterator_inp_being_freed(struct sctp_inpcb *inp) 38048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 38058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_iterator *it, *nit; 38068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 38088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We enter with the only the ITERATOR_LOCK in place and a write 38098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * lock on the inp_info stuff. 38108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 38118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it = sctp_it_ctl.cur_it; 38128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 38138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (it && (it->vn != curvnet)) { 38148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its not looking at our VNET */ 38158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 38168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 38188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (it && (it->inp == inp)) { 38198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 38208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This is tricky and we hold the iterator lock, 38218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * but when it returns and gets the lock (when we 38228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * release it) the iterator will try to operate on 38238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * inp. We need to stop that from happening. But 38248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * of course the iterator has a reference on the 38258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * stcb and inp. We can mark it and it will stop. 38268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 38278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If its a single iterator situation, we 38288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * set the end iterator flag. Otherwise 38298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we set the iterator to go to the next inp. 38308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 38318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 38328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 38338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; 38348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 38358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_INP; 38368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now go through and remove any single reference to 38398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * our inp that may be still pending on the list 38408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 38418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ITERATOR_WQ_LOCK(); 38428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { 38438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 38448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (it->vn != curvnet) { 38458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 384632a191a90b5c914a02047389c5b3197e08fc9841tuexen } 38478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 38488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (it->inp == inp) { 38498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This one points to me is it inp specific? */ 38508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 38518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Remove and free this one */ 38528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, 38538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it, sctp_nxt_itr); 38548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (it->function_atend != NULL) { 38558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*it->function_atend) (it->pointer, it->val); 38568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(it, SCTP_M_ITER); 38588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 38598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->inp = LIST_NEXT(it->inp, sctp_list); 38608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (it->inp) { 38618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INCR_REF(it->inp); 38628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* When its put in the refcnt is incremented so decr it */ 38658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 38668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 38688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ITERATOR_WQ_UNLOCK(); 38698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 38708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* release sctp_inpcb unbind the port */ 38728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 38738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from) 38748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 38758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 38768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Here we free a endpoint. We must find it (if it is in the Hash 38778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * table) and remove it from there. Then we must also find it in the 38788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * overall list and remove it from there. After all removals are 38798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * complete then any timer has to be stopped. Then start the actual 38808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * freeing. a) Any local lists. b) Any associations. c) The hash of 38818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * all associations. d) finally the ep itself. 38828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 38838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *asoc, *nasoc; 38848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr, *nladdr; 38858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct inpcb *ip_pcb; 38868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 3887b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int being_refed = 0; 38888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *sq, *nsq; 38898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__Panda__) && !defined(__Userspace__) 38908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__FreeBSD__) || __FreeBSD_version < 500000 38918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_rtentry_t *rt; 38928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 38938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 38948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int cnt; 38958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sharedkey_t *shared_key, *nshared_key; 38968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 38988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 38998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_lock_assert(SCTP_INP_SO(inp)); 39008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 39018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 39028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, NULL, 0); 39038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 39048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ITERATOR_LOCK(); 39058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* mark any iterators on the list or being processed */ 39068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_iterator_inp_being_freed(inp); 39078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ITERATOR_UNLOCK(); 39088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = inp->sctp_socket; 39098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 39108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* been here before.. eeks.. get out of here */ 39118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("This conflict in free SHOULD not be happening! from %d, imm %d\n", from, immediate); 39128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 39138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, NULL, 1); 39148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 39158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 39168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_CREATE_LOCK(inp); 39188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WLOCK(); 39198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(inp); 39218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from == SCTP_CALLED_AFTER_CMPSET_OFCLOSE) { 39228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags &= ~SCTP_PCB_FLAGS_CLOSE_IP; 39238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* socket is gone, so no more wakeups allowed */ 39248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags |= SCTP_PCB_FLAGS_DONT_WAKE; 39258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT; 39268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT; 39278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* First time through we have the socket lock, after that no more. */ 39308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_stop(SCTP_TIMER_TYPE_NEWCOOKIE, inp, NULL, NULL, 3931b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen SCTP_FROM_SCTP_PCB+SCTP_LOC_1); 39328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->control) { 39348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(inp->control); 39358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->control = NULL; 39368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->pkt) { 39388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(inp->pkt); 39398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->pkt = NULL; 39408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ip_pcb = &inp->ip_inp.inp; /* we could just cast the main pointer 39428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * here but I will be nice :> (i.e. 39438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ip_pcb = ep;) */ 39448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (immediate == SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE) { 39458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int cnt_in_sd; 39468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_in_sd = 0; 39488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_list, sctp_tcblist, nasoc) { 39498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(asoc); 39508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 39518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Skip guys being freed */ 39528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_in_sd++; 39538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE) { 39548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 39558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Special case - we did not start a kill 39568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * timer on the asoc due to it was not 39578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * closed. So go ahead and start it now. 39588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 39598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; 39608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, asoc, NULL); 39618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(asoc); 39638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 39648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_WAIT) || 39668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_ECHOED)) && 39678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->asoc.total_output_queue_size == 0)) { 39688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If we have data in queue, we don't want to just 39698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * free since the app may have done, send()/close 39708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * or connect/send/close. And it wants the data 39718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to get across first. 39728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 39738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Just abandon things in the front states */ 39748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_NOFORCE, 39758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_PCB+SCTP_LOC_2) == 0) { 39768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_in_sd++; 39778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 39798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Disconnect the socket please */ 39818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sctp_socket = NULL; 39828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asoc.state |= SCTP_STATE_CLOSED_SOCKET; 39838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((asoc->asoc.size_on_reasm_queue > 0) || 39848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->asoc.control_pdapi) || 39858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->asoc.size_on_all_streams > 0) || 3986b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen (so && (so->so_rcv.sb_cc > 0))) { 39878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Left with Data unread */ 39888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 39898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 39908f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); 39918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_3; 39928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); 39938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_aborted); 39948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || 39958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 39968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 39978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 39988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_free_assoc(inp, asoc, 39998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCBFREE_NOFORCE, SCTP_FROM_SCTP_PCB+SCTP_LOC_4) == 0) { 40008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_in_sd++; 40018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 40038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (TAILQ_EMPTY(&asoc->asoc.send_queue) && 40048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_EMPTY(&asoc->asoc.sent_queue) && 400520ceb0625959c5d1b8fa24de8b705a47af5a6e2et (asoc->asoc.stream_queue_cnt == 0)) { 40068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->asoc.locked_on_sending) { 40078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto abort_anyway; 40088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_SENT) && 40108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { 40118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *netp; 40128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 40138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 40148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * there is nothing queued to send, 40158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * so I send shutdown 40168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 40178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || 40188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 40198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 40208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40217988ea8f0c067cf3757e798b473b1ae4d34b6dfdt SCTP_SET_STATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_SENT); 40228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CLEAR_SUBSTATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_PENDING); 40237988ea8f0c067cf3757e798b473b1ae4d34b6dfdt sctp_stop_timers_for_shutdown(asoc); 40247988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (asoc->asoc.alternate) { 40257988ea8f0c067cf3757e798b473b1ae4d34b6dfdt netp = asoc->asoc.alternate; 40267988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } else { 40277988ea8f0c067cf3757e798b473b1ae4d34b6dfdt netp = asoc->asoc.primary_destination; 40287988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } 40297988ea8f0c067cf3757e798b473b1ae4d34b6dfdt sctp_send_shutdown(asoc, netp); 40308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, asoc->sctp_ep, asoc, 40318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netp); 40328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc, 40338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asoc.primary_destination); 40348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_chunk_output(inp, asoc, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_LOCKED); 40358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 40378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* mark into shutdown pending */ 40388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_queue_pending *sp; 40398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 40408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asoc.state |= SCTP_STATE_SHUTDOWN_PENDING; 40418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc, 40428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asoc.primary_destination); 40438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->asoc.locked_on_sending) { 40448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp = TAILQ_LAST(&((asoc->asoc.locked_on_sending)->outqueue), 40458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_streamhead); 40468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp == NULL) { 40478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Error, sp is NULL, locked on sending is %p strm:%d\n", 4048ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t (void *)asoc->asoc.locked_on_sending, 40498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asoc.locked_on_sending->stream_no); 40508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 40518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sp->length == 0) && (sp->msg_is_complete == 0)) 40528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asoc.state |= SCTP_STATE_PARTIAL_MSG_LEFT; 40538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (TAILQ_EMPTY(&asoc->asoc.send_queue) && 40568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_EMPTY(&asoc->asoc.sent_queue) && 40578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (asoc->asoc.state & SCTP_STATE_PARTIAL_MSG_LEFT)) { 40588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 40598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen abort_anyway: 40608f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); 40618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_5; 40628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); 40638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_aborted); 40648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || 40658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 40668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 40678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_free_assoc(inp, asoc, 40698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCBFREE_NOFORCE, 40708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FROM_SCTP_PCB+SCTP_LOC_6) == 0) { 40718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_in_sd++; 40728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 40748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 40758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_chunk_output(inp, asoc, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED); 40768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt_in_sd++; 40798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(asoc); 40808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now is there some left in our SHUTDOWN state? */ 40828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cnt_in_sd) { 40838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 40848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, NULL, 2); 40858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 40868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_socket = NULL; 40878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 40888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_CREATE_UNLOCK(inp); 40898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 40908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 40918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 40938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_socket = NULL; 40948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) != 40958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PCB_FLAGS_UNBOUND) { 40968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 40978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ok, this guy has been bound. It's port is 40988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * somewhere in the SCTP_BASE_INFO(hash table). Remove 40998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it! 41008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 41018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(inp, sctp_hash); 41028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags |= SCTP_PCB_FLAGS_UNBOUND; 41038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 41058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If there is a timer running to kill us, 41068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * forget it, since it may have a contest 41078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * on the INP lock.. which would cause us 41088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to die ... 41098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 41108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt = 0; 41118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_list, sctp_tcblist, nasoc) { 41128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(asoc); 41138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 41148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE) { 411520ceb0625959c5d1b8fa24de8b705a47af5a6e2et asoc->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; 411620ceb0625959c5d1b8fa24de8b705a47af5a6e2et sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, asoc, NULL); 41178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt++; 41198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(asoc); 41208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 41218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Free associations that are NOT killing us */ 41238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_COOKIE_WAIT) && 41248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0)) { 41258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *op_err; 412620ceb0625959c5d1b8fa24de8b705a47af5a6e2et 41278f9e45fea288542b24a6bda01269c6fc184d991at op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, ""); 41288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB+SCTP_LOC_7; 41298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED); 41308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR_COUNTER32(sctps_aborted); 41318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (asoc->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 41328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt++; 41338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(asoc); 41348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 41358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) || 41378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 41388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_DECR_GAUGE32(sctps_currestab); 41398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_free_assoc(inp, asoc, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_PCB+SCTP_LOC_8) == 0) { 41418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt++; 41428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cnt) { 41458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Ok we have someone out there that will kill us */ 41468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); 41478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 41488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, NULL, 3); 41498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 41508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 41518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_CREATE_UNLOCK(inp); 41528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 41538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 41548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_INP_LOCK_CONTENDED(inp)) 41568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen being_refed++; 41578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_INP_READ_CONTENDED(inp)) 41588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen being_refed++; 4159b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (SCTP_ASOC_CREATE_LOCK_CONTENDED(inp)) 41608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen being_refed++; 41618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 4162b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if ((inp->refcount) || 416320ceb0625959c5d1b8fa24de8b705a47af5a6e2et (being_refed) || 416420ceb0625959c5d1b8fa24de8b705a47af5a6e2et (inp->sctp_flags & SCTP_PCB_FLAGS_CLOSE_IP)) { 41658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); 41668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 41678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, NULL, 4); 41688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 41698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL); 41708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 41718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_CREATE_UNLOCK(inp); 41728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 41738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 41748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_ep.signature_change.type = 0; 41768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_ALLGONE; 41778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Remove it from the list .. last thing we need a 41788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * lock for. 41798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 41808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(inp, sctp_list); 41818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 41828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_CREATE_UNLOCK(inp); 41838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 41848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now we release all locks. Since this INP 41858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cannot be found anymore except possibly by the 41868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * kill timer that might be running. We call 41878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the drain function here. It should hit the case 41888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * were it sees the ACTIVE flag cleared and exit 41898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * out freeing us to proceed and destroy everything. 41908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 41918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from != SCTP_CALLED_FROM_INPKILL_TIMER) { 41928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP_DRAIN(&inp->sctp_ep.signature_change.timer); 41938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 41948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Probably un-needed */ 41958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.signature_change.timer); 41968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 41978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 41988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 41998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, NULL, 5); 42008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 42018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__Panda__) || defined(__Windows__) || defined(__Userspace__)) 42038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__FreeBSD__) || __FreeBSD_version < 500000 42048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rt = ip_pcb->inp_route.ro_rt; 42058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 42068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 42078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__) 42098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->pak_to_read) { 42108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.zero_copy_timer.timer); 42118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RELEASE_PKT(inp->pak_to_read); 42128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->pak_to_read = NULL; 42138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->pak_to_read_sendq) { 42158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&inp->sctp_ep.zero_copy_sendq_timer.timer); 42168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RELEASE_PKT(inp->pak_to_read_sendq); 42178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->pak_to_read_sendq = NULL; 42188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 42208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_asocidhash) != NULL) { 42218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(inp->sctp_asocidhash, inp->hashasocidmark); 42228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_asocidhash = NULL; 42238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 42258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(sq, &inp->read_queue, next, nsq) { 42268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its only abandoned if it had data left */ 42278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sq->length) 42288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_left_abandon); 42298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&inp->read_queue, sq, next); 42318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(sq->whoFrom); 42328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (so) 42338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so->so_rcv.sb_cc -= sq->length; 42348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sq->data) { 42358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(sq->data); 42368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sq->data = NULL; 42378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 42398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * no need to free the net count, since at this point all 42408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assoc's are gone. 42418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 42428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), sq); 42438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_READQ_COUNT(); 42448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now the sctp_pcb things */ 42468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 42478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * free each asoc if it is not already closed/free. we can't use the 42488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * macro here since le_next will get freed as part of the 42498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_free_assoc() call. 42508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 42518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (so) { 42528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef IPSEC 42538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ipsec_delete_pcbpolicy(ip_pcb); 42548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* IPSEC */ 42558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Unlocks not needed since the socket is gone now */ 42578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __Panda__ 42598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ip_pcb->inp_options) { 42608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_m_free(ip_pcb->inp_options); 42618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ip_pcb->inp_options = 0; 42628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 42648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__Panda__) || defined(__Windows__) || defined(__Userspace__)) 42668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__FreeBSD__) || __FreeBSD_version < 500000 42678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (rt) { 42688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen RTFREE(rt); 42698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ip_pcb->inp_route.ro_rt = 0; 42708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 4272f7068d8ea8f314aa54a3aaec7d3603a9b9b55e0ctuexen#if defined(__FreeBSD__) && __FreeBSD_version < 803000 42738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 42748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ip_pcb->inp_moptions) { 42758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp_freemoptions(ip_pcb->inp_moptions); 42768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ip_pcb->inp_moptions = 0; 42778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 42788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 42798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 42808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 42818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 4283e765e73401fe6a4cd2740e2273f5f91c874cd3e5t#if !(defined(__Panda__) || defined(__Windows__) || defined(__Userspace__)) 4284e765e73401fe6a4cd2740e2273f5f91c874cd3e5t#if defined(__FreeBSD__) || defined(__APPLE__) 42858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ip_pcb->inp_vflag & INP_IPV6) { 4286e765e73401fe6a4cd2740e2273f5f91c874cd3e5t#else 4287e765e73401fe6a4cd2740e2273f5f91c874cd3e5t if (inp->inp_vflag & INP_IPV6) { 42888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 42898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct in6pcb *in6p; 42908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 42918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen in6p = (struct in6pcb *)inp; 42928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ip6_freepcbopts(in6p->in6p_outputopts); 42938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4294e765e73401fe6a4cd2740e2273f5f91c874cd3e5t#endif 42958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* INET6 */ 42968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)) 42978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->inp_vflag = 0; 42988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 42998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ip_pcb->inp_vflag = 0; 43008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 43018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free up authentication fields */ 43028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_ep.local_auth_chunks != NULL) 43038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_chunklist(inp->sctp_ep.local_auth_chunks); 43048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_ep.local_hmacs != NULL) 43058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_hmaclist(inp->sctp_ep.local_hmacs); 43068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(shared_key, &inp->sctp_ep.shared_keys, next, nshared_key) { 43088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(shared_key, next); 43098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_sharedkey(shared_key); 43108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 43118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 43148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_state = INPCB_STATE_DEAD; 4315e8462524a4831589c29f7609529ce8eec40e4e5dtuexen if (in_pcb_checkstate(&inp->ip_inp.inp, WNT_STOPUSING, 1) != WNT_STOPUSING) { 431673ebd69a3b24c68f2419fc040e13878cf3956cf9tuexen#ifdef INVARIANTS 4317ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t panic("sctp_inpcb_free inp = %p couldn't set to STOPUSING\n", (void *)inp); 4318e8462524a4831589c29f7609529ce8eec40e4e5dtuexen#else 4319ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t SCTP_PRINTF("sctp_inpcb_free inp = %p couldn't set to STOPUSING\n", (void *)inp); 432073ebd69a3b24c68f2419fc040e13878cf3956cf9tuexen#endif 4321e8462524a4831589c29f7609529ce8eec40e4e5dtuexen } 43228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_socket->so_flags |= SOF_PCBCLEARING; 43238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 43248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 43258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if we have an address list the following will free the list of 43268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ifaddr's that are set into this ep. Again macro limitations here, 43278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since the LIST_FOREACH could be a bad idea. 43288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 43298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) { 43308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_remove_laddr(laddr); 43318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TRACK_FREED_ASOCS 43348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TEMP CODE */ 43358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(asoc, &inp->sctp_asoc_free_list, sctp_tcblist, nasoc) { 43368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(asoc, sctp_tcblist); 43378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), asoc); 43388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_ASOC_COUNT(); 43398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* *** END TEMP CODE ****/ 43418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 43428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF 43438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF); 43448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 43458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now lets see about freeing the EP hash table. */ 43468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_tcbhash != NULL) { 43478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(inp->sctp_tcbhash, inp->sctp_hashmark); 43488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_tcbhash = NULL; 43498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now we must put the ep memory back into the zone pool */ 43518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) 4352998635733088fde643e6d807fa76679c4ceeaa00t crfree(inp->ip_inp.inp.inp_cred); 43538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen INP_LOCK_DESTROY(&inp->ip_inp.inp); 43548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 43558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_LOCK_DESTROY(inp); 43568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_READ_DESTROY(inp); 43578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ASOC_CREATE_LOCK_DESTROY(inp); 43588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) 43598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp); 43608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_EP_COUNT(); 43618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 43628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* For Tiger, we will do this later... */ 43638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 43648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 43658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_nets * 43688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_findnet(struct sctp_tcb *stcb, struct sockaddr *addr) 43698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 43708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 43718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* locate the address */ 43728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 43738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_cmpaddr(addr, (struct sockaddr *)&net->ro._l_addr)) 43748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (net); 43758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 43778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 43788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 43818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_address_on_local_host(struct sockaddr *addr, uint32_t vrf_id) 43828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 43838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __Panda__ 43848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 43858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 43868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *sctp_ifa; 43878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ifa = sctp_find_ifa_by_addr(addr, vrf_id, SCTP_ADDR_NOT_LOCKED); 43888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_ifa) { 43898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 43908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 43918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 43928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 43938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 43948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 43958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 43968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 43978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * add's a remote endpoint address, done with the INIT/INIT-ACK as well as 43988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * when a ASCONF arrives that adds it. It will also initialize all the cwnd 43998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * stats of stuff. 44008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 44018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 44028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr, 44038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets **netp, int set_scope, int from) 44048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 44058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 44068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * The following is redundant to the same lines in the 44078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_aloc_assoc() but is needed since others call the add 44088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address function 44098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 44108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, *netfirst; 44118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int addr_inscope; 44128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB1, "Adding an address (from:%d) to the peer: ", 44148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen from); 44158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_PCB1, newaddr); 44168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netfirst = sctp_findnet(stcb, newaddr); 44188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netfirst) { 44198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 44208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Lie and return ok, we don't want to make the association 44218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * go away for this behavior. It will happen in the TCP 44228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * model in a connected socket. It does not reach the hash 44238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * table until after the association is built so it can't be 44248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * found. Mark as reachable, since the initial creation will 44258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * have been cleared and the NOT_IN_ASSOC flag will have 44268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * been added... and we don't want to end up removing it 44278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * back out. 44288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 44298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netfirst->dest_state & SCTP_ADDR_UNCONFIRMED) { 44308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netfirst->dest_state = (SCTP_ADDR_REACHABLE | 44318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_UNCONFIRMED); 44328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 44338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netfirst->dest_state = SCTP_ADDR_REACHABLE; 44348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 44378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_inscope = 1; 44398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (newaddr->sa_family) { 44408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 44418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 44428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 44438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 44448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = (struct sockaddr_in *)newaddr; 44468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sin->sin_addr.s_addr == 0) { 44478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Invalid address */ 44488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 44498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* zero out the bzero area */ 44518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); 44528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* assure len is set */ 44547b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 44558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin->sin_len = sizeof(struct sockaddr_in); 44568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 44578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (set_scope) { 44588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DONT_DO_PRIVADDR_SCOPE 44591e540eb0bb67e9832e4ccc793a4271c53eb49e8ft stcb->asoc.scope.ipv4_local_scope = 1; 44608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 44618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) { 44627988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.ipv4_local_scope = 1; 44638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_DONT_DO_PRIVADDR_SCOPE */ 44658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 44668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Validate the address is in scope */ 44678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) && 44687988ea8f0c067cf3757e798b473b1ae4d34b6dfdt (stcb->asoc.scope.ipv4_local_scope == 0)) { 44698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_inscope = 0; 44708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 44738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 44758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 44768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 44778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 44788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 44798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 44808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)newaddr; 44818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 44828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Invalid address */ 44838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 44848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 44858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* assure len is set */ 44867b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN 44878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_len = sizeof(struct sockaddr_in6); 44888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 44898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (set_scope) { 44908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id)) { 44917988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.loopback_scope = 1; 44927988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.local_scope = 0; 44937988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.ipv4_local_scope = 1; 44947988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.site_scope = 1; 44958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 44968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 44978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If the new destination is a LINK_LOCAL we 44988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * must have common site scope. Don't set 44998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the local scope since we may not share 45008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * all links, only loopback can do this. 45018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Links on the local network would also be 45028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * on our private network for v4 too. 45038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 45047988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.ipv4_local_scope = 1; 45057988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.site_scope = 1; 45068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { 45078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 45088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If the new destination is SITE_LOCAL then 45098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we must have site scope in common. 45108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 45117988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.site_scope = 1; 45128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 45148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Validate the address is in scope */ 45158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) && 45167988ea8f0c067cf3757e798b473b1ae4d34b6dfdt (stcb->asoc.scope.loopback_scope == 0)) { 45178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_inscope = 0; 45188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 45197988ea8f0c067cf3757e798b473b1ae4d34b6dfdt (stcb->asoc.scope.local_scope == 0)) { 45208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_inscope = 0; 45218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && 45227988ea8f0c067cf3757e798b473b1ae4d34b6dfdt (stcb->asoc.scope.site_scope == 0)) { 45238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_inscope = 0; 45248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 45278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 45296a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#if defined(__Userspace__) 45306a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen case AF_CONN: 45316a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen { 45326a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen struct sockaddr_conn *sconn; 45336a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen 45346a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen sconn = (struct sockaddr_conn *)newaddr; 45356a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen if (sconn->sconn_addr == NULL) { 45366a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen /* Invalid address */ 45376a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen return (-1); 45386a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen } 45397b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SCONN_LEN 45406a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen sconn->sconn_len = sizeof(struct sockaddr_conn); 45416a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 45426a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen break; 45436a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen } 45446a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 45458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 45468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not supported family type */ 45478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 45488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_net), struct sctp_nets); 45508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == NULL) { 45518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 45528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INCR_RADDR_COUNT(); 45548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(net, sizeof(struct sctp_nets)); 45558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&net->start_time); 4556dcaf6808815dc9f58550c7c846d9a4dc10d7d89et#ifdef HAVE_SA_LEN 4557dcaf6808815dc9f58550c7c846d9a4dc10d7d89et memcpy(&net->ro._l_addr, newaddr, newaddr->sa_len); 4558dcaf6808815dc9f58550c7c846d9a4dc10d7d89et#endif 45598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (newaddr->sa_family) { 45608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 45618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 4562dcaf6808815dc9f58550c7c846d9a4dc10d7d89et#ifndef HAVE_SA_LEN 45638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&net->ro._l_addr, newaddr, sizeof(struct sockaddr_in)); 45648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 45658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((struct sockaddr_in *)&net->ro._l_addr)->sin_port = stcb->rport; 45668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 45678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 45688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 45698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 4570dcaf6808815dc9f58550c7c846d9a4dc10d7d89et#ifndef HAVE_SA_LEN 45718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(&net->ro._l_addr, newaddr, sizeof(struct sockaddr_in6)); 45728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 45738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((struct sockaddr_in6 *)&net->ro._l_addr)->sin6_port = stcb->rport; 45748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 45758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 45766a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#if defined(__Userspace__) 45776a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen case AF_CONN: 4578dcaf6808815dc9f58550c7c846d9a4dc10d7d89et#ifndef HAVE_SA_LEN 45796a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen memcpy(&net->ro._l_addr, newaddr, sizeof(struct sockaddr_conn)); 45806a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 45816a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen ((struct sockaddr_conn *)&net->ro._l_addr)->sconn_port = stcb->rport; 45826a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen break; 45836a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 45848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 45858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 45868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->addr_is_local = sctp_is_address_on_local_host(newaddr, stcb->asoc.vrf_id); 45888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->addr_is_local && ((set_scope || (from == SCTP_ADDR_IS_CONFIRMED)))) { 45897988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.loopback_scope = 1; 45907988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.ipv4_local_scope = 1; 45917988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.local_scope = 0; 45927988ea8f0c067cf3757e798b473b1ae4d34b6dfdt stcb->asoc.scope.site_scope = 1; 45938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen addr_inscope = 1; 45948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 45958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->failure_threshold = stcb->asoc.def_net_failure; 45968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->pf_threshold = stcb->asoc.def_net_pf_threshold; 45978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (addr_inscope == 0) { 45988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state = (SCTP_ADDR_REACHABLE | 45998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_OUT_OF_SCOPE); 46008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 46018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from == SCTP_ADDR_IS_CONFIRMED) 46028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* SCTP_ADDR_IS_CONFIRMED is passed by connect_x */ 46038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state = SCTP_ADDR_REACHABLE; 46048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 46058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state = SCTP_ADDR_REACHABLE | 46068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_UNCONFIRMED; 46078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We set this to 0, the timer code knows that 46098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this means its an initial value 46108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 46118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->rto_needed = 1; 4612e2828360ea9cf8951730d46f5c14626c9425cb30t net->RTO = 0; 46138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->RTO_measured = 0; 46148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.numnets++; 4615153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen net->ref_count = 1; 46168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->cwr_window_tsn = net->last_cwr_tsn = stcb->asoc.sending_seq - 1; 4617153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen net->port = stcb->asoc.port; 46188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dscp = stcb->asoc.default_dscp; 46198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 46208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->flowlabel = stcb->asoc.default_flowlabel; 46218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 46228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) { 46238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state |= SCTP_ADDR_NOHB; 46248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 46258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state &= ~SCTP_ADDR_NOHB; 46268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) { 46288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state |= SCTP_ADDR_NO_PMTUD; 46298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 46308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state &= ~SCTP_ADDR_NO_PMTUD; 46318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->heart_beat_delay = stcb->asoc.heart_beat_delay; 46338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Init the timer structure */ 46348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&net->rxt_timer.timer); 46358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&net->pmtu_timer.timer); 46368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&net->hb_timer.timer); 46378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now generate a route for this guy */ 46398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 46408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_EMBEDDED_V6_SCOPE 46418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* KAME hack: embed scopeid */ 46428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (newaddr->sa_family == AF_INET6) { 46438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 46448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 4646c2ae94ce88da509bd10c652de26407ac5b2ee97ctuexen#if defined(__APPLE__) 46471ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) 46481ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen (void)in6_embedscope(&sin6->sin6_addr, sin6, &stcb->sctp_ep->ip_inp.inp, NULL); 46498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 46501ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen (void)in6_embedscope(&sin6->sin6_addr, sin6, &stcb->sctp_ep->ip_inp.inp, NULL, NULL); 46518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 46528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(SCTP_KAME) 46538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sa6_embedscope(sin6, MODULE_GLOBAL(ip6_use_defzone)); 46548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 46558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)in6_embedscope(&sin6->sin6_addr, sin6); 46568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 46578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef SCOPEDROUTING 46588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6->sin6_scope_id = 0; 46598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 46608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 46618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */ 46628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 46638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_RTALLOC((sctp_route_t *)&net->ro, stcb->asoc.vrf_id); 46648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46654ebd24bf249e4dd566cc01e122361ce9681cee49t#if defined(__Userspace__) 46664ebd24bf249e4dd566cc01e122361ce9681cee49t net->src_addr_selected = 0; 46674ebd24bf249e4dd566cc01e122361ce9681cee49t#else 46688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro)) { 46698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Get source address */ 46708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro._s_addr = sctp_source_address_selection(stcb->sctp_ep, 46718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, 46728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_route_t *)&net->ro, 46738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net, 46748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, 46758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.vrf_id); 46764ebd24bf249e4dd566cc01e122361ce9681cee49t if (net->ro._s_addr != NULL) { 46774ebd24bf249e4dd566cc01e122361ce9681cee49t net->src_addr_selected = 1; 46784ebd24bf249e4dd566cc01e122361ce9681cee49t /* Now get the interface MTU */ 46794ebd24bf249e4dd566cc01e122361ce9681cee49t if (net->ro._s_addr->ifn_p != NULL) { 46804ebd24bf249e4dd566cc01e122361ce9681cee49t net->mtu = SCTP_GATHER_MTU_FROM_INTFC(net->ro._s_addr->ifn_p); 46814ebd24bf249e4dd566cc01e122361ce9681cee49t } 46824ebd24bf249e4dd566cc01e122361ce9681cee49t } else { 46834ebd24bf249e4dd566cc01e122361ce9681cee49t net->src_addr_selected = 0; 46848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4685e1c11e93db18d719a486b6b7fe68f095c950e492tuexen if (net->mtu > 0) { 46868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t rmtu; 46878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 46888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rmtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, net->ro.ro_rt); 46898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (rmtu == 0) { 46908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Start things off to match mtu of interface please. */ 46918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SET_MTU_OF_ROUTE(&net->ro._l_addr.sa, 46928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro.ro_rt, net->mtu); 46938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 46948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we take the route mtu over the interface, since 46958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the route may be leading out the loopback, or 46968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a different interface. 46978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 46984ebd24bf249e4dd566cc01e122361ce9681cee49t net->mtu = rmtu; 46998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47004ebd24bf249e4dd566cc01e122361ce9681cee49t } 47014ebd24bf249e4dd566cc01e122361ce9681cee49t } else { 47024ebd24bf249e4dd566cc01e122361ce9681cee49t net->src_addr_selected = 0; 470332a191a90b5c914a02047389c5b3197e08fc9841tuexen } 47041141c3cab80d58656c01caa571399fad29063a85t#endif 4705e1c11e93db18d719a486b6b7fe68f095c950e492tuexen if (net->mtu == 0) { 4706e1c11e93db18d719a486b6b7fe68f095c950e492tuexen switch (newaddr->sa_family) { 4707e1c11e93db18d719a486b6b7fe68f095c950e492tuexen#ifdef INET 4708e1c11e93db18d719a486b6b7fe68f095c950e492tuexen case AF_INET: 4709e1c11e93db18d719a486b6b7fe68f095c950e492tuexen net->mtu = SCTP_DEFAULT_MTU; 4710e1c11e93db18d719a486b6b7fe68f095c950e492tuexen break; 4711e1c11e93db18d719a486b6b7fe68f095c950e492tuexen#endif 4712e1c11e93db18d719a486b6b7fe68f095c950e492tuexen#ifdef INET6 4713e1c11e93db18d719a486b6b7fe68f095c950e492tuexen case AF_INET6: 4714e1c11e93db18d719a486b6b7fe68f095c950e492tuexen net->mtu = 1280; 4715e1c11e93db18d719a486b6b7fe68f095c950e492tuexen break; 4716e1c11e93db18d719a486b6b7fe68f095c950e492tuexen#endif 47176a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#if defined(__Userspace__) 47186a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen case AF_CONN: 47196a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen net->mtu = 1280; 47206a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen break; 47216a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 4722e1c11e93db18d719a486b6b7fe68f095c950e492tuexen default: 4723e1c11e93db18d719a486b6b7fe68f095c950e492tuexen break; 47248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 4725e1c11e93db18d719a486b6b7fe68f095c950e492tuexen } 472648830a703639020b04dbea0128bc37fd8a8ab35et#if defined(INET) || defined(INET6) 4727e1c11e93db18d719a486b6b7fe68f095c950e492tuexen if (net->port) { 4728e1c11e93db18d719a486b6b7fe68f095c950e492tuexen net->mtu -= (uint32_t)sizeof(struct udphdr); 4729e1c11e93db18d719a486b6b7fe68f095c950e492tuexen } 47306c632b3f6e570981666f8a3ff4be34eaf1735835t#endif 4731e1c11e93db18d719a486b6b7fe68f095c950e492tuexen if (from == SCTP_ALLOC_ASOC) { 4732e1c11e93db18d719a486b6b7fe68f095c950e492tuexen stcb->asoc.smallest_mtu = net->mtu; 4733e1c11e93db18d719a486b6b7fe68f095c950e492tuexen } 4734e1c11e93db18d719a486b6b7fe68f095c950e492tuexen if (stcb->asoc.smallest_mtu > net->mtu) { 4735e1c11e93db18d719a486b6b7fe68f095c950e492tuexen stcb->asoc.smallest_mtu = net->mtu; 47368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 47388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_EMBEDDED_V6_SCOPE 47398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (newaddr->sa_family == AF_INET6) { 47408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 47418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 47428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)&net->ro._l_addr; 47438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME 47448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sa6_recoverscope(sin6); 47458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 47468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)in6_recoverscope(sin6, &sin6->sin6_addr, NULL); 47478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_KAME */ 47488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */ 47508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 47518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 47528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* JRS - Use the congestion control given in the CC module */ 475332a191a90b5c914a02047389c5b3197e08fc9841tuexen if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) 47548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (*stcb->asoc.cc_functions.sctp_set_initial_cc_param)(stcb, net); 47558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 47568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 47578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CMT: CUC algo - set find_pseudo_cumack to TRUE (1) at beginning 47588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * of assoc (2005/06/27, iyengar@cis.udel.edu) 47598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 47608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->find_pseudo_cumack = 1; 47618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->find_rtx_pseudo_cumack = 1; 47628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) 47638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Choose an initial flowid. */ 47648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->flowid = stcb->asoc.my_vtag ^ 47658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(stcb->rport) ^ 47668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(stcb->sctp_ep->sctp_lport); 47678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 47688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->flowidset = 1; 47698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 47708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 47718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netp) { 47728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *netp = net; 47738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 47748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netfirst = TAILQ_FIRST(&stcb->asoc.nets); 47758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro.ro_rt == NULL) { 47768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Since we have no route put it at the back */ 47778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.nets, net, sctp_next); 47788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (netfirst == NULL) { 47798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We are the first one in the pool. */ 47808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_HEAD(&stcb->asoc.nets, net, sctp_next); 47818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (netfirst->ro.ro_rt == NULL) { 47828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 47838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * First one has NO route. Place this one ahead of the first 47848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one. 47858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 47868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_HEAD(&stcb->asoc.nets, net, sctp_next); 47878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __Panda__ 47888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (net->ro.ro_rt->rt_ifp != netfirst->ro.ro_rt->rt_ifp) { 47898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 47908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This one has a different interface than the one at the 47918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * top of the list. Place it ahead. 47928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 47938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_HEAD(&stcb->asoc.nets, net, sctp_next); 47948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 47958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 47968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 47978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Ok we have the same interface as the first one. Move 47988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * forward until we find either a) one with a NULL route... 47998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * insert ahead of that b) one with a different ifp.. insert 48008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * after that. c) end of the list.. insert at the tail. 48018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 48028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *netlook; 48038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen do { 48058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netlook = TAILQ_NEXT(netfirst, sctp_next); 48068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (netlook == NULL) { 48078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* End of the list */ 48088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&stcb->asoc.nets, net, sctp_next); 48098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 48108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (netlook->ro.ro_rt == NULL) { 48118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* next one has NO route */ 48128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_BEFORE(netfirst, net, sctp_next); 48138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 48148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __Panda__ 48168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else if (netlook->ro.ro_rt->rt_ifp != net->ro.ro_rt->rt_ifp) 48178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 48188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 48198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 48208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 48218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_AFTER(&stcb->asoc.nets, netlook, 48228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net, sctp_next); 48238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 48248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __Panda__ 48268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Shift forward */ 48278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen netfirst = netlook; 48288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 48298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } while (netlook != NULL); 48308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* got to have a primary set */ 48338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.primary_destination == 0) { 48348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination = net; 48358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((stcb->asoc.primary_destination->ro.ro_rt == NULL) && 48368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (net->ro.ro_rt) && 48378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0)) { 48388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* No route to current primary adopt new primary */ 48398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination = net; 48408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Validate primary is first */ 48428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net = TAILQ_FIRST(&stcb->asoc.nets); 48438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((net != stcb->asoc.primary_destination) && 48448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (stcb->asoc.primary_destination)) { 48458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* first one on the list is NOT the primary 48468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_cmpaddr() is much more efficient if 48478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the primary is the first on the list, make it 48488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * so. 48498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 48508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&stcb->asoc.nets, 48518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination, sctp_next); 48528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_HEAD(&stcb->asoc.nets, 48538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination, sctp_next); 48548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 48568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 48578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t 48608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_aloc_a_assoc_id(struct sctp_inpcb *inp, struct sctp_tcb *stcb) 48618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 48628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t id; 48638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpasochead *head; 48648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *lstcb; 48658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(inp); 48678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen try_again: 48688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 48698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TSNH */ 48708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 48718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 48728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 48748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We don't allow assoc id to be one of SCTP_FUTURE_ASSOC, 48758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SCTP_CURRENT_ASSOC and SCTP_ALL_ASSOC. 48768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 48778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_associd_counter <= SCTP_ALL_ASSOC) { 48788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_associd_counter = SCTP_ALL_ASSOC + 1; 48798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen id = inp->sctp_associd_counter; 48818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_associd_counter++; 48828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lstcb = sctp_findasoc_ep_asocid_locked(inp, (sctp_assoc_t)id, 0); 48838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lstcb) { 48848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto try_again; 48858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 48868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &inp->sctp_asocidhash[SCTP_PCBHASH_ASOC(id, inp->hashasocidmark)]; 48878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(head, stcb, sctp_tcbasocidhash); 48888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.in_asocid_hash = 1; 48898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 48908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return id; 48918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 48928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 48938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 48948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * allocate an association and add it to the endpoint. The caller must be 48958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * careful to add all additional addresses once they are know right away or 48968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * else the assoc will be may experience a blackout scenario. 48978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 48988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_tcb * 48998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr, 49008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int *error, uint32_t override_tag, uint32_t vrf_id, 49018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 49028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct thread *p 49038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__) 49048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen PKTHREAD p 49058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 49068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__) 49078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* __Userspace__ NULL proc is going to be passed here. See sctp_lower_sosend */ 49088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 49098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct proc *p 49108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 49118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen) 49128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 49138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* note the p argument is only valid in unbound sockets */ 49148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 49158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 49168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 49178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpasochead *head; 49188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t rport; 49198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int err; 49208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 49218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 49228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Assumption made here: Caller has done a 49238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_findassociation_ep_addr(ep, addr's); to make sure the 49248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address does not exist already. 49258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 49268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_INFO(ipi_count_asoc) >= SCTP_MAX_NUM_OF_ASOC) { 49278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Hit max assoc, sorry no more */ 49288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); 49298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = ENOBUFS; 49308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 49318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (firstaddr == NULL) { 49338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 49348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = EINVAL; 49358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 49368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(inp); 49388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) && 49398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE)) || 49408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) { 49418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 49428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If its in the TCP pool, its NOT allowed to create an 49438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * association. The parent listener needs to call 49448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_aloc_assoc.. or the one-2-many socket. If a peeled 49458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * off, or connected one does this.. its an error. 49468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 49478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 49488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 49498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = EINVAL; 49508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 49518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 49538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)) { 49548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) || 49558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED)) { 49568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 49578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 49588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = EINVAL; 49598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 49608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB3, "Allocate an association for peer:"); 49638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG 49648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (firstaddr) { 49658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG_ADDR(SCTP_DEBUG_PCB3, firstaddr); 49668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (firstaddr->sa_family) { 49678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 49688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 49698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n", 49708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(((struct sockaddr_in *)firstaddr)->sin_port)); 49718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 49728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 49738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 49748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 49758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n", 49768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(((struct sockaddr_in6 *)firstaddr)->sin6_port)); 49778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 49788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 49796a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#if defined(__Userspace__) 49806a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen case AF_CONN: 49816a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen SCTPDBG(SCTP_DEBUG_PCB3, "Port:%d\n", 49826a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen ntohs(((struct sockaddr_conn *)firstaddr)->sconn_port)); 49836a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen break; 49846a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 49858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 49868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 49878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 49898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB3,"None\n"); 49908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 49918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_DEBUG */ 49928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (firstaddr->sa_family) { 49938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 49948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 49958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 49968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in *sin; 49978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 49988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin = (struct sockaddr_in *)firstaddr; 49998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ntohs(sin->sin_port) == 0) || 50008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sin->sin_addr.s_addr == INADDR_ANY) || 50018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sin->sin_addr.s_addr == INADDR_BROADCAST) || 50028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 50038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Invalid address */ 50048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 50058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 50068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = EINVAL; 50078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 50088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rport = sin->sin_port; 50108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 50118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 50138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 50148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 50158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen { 50168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 *sin6; 50178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 50188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6 = (struct sockaddr_in6 *)firstaddr; 50198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ntohs(sin6->sin6_port) == 0) || 50208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || 50218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 50228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Invalid address */ 50238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 50248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 50258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = EINVAL; 50268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 50278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rport = sin6->sin6_port; 50298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 50308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 50326a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#if defined(__Userspace__) 50336a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen case AF_CONN: 50346a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen { 50356a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen struct sockaddr_conn *sconn; 50366a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen 50376a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen sconn = (struct sockaddr_conn *)firstaddr; 50386a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen if ((ntohs(sconn->sconn_port) == 0) || 50396a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen (sconn->sconn_addr == NULL)) { 50406a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen /* Invalid address */ 50416a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen SCTP_INP_RUNLOCK(inp); 50426a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 50436a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen *error = EINVAL; 50446a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen return (NULL); 50456a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen } 50466a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen rport = sconn->sconn_port; 50476a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen break; 50486a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen } 50496a977e5c22f6cf4a20cff9658398a6a7fe42e1adtuexen#endif 50508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 50518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not supported family type */ 50528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 50538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 50548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = EINVAL; 50558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 50568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 50588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { 50598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 50608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * If you have not performed a bind, then we need to do the 50618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ephemeral bind for you. 50628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 50638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((err = sctp_inpcb_bind(inp->sctp_socket, 50648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sockaddr *)NULL, 50658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_ifa *)NULL, 50668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __Panda__ 50678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p 50688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 50698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct proc *)NULL 50708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 50718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ))) { 50728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* bind error, probably perm */ 50738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = err; 50748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 50758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_asoc), struct sctp_tcb); 50788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb == NULL) { 50798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* out of memory? */ 50808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM); 50818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = ENOMEM; 50828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 50838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 50848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INCR_ASOC_COUNT(); 50858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 50868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(stcb, sizeof(*stcb)); 50878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 50888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 50898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->assoc_id = sctp_aloc_a_assoc_id(inp, stcb); 50908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_INIT(stcb); 50918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_LOCK_INIT(stcb); 50928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->rport = rport; 50938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* setup back pointer's */ 50948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep = inp; 50958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_socket = inp->sctp_socket; 50968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((err = sctp_init_asoc(inp, stcb, override_tag, vrf_id))) { 50978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* failed */ 50988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_DESTROY(stcb); 50998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_LOCK_DESTROY(stcb); 51008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_tcbasocidhash); 51018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); 51028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_ASOC_COUNT(); 51038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = err; 51048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 51058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* and the port */ 51078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WLOCK(); 51088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(inp); 51098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & (SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 51108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* inpcb freed while alloc going on */ 51118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_DESTROY(stcb); 51128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_LOCK_DESTROY(stcb); 51138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_tcbasocidhash); 51148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); 51158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 51168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 51178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_ASOC_COUNT(); 51188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 51198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = EINVAL; 51208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 51218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 51238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now that my_vtag is set, add it to the hash */ 51258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 51268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* put it in the bucket in the vtag hash of assoc's for the system */ 51278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(head, stcb, sctp_asocs); 51288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 51298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((err = sctp_add_remote_addr(stcb, firstaddr, NULL, SCTP_DO_SETSCOPE, SCTP_ALLOC_ASOC))) { 51318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* failure.. memory error? */ 51328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->strmout) { 51338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(asoc->strmout, SCTP_M_STRMO); 51348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmout = NULL; 51358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->mapping_array) { 51378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); 51388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->mapping_array = NULL; 51398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->nr_mapping_array) { 51418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP); 51428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->nr_mapping_array = NULL; 51438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_ASOC_COUNT(); 51456094da0ffddb92b1921fb00169cd740ef64807det SCTP_TCB_UNLOCK(stcb); 51468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_DESTROY(stcb); 51478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_LOCK_DESTROY(stcb); 51488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_tcbasocidhash); 51498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); 51508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 51518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS); 51528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *error = ENOBUFS; 51538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 51548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Init all the timers */ 51568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&asoc->dack_timer.timer); 51578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&asoc->strreset_timer.timer); 51588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&asoc->asconf_timer.timer); 51598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&asoc->shut_guard_timer.timer); 51608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&asoc->autoclose_timer.timer); 51618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&asoc->delayed_event_timer.timer); 51628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&asoc->delete_prim_timer.timer); 51638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&inp->sctp_asoc_list, stcb, sctp_tcblist); 51658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now file the port under the hash as well */ 51668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_tcbhash != NULL) { 51678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &inp->sctp_tcbhash[SCTP_PCBHASH_ALLADDR(stcb->rport, 51688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_hashmark)]; 51698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(head, stcb, sctp_tcbhash); 51708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 51718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 5172ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t SCTPDBG(SCTP_DEBUG_PCB1, "Association %p now allocated\n", (void *)stcb); 51738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (stcb); 51748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 51758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 51788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_remove_net(struct sctp_tcb *stcb, struct sctp_nets *net) 51798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 51808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 51818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 51838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->numnets--; 51848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->nets, net, sctp_next); 51858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == asoc->primary_destination) { 51868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Reset primary */ 51878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *lnet; 51888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 51898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lnet = TAILQ_FIRST(&asoc->nets); 51908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Mobility adaptation 51918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen Ideally, if deleted destination is the primary, it becomes 51928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen a fast retransmission trigger by the subsequent SET PRIMARY. 51938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (by micchie) 51948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 51958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_is_mobility_feature_on(stcb->sctp_ep, 5196e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_BASE) || 51978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_mobility_feature_on(stcb->sctp_ep, 5198e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_MOBILITY_FASTHANDOFF)) { 51998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "remove_net: primary dst is deleting\n"); 52008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->deleted_primary != NULL) { 52018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_ASCONF1, "remove_net: deleted primary may be already stored\n"); 52028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out; 52038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->deleted_primary = net; 52058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&net->ref_count, 1); 52068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&net->lastsa, 0, sizeof(net->lastsa)); 52078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&net->lastsv, 0, sizeof(net->lastsv)); 52088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mobility_feature_on(stcb->sctp_ep, 52098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MOBILITY_PRIM_DELETED); 52108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_PRIM_DELETED, 52118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->sctp_ep, stcb, NULL); 52128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenout: 52148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Try to find a confirmed primary */ 52158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->primary_destination = sctp_find_alternate_net(stcb, lnet, 0); 52168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == asoc->last_data_chunk_from) { 52188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Reset primary */ 52198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_data_chunk_from = TAILQ_FIRST(&asoc->nets); 52208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == asoc->last_control_chunk_from) { 52228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Clear net */ 52238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_control_chunk_from = NULL; 52248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == stcb->asoc.alternate) { 52268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(stcb->asoc.alternate); 52278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.alternate = NULL; 52288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(net); 52308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 52318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 52338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * remove a remote endpoint address from an association, it will fail if the 52348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address does not exist. 52358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 52368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 52378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_del_remote_addr(struct sctp_tcb *stcb, struct sockaddr *remaddr) 52388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 52398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 52408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Here we need to remove a remote address. This is quite simple, we 52418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * first find it in the list of address for the association 52428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (tasoc->asoc.nets) and then if it is there, we do a LIST_REMOVE 52438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * on that item. Note we do not allow it to be removed if there are 52448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * no other addresses. 52458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 52468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 52478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, *nnet; 52488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 52508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* locate the address */ 52528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(net, &asoc->nets, sctp_next, nnet) { 52538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._l_addr.sa.sa_family != remaddr->sa_family) { 52548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 52558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_cmpaddr((struct sockaddr *)&net->ro._l_addr, 52578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen remaddr)) { 52588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we found the guy */ 52598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->numnets < 2) { 52608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Must have at LEAST two remote addresses */ 52618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 52628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 52638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_remove_net(stcb, net); 52648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 52658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not found. */ 52698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-2); 52708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 52718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 52738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_delete_from_timewait(uint32_t tag, uint16_t lport, uint16_t rport) 52748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 52758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpvtaghead *chain; 52768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tagblock *twait_block; 5277b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int found = 0; 52788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 52798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; 528115aed6e434dc1aac416f14635bb78920317d60e7t LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { 528215aed6e434dc1aac416f14635bb78920317d60e7t for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { 528315aed6e434dc1aac416f14635bb78920317d60e7t if ((twait_block->vtag_block[i].v_tag == tag) && 528415aed6e434dc1aac416f14635bb78920317d60e7t (twait_block->vtag_block[i].lport == lport) && 528515aed6e434dc1aac416f14635bb78920317d60e7t (twait_block->vtag_block[i].rport == rport)) { 528615aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].tv_sec_at_expire = 0; 528715aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].v_tag = 0; 528815aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].lport = 0; 528915aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].rport = 0; 529015aed6e434dc1aac416f14635bb78920317d60e7t found = 1; 52918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 529215aed6e434dc1aac416f14635bb78920317d60e7t } 52938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 529415aed6e434dc1aac416f14635bb78920317d60e7t if (found) 529515aed6e434dc1aac416f14635bb78920317d60e7t break; 52968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 52978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 52988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 52998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 53008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_in_timewait(uint32_t tag, uint16_t lport, uint16_t rport) 53018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 53028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpvtaghead *chain; 53038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tagblock *twait_block; 5304b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int found = 0; 53058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 53068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 53078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WLOCK(); 53088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; 530915aed6e434dc1aac416f14635bb78920317d60e7t LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { 531015aed6e434dc1aac416f14635bb78920317d60e7t for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { 531115aed6e434dc1aac416f14635bb78920317d60e7t if ((twait_block->vtag_block[i].v_tag == tag) && 531215aed6e434dc1aac416f14635bb78920317d60e7t (twait_block->vtag_block[i].lport == lport) && 531315aed6e434dc1aac416f14635bb78920317d60e7t (twait_block->vtag_block[i].rport == rport)) { 531415aed6e434dc1aac416f14635bb78920317d60e7t found = 1; 53158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 531615aed6e434dc1aac416f14635bb78920317d60e7t } 53178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 531815aed6e434dc1aac416f14635bb78920317d60e7t if (found) 531915aed6e434dc1aac416f14635bb78920317d60e7t break; 53208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 5322b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen return (found); 53238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 53248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 53258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 53268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 53278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_add_vtag_to_timewait(uint32_t tag, uint32_t time, uint16_t lport, uint16_t rport) 53288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 53298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpvtaghead *chain; 53308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tagblock *twait_block; 53318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval now; 53328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int set, i; 53338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 53348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (time == 0) { 53358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its disabled */ 53368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 53378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&now); 53398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; 53408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen set = 0; 534115aed6e434dc1aac416f14635bb78920317d60e7t LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { 53428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Block(s) present, lets find space, and expire on the fly */ 534315aed6e434dc1aac416f14635bb78920317d60e7t for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { 534415aed6e434dc1aac416f14635bb78920317d60e7t if ((twait_block->vtag_block[i].v_tag == 0) && 534515aed6e434dc1aac416f14635bb78920317d60e7t !set) { 534615aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].tv_sec_at_expire = 534715aed6e434dc1aac416f14635bb78920317d60e7t now.tv_sec + time; 534815aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].v_tag = tag; 534915aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].lport = lport; 535015aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].rport = rport; 535115aed6e434dc1aac416f14635bb78920317d60e7t set = 1; 535215aed6e434dc1aac416f14635bb78920317d60e7t } else if ((twait_block->vtag_block[i].v_tag) && 535315aed6e434dc1aac416f14635bb78920317d60e7t ((long)twait_block->vtag_block[i].tv_sec_at_expire < now.tv_sec)) { 535415aed6e434dc1aac416f14635bb78920317d60e7t /* Audit expires this guy */ 535515aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].tv_sec_at_expire = 0; 535615aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].v_tag = 0; 535715aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].lport = 0; 535815aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].rport = 0; 535915aed6e434dc1aac416f14635bb78920317d60e7t if (set == 0) { 536015aed6e434dc1aac416f14635bb78920317d60e7t /* Reuse it for my new tag */ 536115aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].tv_sec_at_expire = now.tv_sec + time; 53628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen twait_block->vtag_block[i].v_tag = tag; 53638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen twait_block->vtag_block[i].lport = lport; 53648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen twait_block->vtag_block[i].rport = rport; 53658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen set = 1; 53668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 536815aed6e434dc1aac416f14635bb78920317d60e7t } 536915aed6e434dc1aac416f14635bb78920317d60e7t if (set) { 537015aed6e434dc1aac416f14635bb78920317d60e7t /* 537115aed6e434dc1aac416f14635bb78920317d60e7t * We only do up to the block where we can 537215aed6e434dc1aac416f14635bb78920317d60e7t * place our tag for audits 537315aed6e434dc1aac416f14635bb78920317d60e7t */ 537415aed6e434dc1aac416f14635bb78920317d60e7t break; 53758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Need to add a new block to chain */ 53788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!set) { 53798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(twait_block, struct sctp_tagblock *, 53808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_tagblock), SCTP_M_TIMW); 53818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (twait_block == NULL) { 53828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 53838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("Can not alloc tagblock"); 53848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 53858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 53868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(twait_block, 0, sizeof(struct sctp_tagblock)); 53888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(chain, twait_block, sctp_nxt_tagblock); 53898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen twait_block->vtag_block[0].tv_sec_at_expire = now.tv_sec + time; 53908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen twait_block->vtag_block[0].v_tag = tag; 53918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen twait_block->vtag_block[0].lport = lport; 53928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen twait_block->vtag_block[0].rport = rport; 53938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 53948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 53958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 53968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 53978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __Panda__ 53988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid panda_wakeup_socket(struct socket *so); 53998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 54008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 54018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*- 54028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Free the association after un-hashing the remote port. This 54038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * function ALWAYS returns holding NO LOCK on the stcb. It DOES 54048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * expect that the input to this function IS a locked TCB. 54058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * It will return 0, if it did NOT destroy the association (instead 54068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it unlocks it. It will return NON-zero if it either destroyed the 54078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * association OR the association is already destroyed. 54088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 54098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 54108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfree, int from_location) 54118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 54128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 54138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 54148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, *nnet; 54158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr, *naddr; 54168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, *nchk; 54178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr *aparam, *naparam; 54188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_ack *aack, *naack; 54198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_reset_list *strrst, *nstrrst; 54208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *sq, *nsq; 54218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_queue_pending *sp, *nsp; 54228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sharedkey_t *shared_key, *nshared_key; 54238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct socket *so; 54248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 54258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* first, lets purge the entry from the hash table. */ 54268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 54278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_lock_assert(SCTP_INP_SO(inp)); 54288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 54298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 54308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 54318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, stcb, 6); 54328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 54338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state == 0) { 54348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 54358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, NULL, 7); 54368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 54378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* there is no asoc, really TSNH :-0 */ 54388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 54398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.alternate) { 54418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(stcb->asoc.alternate); 54428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.alternate = NULL; 54438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) /* TEMP: moved to below */ 54458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TEMP CODE */ 54468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->freed_from_where == 0) { 54478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Only record the first place free happened from */ 54488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->freed_from_where = from_location; 54498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TEMP CODE */ 54518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 54528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 54538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 54548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 54558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) 54568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing around */ 54578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = NULL; 54588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 54598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = inp->sctp_socket; 54608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 54618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 54628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We used timer based freeing if a reader or writer is in the way. 54638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * So we first check if we are actually being called from a timer, 54648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if so we abort early if a reader or writer is still in the way. 54658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 54668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) && 54678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (from_inpcbfree == SCTP_NORMAL_PROC)) { 54688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 54698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is it the timer driving us? if so are the reader/writers 54708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * gone? 54718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 54728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.refcnt) { 54738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nope, reader or writer in the way */ 54748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL); 54758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no asoc destroyed */ 54768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 54778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 54788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, stcb, 8); 54798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 54808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 54818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 54838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now clean up any other timers */ 54848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); 54858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->dack_timer.self = NULL; 54868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); 54878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*- 54888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For stream reset we don't blast this unless 54898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * it is a str-reset timer, it might be the 54908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * free-asoc timer which we DON'T want to 54918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * disturb. 54928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 54938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->strreset_timer.type == SCTP_TIMER_TYPE_STRRESET) 54948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strreset_timer.self = NULL; 54958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); 54968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->asconf_timer.self = NULL; 54978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); 54988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->autoclose_timer.self = NULL; 54998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer); 55008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->shut_guard_timer.self = NULL; 55018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); 55028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->delayed_event_timer.self = NULL; 55038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Mobility adaptation */ 55048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->delete_prim_timer.timer); 55058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->delete_prim_timer.self = NULL; 55068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 55078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&net->rxt_timer.timer); 55088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->rxt_timer.self = NULL; 55098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); 55108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->pmtu_timer.self = NULL; 55118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer); 55128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->hb_timer.self = NULL; 55138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now the read queue needs to be cleaned up (only once) */ 55158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0) { 55168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.state |= SCTP_STATE_ABOUT_TO_BE_FREED; 55178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_READ_LOCK(inp); 55188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(sq, &inp->read_queue, next) { 55198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sq->stcb == stcb) { 55208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sq->do_not_ref_stcb = 1; 55218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sq->sinfo_cumtsn = stcb->asoc.cumulative_tsn; 55228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If there is no end, there never 55238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * will be now. 55248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 55258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sq->end_added == 0) { 55268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Held for PD-API clear that. */ 55278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sq->pdapi_aborted = 1; 55288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sq->held_length = 0; 55298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT) && (so != NULL)) { 55308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 55318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Need to add a PD-API aborted indication. 55328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Setting the control_pdapi assures that it will 55338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * be added right after this msg. 55348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 55358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t strseq; 55368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.control_pdapi = sq; 55378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen strseq = (sq->sinfo_stream << 16) | sq->sinfo_ssn; 55388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION, 55398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb, 55408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PARTIAL_DELIVERY_ABORTED, 55418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void *)&strseq, 55428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SO_LOCKED); 55438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.control_pdapi = NULL; 55448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Add an end to wake them */ 55478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sq->end_added = 1; 55488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_READ_UNLOCK(inp); 55518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->block_entry) { 55528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_PCB, ECONNRESET); 55538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->block_entry->error = ECONNRESET; 55548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->block_entry = NULL; 55558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.refcnt) || (stcb->asoc.state & SCTP_STATE_IN_ACCEPT_QUEUE)) { 55588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Someone holds a reference OR the socket is unaccepted yet. 55598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 55608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb->asoc.refcnt) || 55618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 55628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { 55638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; 55648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL); 55658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 55678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 55688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) 55698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing around */ 55708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = NULL; 55718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (so) { 55728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Wake any reader/writers */ 55738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sorwakeup(inp, so); 55748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sowwakeup(inp, so); 55758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 55778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 55788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, stcb, 9); 55798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 55808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no asoc destroyed */ 55818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 55828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 55838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 55848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, stcb, 10); 55858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 55868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* When I reach here, no others want 55878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to kill the assoc yet.. and I own 55888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the lock. Now its possible an abort 55898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * comes in when I do the lock exchange 55908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * below to grab all the locks to do 55918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the final take out. to prevent this 55928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we increment the count, which will 55938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * start a timer and blow out above thus 55948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assuring us that we hold exclusive 55958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * killing of the asoc. Note that 55968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * after getting back the TCB lock 55978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we will go ahead and increment the 55988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * counter back up and stop any timer 55998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a passing stranger may have started :-S 56008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 56018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from_inpcbfree == SCTP_NORMAL_PROC) { 56028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 56038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 56058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WLOCK(); 56068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WLOCK(inp); 56078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 56088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Double check the GONE flag */ 56108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 56118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) 56128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* nothing around */ 56138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so = NULL; 56148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 56168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 56178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 56188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * For TCP type we need special handling when we are 56198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * connected. We also include the peel'ed off ones to. 56208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 56218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { 56228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED; 56238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_flags |= SCTP_PCB_FLAGS_WAS_CONNECTED; 56248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (so) { 56258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SOCK_LOCK(so); 56268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (so->so_rcv.sb_cc == 0) { 56278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen so->so_state &= ~(SS_ISCONNECTING | 56288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SS_ISDISCONNECTING | 56298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SS_ISCONFIRMING | 56308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SS_ISCONNECTED); 56318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 56338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen socantrcvmore(so); 56348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 56358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen socantrcvmore_locked(so); 56368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 56378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sowwakeup(inp, so); 56388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_sorwakeup(inp, so); 56398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_SOWAKEUP(so); 56408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Make it invalid too, that way if its 56458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * about to run it will abort and return. 56468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 56478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* re-increment the lock */ 56488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from_inpcbfree == SCTP_NORMAL_PROC) { 56498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, -1); 56508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.refcnt) { 56528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE; 56538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL); 56548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from_inpcbfree == SCTP_NORMAL_PROC) { 56558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 56568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 56578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 56598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 56608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->state = 0; 56628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_tcbhash) { 56638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_tcbhash); 56648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.in_asocid_hash) { 56668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_tcbasocidhash); 56678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now lets remove it from the list of ALL associations in the EP */ 56698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_tcblist); 56708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from_inpcbfree == SCTP_NORMAL_PROC) { 56718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INCR_REF(inp); 56728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_WUNLOCK(inp); 56738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* pull from vtag hash */ 56758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(stcb, sctp_asocs); 56768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_add_vtag_to_timewait(asoc->my_vtag, SCTP_BASE_SYSCTL(sctp_vtag_time_wait), 56778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->sctp_lport, stcb->rport); 56788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now restop the timers to be sure 56808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this is paranoia at is finest! 56818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 56828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); 56838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); 56848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); 56858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); 56868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->shut_guard_timer.timer); 56878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); 56888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); 56898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 56908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&net->rxt_timer.timer); 56918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); 56928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer); 56938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 56948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 56958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strreset_timer.type = SCTP_TIMER_TYPE_NONE; 56968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 56978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * The chunk lists and such SHOULD be empty but we check them just 56988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * in case. 56998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 57008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* anything on the wheel needs to be removed */ 57018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < asoc->streamoutcnt; i++) { 57028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_stream_out *outs; 57038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 57048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen outs = &asoc->strmout[i]; 57058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now clean up any chunks here */ 57068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { 57078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&outs->outqueue, sp, next); 5708647dfd814628db0cc7cbfecaf4acb44f997eadb2tuexen sctp_free_spbufspace(stcb, asoc, sp); 57098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->data) { 57108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (so) { 57118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Still an open socket - report */ 57128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb, 571347674b651417d493ff4e0318113fd7beeef119dbtuexen 0, (void *)sp, SCTP_SO_LOCKED); 57148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->data) { 57168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(sp->data); 57178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->data = NULL; 57188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->tail_mbuf = NULL; 5719647dfd814628db0cc7cbfecaf4acb44f997eadb2tuexen sp->length = 0; 57208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sp->net) { 57238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(sp->net); 57248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sp->net = NULL; 57258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 5726647dfd814628db0cc7cbfecaf4acb44f997eadb2tuexen sctp_free_a_strmoq(stcb, sp, SCTP_SO_LOCKED); 57278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 57308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(strrst, &asoc->resetHead, next_resp, nstrrst) { 57318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->resetHead, strrst, next_resp); 57328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(strrst, SCTP_M_STRESET); 57338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(sq, &asoc->pending_reply_queue, next, nsq) { 57358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->pending_reply_queue, sq, next); 57368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sq->data) { 57378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(sq->data); 57388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sq->data = NULL; 57398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(sq->whoFrom); 57418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sq->whoFrom = NULL; 57428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sq->stcb = NULL; 57438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Free the ctl entry */ 57448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), sq); 57458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_READQ_COUNT(); 57468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 57478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->free_chunks, sctp_next, nchk) { 57498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->free_chunks, chk, sctp_next); 57508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 57518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 57528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 57538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->holds_key_ref) 57558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 57568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 57578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_CHK_COUNT(); 57588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_subtract_int(&SCTP_BASE_INFO(ipi_free_chunks), 1); 57598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->free_chunk_cnt--; 57608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 57618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* pending send queue SHOULD be empty */ 57638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { 576460db5740d3bcc26fd4ebc19b6b0652506994fd14t if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 576560db5740d3bcc26fd4ebc19b6b0652506994fd14t asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 576660db5740d3bcc26fd4ebc19b6b0652506994fd14t#ifdef INVARIANTS 576760db5740d3bcc26fd4ebc19b6b0652506994fd14t } else { 576860db5740d3bcc26fd4ebc19b6b0652506994fd14t panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 576960db5740d3bcc26fd4ebc19b6b0652506994fd14t#endif 577060db5740d3bcc26fd4ebc19b6b0652506994fd14t } 57718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); 57728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 57738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (so) { 57748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Still a socket? */ 577547674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 577647674b651417d493ff4e0318113fd7beeef119dbtuexen 0, chk, SCTP_SO_LOCKED); 57778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 57798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 57808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 57818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->holds_key_ref) 57848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 57858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->whoTo) { 57868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(chk->whoTo); 57878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->whoTo = NULL; 57888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 57908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_CHK_COUNT(); 57918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 57928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 57938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sent queue SHOULD be empty */ 57948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { 579560db5740d3bcc26fd4ebc19b6b0652506994fd14t if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { 5796446be8e8a472f6e688885674d2430118fc4be5d7t if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 5797446be8e8a472f6e688885674d2430118fc4be5d7t asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 5798446be8e8a472f6e688885674d2430118fc4be5d7t#ifdef INVARIANTS 5799446be8e8a472f6e688885674d2430118fc4be5d7t } else { 5800446be8e8a472f6e688885674d2430118fc4be5d7t panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 5801446be8e8a472f6e688885674d2430118fc4be5d7t#endif 5802446be8e8a472f6e688885674d2430118fc4be5d7t } 5803446be8e8a472f6e688885674d2430118fc4be5d7t } 58048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); 58058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 58068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (so) { 58078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Still a socket? */ 580847674b651417d493ff4e0318113fd7beeef119dbtuexen sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 580947674b651417d493ff4e0318113fd7beeef119dbtuexen 0, chk, SCTP_SO_LOCKED); 58108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 58128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 58138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 58148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->holds_key_ref) 58178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 58188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(chk->whoTo); 58198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 58208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_CHK_COUNT(); 58218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 58228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 582360db5740d3bcc26fd4ebc19b6b0652506994fd14t#ifdef INVARIANTS 582460db5740d3bcc26fd4ebc19b6b0652506994fd14t for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 582560db5740d3bcc26fd4ebc19b6b0652506994fd14t if (stcb->asoc.strmout[i].chunks_on_queues > 0) { 582660db5740d3bcc26fd4ebc19b6b0652506994fd14t panic("%u chunks left for stream %u.", stcb->asoc.strmout[i].chunks_on_queues, i); 582760db5740d3bcc26fd4ebc19b6b0652506994fd14t } 582860db5740d3bcc26fd4ebc19b6b0652506994fd14t } 582960db5740d3bcc26fd4ebc19b6b0652506994fd14t#endif 58308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* control queue MAY not be empty */ 58318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->control_send_queue, sctp_next, nchk) { 58328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->control_send_queue, chk, sctp_next); 58338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 58348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 58358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 58368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->holds_key_ref) 58388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 58398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(chk->whoTo); 58408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 58418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_CHK_COUNT(); 58428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 58438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ASCONF queue MAY not be empty */ 58458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->asconf_send_queue, sctp_next, nchk) { 58468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->asconf_send_queue, chk, sctp_next); 58478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 58488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 58498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 58508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->holds_key_ref) 58528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 58538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(chk->whoTo); 58548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 58558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_CHK_COUNT(); 58568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 58578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) { 58598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); 58608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 58618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 58628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 58638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->holds_key_ref) 58658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED); 58668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(chk->whoTo); 58678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk); 58688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_CHK_COUNT(); 58698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 58708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 58728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->mapping_array) { 58738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); 58748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->mapping_array = NULL; 58758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->nr_mapping_array) { 58778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP); 58788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->nr_mapping_array = NULL; 58798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* the stream outs */ 58818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->strmout) { 58828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(asoc->strmout, SCTP_M_STRMO); 58838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmout = NULL; 58848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strm_realoutsize = asoc->streamoutcnt = 0; 58868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->strmin) { 58878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *ctl, *nctl; 58888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 58898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < asoc->streamincnt; i++) { 58908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) { 58918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next); 58928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(ctl->whoFrom); 58938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ctl->data) { 58948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(ctl->data); 58958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ctl->data = NULL; 58968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 58978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 58988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We don't free the address here 58998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since all the net's were freed 59008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * above. 59018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 59028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl); 59038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_READQ_COUNT(); 59048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(asoc->strmin, SCTP_M_STRMI); 59078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->strmin = NULL; 59088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->streamincnt = 0; 59108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(net, &asoc->nets, sctp_next, nnet) { 59118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS 59128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_INFO(ipi_count_raddr) == 0) { 59138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen panic("no net's left alloc'ed, or list points to itself"); 59148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 59168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->nets, net, sctp_next); 59178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(net); 59188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(laddr, &asoc->sctp_restricted_addrs, sctp_nxt_addr, naddr) { 59208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 59218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_remove_laddr(laddr); 59228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* pending asconf (address) parameters */ 59258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(aparam, &asoc->asconf_queue, next, naparam) { 59268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 59278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->asconf_queue, aparam, next); 59288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(aparam,SCTP_M_ASC_ADDR); 59298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(aack, &asoc->asconf_ack_sent, next, naack) { 59318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 59328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->asconf_ack_sent, aack, next); 59338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aack->data != NULL) { 59348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(aack->data); 59358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), aack); 59378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clean up auth stuff */ 59398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->local_hmacs) 59408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_hmaclist(asoc->local_hmacs); 59418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peer_hmacs) 59428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_hmaclist(asoc->peer_hmacs); 59438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->local_auth_chunks) 59458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_chunklist(asoc->local_auth_chunks); 59468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->peer_auth_chunks) 59478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_chunklist(asoc->peer_auth_chunks); 59488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_authinfo(&asoc->authinfo); 59508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(shared_key, &asoc->shared_keys, next, nshared_key) { 59528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(shared_key, next); 59538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_sharedkey(shared_key); 59548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore FREED_MEMORY*/ 59558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Insert new items here :> */ 59588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 59598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Get rid of LOCK */ 59606094da0ffddb92b1921fb00169cd740ef64807det SCTP_TCB_UNLOCK(stcb); 59618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK_DESTROY(stcb); 59628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_SEND_LOCK_DESTROY(stcb); 59638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from_inpcbfree == SCTP_NORMAL_PROC) { 59648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_WUNLOCK(); 59658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(inp); 59668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) /* TEMP CODE */ 59688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->freed_from_where = from_location; 59698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 59708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TRACK_FREED_ASOCS 59718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 59728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now clean up the tasoc itself */ 59738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); 59748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_ASOC_COUNT(); 59758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 59768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(&inp->sctp_asoc_free_list, stcb, sctp_tcblist); 59778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 59788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 59798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb); 59808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_ASOC_COUNT(); 59818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 59828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from_inpcbfree == SCTP_NORMAL_PROC) { 59838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 59848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* If its NOT the inp_free calling us AND 59858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_close as been called, we 59868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * call back... 59878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 59888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 59898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This will start the kill timer (if we are 59908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the last one) since we hold an increment yet. But 59918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this is the only safe way to do this 59928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * since otherwise if the socket closes 59938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * at the same time we are here we might 59948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * collide in the cleanup. 59958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 59968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_inpcb_free(inp, 59978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE, 59988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CALLED_DIRECTLY_NOCMPSET); 59998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 60008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto out_of; 60018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 60028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* The socket is still open. */ 60038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_DECR_REF(inp); 60048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (from_inpcbfree == SCTP_NORMAL_PROC) { 60078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 60088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out_of: 60108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* destroyed the asoc */ 60118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING 60128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_log_closing(inp, NULL, 11); 60138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 60148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 60158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 60168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 60178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 60188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 60198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 60208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * determine if a destination is "reachable" based upon the addresses bound 60218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to the current endpoint (e.g. only v4 or v6 currently bound) 60228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 60238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 60248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FIX: if we allow assoc-level bindx(), then this needs to be fixed to use 60258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assoc level v4/v6 flags, as the assoc *may* not have the same address 60268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * types bound as its endpoint 60278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 60288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 60298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_destination_is_reachable(struct sctp_tcb *stcb, struct sockaddr *destaddr) 60308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 60318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 60328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int answer; 60338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 60348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 60358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * No locks here, the TCB, in all cases is already locked and an 60368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assoc is up. There is either a INP lock by the caller applied (in 60378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * asconf case when deleting an address) or NOT in the HB case, 60388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * however if HB then the INP increment is up and the INP will not 60398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * be removed (on top of the fact that we have a TCB lock). So we 60408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * only want to read the sctp_flags, which is either bound-all or 60418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not.. no protection needed since once an assoc is up you can't be 60428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * changing your binding. 60438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 60448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = stcb->sctp_ep; 60458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 60468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* if bound all, destination is not restricted */ 60478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 60488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * RRS: Question during lock work: Is this correct? If you 60498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * are bound-all you still might need to obey the V4--V6 60508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * flags??? IMO this bound-all stuff needs to be removed! 60518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 60528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 60538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* NOTE: all "scope" checks are done when local addresses are added */ 60558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (destaddr->sa_family) { 6056e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET6 60578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 60588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)) 60598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen answer = inp->inp_vflag & INP_IPV6; 60608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 60618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen answer = inp->ip_inp.inp.inp_vflag & INP_IPV6; 60628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 60638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 6064e857b728270b80432f048a8de3c84aa9089dd06btuexen#endif 6065e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET 60668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 60678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)) 60688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen answer = inp->inp_vflag & INP_IPV4; 60698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 60708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen answer = inp->ip_inp.inp.inp_vflag & INP_IPV4; 60718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6072186f71381d5ac588524f9a1401d0c0a9997601e5tuexen break; 6073e857b728270b80432f048a8de3c84aa9089dd06btuexen#endif 607475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__) 607575cd23222c96d5ebe5a9082c57a263f917f1462btuexen case AF_CONN: 607675cd23222c96d5ebe5a9082c57a263f917f1462btuexen answer = inp->ip_inp.inp.inp_vflag & INP_CONN; 60778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 607875cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 60798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 60808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid family, so it's unreachable */ 60818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen answer = 0; 60828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 60838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 60848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (answer); 60858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 60868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 60878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 60888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * update the inp_vflags on an endpoint 60898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 60908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 60918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_update_ep_vflag(struct sctp_inpcb *inp) 60928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 60938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 60948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 60958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* first clear the flag */ 60968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)) 60978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->inp_vflag = 0; 60988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 60998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_vflag = 0; 61008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set the flag based on addresses on the ep list */ 61028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 61038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == NULL) { 61048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", 61058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen __FUNCTION__); 61068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 61078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 61098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) { 61108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 61118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (laddr->ifa->address.sa.sa_family) { 61138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 61148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 61158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)) 61168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->inp_vflag |= INP_IPV6; 61178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 61188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_vflag |= INP_IPV6; 61198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 61218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 61238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 61248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)) 61258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->inp_vflag |= INP_IPV4; 61268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 61278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_vflag |= INP_IPV4; 61288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 61308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 613175cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__) 613275cd23222c96d5ebe5a9082c57a263f917f1462btuexen case AF_CONN: 613375cd23222c96d5ebe5a9082c57a263f917f1462btuexen inp->ip_inp.inp.inp_vflag |= INP_CONN; 613475cd23222c96d5ebe5a9082c57a263f917f1462btuexen break; 613575cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 61368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 61378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 61388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 61418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 61428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 61438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Add the address to the endpoint local address list There is nothing to be 61448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * done if we are bound to all addresses 61458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 61468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 61478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t action) 61488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 61498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 6150b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int fnd, error = 0; 61518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 61528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 0; 61538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 61548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 61558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* You are already bound to all. You have it already */ 61568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 61578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 61598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa->address.sa.sa_family == AF_INET6) { 61608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 61618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't bind a non-useable addr. */ 61628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 61638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* first, is it already present? */ 61678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 61688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == ifa) { 61698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 61708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 61718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 61738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 61748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (fnd == 0) { 61758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Not in the ep list */ 61768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen error = sctp_insert_laddr(&inp->sctp_addr_list, ifa, action); 61778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (error != 0) 61788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 61798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->laddr_count++; 61808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update inp_vflag flags */ 61818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (ifa->address.sa.sa_family) { 61828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 61838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 61848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)) 61858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->inp_vflag |= INP_IPV6; 61868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 61878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_vflag |= INP_IPV6; 61888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 61908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6191e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET 61928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 61938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)) 61948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->inp_vflag |= INP_IPV4; 61958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 61968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->ip_inp.inp.inp_vflag |= INP_IPV4; 61978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 61988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 61998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 620075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__) 620175cd23222c96d5ebe5a9082c57a263f917f1462btuexen case AF_CONN: 620275cd23222c96d5ebe5a9082c57a263f917f1462btuexen inp->ip_inp.inp.inp_vflag |= INP_CONN; 620375cd23222c96d5ebe5a9082c57a263f917f1462btuexen break; 620475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif 62058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 62068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 62078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 62108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 62118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 62128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 62138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 62148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * select a new (hopefully reachable) destination net (should only be used 62158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * when we deleted an ep addr that is the only usable source address to reach 62168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the destination net) 62178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 62188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 62198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_select_primary_destination(struct sctp_tcb *stcb) 62208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 62218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 62228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 62238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 62248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* for now, we'll just pick the first reachable one we find */ 62258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->dest_state & SCTP_ADDR_UNCONFIRMED) 62268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 62278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_destination_is_reachable(stcb, 62288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sockaddr *)&net->ro._l_addr)) { 62298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* found a reachable destination */ 62308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination = net; 62318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* I can't there from here! ...we're gonna die shortly... */ 62348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 62358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 62368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 62378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 62388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Delete the address from the endpoint local address list There is nothing 62398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * to be done if we are bound to all addresses 62408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 62418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 62428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_del_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa) 62438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 62448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 62458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int fnd; 62468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 62478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 0; 62488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 62498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* You are already bound to all. You have it already */ 62508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 62518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 62538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == ifa) { 62548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 62558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 62568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (fnd && (inp->laddr_count < 2)) { 62598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* can't delete unless there are at LEAST 2 addresses */ 62608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 62618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (fnd) { 62638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 62648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * clean up any use of this address go through our 62658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * associations and clear any last_used_address that match 62668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * this one for each assoc, see if a new primary_destination 62678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is needed 62688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 62698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 62708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 62718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clean up "next_addr_touse" */ 62728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inp->next_addr_touse == laddr) 62738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delete this address */ 62748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->next_addr_touse = NULL; 62758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 62768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clean up "last_used_address" */ 62778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 62788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net; 62798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 62808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.last_used_address == laddr) 62818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delete this address */ 62828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.last_used_address = NULL; 62838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now spin through all the nets and purge any ref to laddr */ 62848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 62858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->ro._s_addr && 62868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (net->ro._s_addr->ifa == laddr->ifa)) { 62878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yep, purge src address selected */ 62888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_rtentry_t *rt; 62898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 62908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* delete this address if cached */ 62918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen rt = net->ro.ro_rt; 62928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (rt != NULL) { 62938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen RTFREE(rt); 62948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro.ro_rt = NULL; 62958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 62968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(net->ro._s_addr); 62978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->ro._s_addr = NULL; 62988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->src_addr_selected = 0; 62998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 63028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } /* for each tcb */ 63038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove it from the ep list */ 63048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_remove_laddr(laddr); 63058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp->laddr_count--; 63068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* update inp_vflag flags */ 63078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_update_ep_vflag(inp); 63088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 63108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 63118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 63138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Add the address to the TCB local address restricted list. 63148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This is a "pending" address list (eg. addresses waiting for an 63158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASCONF-ACK response) and cannot be used as a valid source address. 63168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 63178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 63188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_add_local_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa) 63198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 63208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 63218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpladdr *list; 63228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 63248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Assumes TCB is locked.. and possibly the INP. May need to 63258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * confirm/fix that if we need it and is not the case. 63268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 63278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen list = &stcb->asoc.sctp_restricted_addrs; 63288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 63308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa->address.sa.sa_family == AF_INET6) { 63318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) { 63328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Can't bind a non-existent addr. */ 63338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 63348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 63378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* does the address already exist? */ 63388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, list, sctp_nxt_addr) { 63398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == ifa) { 63408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 63418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* add to the list */ 63458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_insert_laddr(list, ifa, 0); 63468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 63478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 63488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 63508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * insert an laddr entry with the given ifa for the desired list 63518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 63528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 63538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_insert_laddr(struct sctpladdr *list, struct sctp_ifa *ifa, uint32_t act) 63548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 63558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 63568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen laddr = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 63588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr == NULL) { 63598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* out of memory? */ 63608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL); 63618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (EINVAL); 63628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 63638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INCR_LADDR_COUNT(); 63648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(laddr, sizeof(*laddr)); 63658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&laddr->start_time); 63668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen laddr->ifa = ifa; 63678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen laddr->action = act; 63688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&ifa->refcount, 1); 63698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* insert it */ 63708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INSERT_HEAD(list, laddr, sctp_nxt_addr); 63718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 63738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 63748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 63768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Remove an laddr entry from the local address list (on an assoc) 63778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 63788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 63798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_remove_laddr(struct sctp_laddr *laddr) 63808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 63818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove from the list */ 63838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(laddr, sctp_nxt_addr); 63848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_ifa(laddr->ifa); 63858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), laddr); 63868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_LADDR_COUNT(); 63878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 63888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 63908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Remove a local address from the TCB local address restricted list 63918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 63928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 63938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_del_local_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa) 63948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 63958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 63968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *laddr; 63978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 63988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 63998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This is called by asconf work. It is assumed that a) The TCB is 64008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * locked and b) The INP is locked. This is true in as much as I can 64018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * trace through the entry asconf code where I did these locks. 64028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Again, the ASCONF code is a bit different in that it does lock 64038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the INP during its work often times. This must be since we don't 64048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * want other proc's looking up things while what they are looking 64058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * up is changing :-D 64068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 64078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = stcb->sctp_ep; 64098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* if subset bound and don't allow ASCONF's, can't delete last */ 64108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) && 64118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) { 64128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_ep->laddr_count < 2) { 64138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* can't delete last address */ 64148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 64158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 64168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 64178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(laddr, &stcb->asoc.sctp_restricted_addrs, sctp_nxt_addr) { 64188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove the address if it exists */ 64198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == NULL) 64208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 64218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (laddr->ifa == ifa) { 64228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_remove_laddr(laddr); 64238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 64248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 64258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 64268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* address not found! */ 64288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 64298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 64308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) 64328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 64338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Temporarily remove for __APPLE__ until we use the Tiger equivalents 64348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 64358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* sysctl */ 64368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int sctp_max_number_of_assoc = SCTP_MAX_NUM_OF_ASOC; 64378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int sctp_scale_up_for_address = SCTP_SCALE_FOR_ADDR; 64388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* FreeBSD || APPLE */ 64398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 6443b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexenstruct sctp_mcore_ctrl *sctp_mcore_workers = NULL; 6444b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexenint *sctp_cpuarry = NULL; 64458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 64468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_queue_to_mcore(struct mbuf *m, int off, int cpu_to_use) 64478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 64488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Queue a packet to a processor for the specified core */ 64498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_mcore_queue *qent; 64508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_mcore_ctrl *wkq; 6451b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int need_wake = 0; 64528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_mcore_workers == NULL) { 64538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Something went way bad during setup */ 64548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_input_with_port(m, off, 0); 64558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 64568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 64578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(qent, struct sctp_mcore_queue *, 64588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sizeof(struct sctp_mcore_queue)), 64598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_MCORE); 64608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (qent == NULL) { 64618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This is trouble */ 64628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_input_with_port(m, off, 0); 64638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 64648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 64658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 64668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen qent->vn = curvnet; 64678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 64688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen qent->m = m; 64698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen qent->off = off; 64708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen qent->v6 = 0; 64718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wkq = &sctp_mcore_workers[cpu_to_use]; 64728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_QLOCK(wkq); 64738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&wkq->que, qent, next); 64758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (wkq->running == 0) { 64768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen need_wake = 1; 64778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 64788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_QUNLOCK(wkq); 6479b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen if (need_wake) { 64808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wakeup(&wkq->running); 64818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 64828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 64838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 64858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_mcore_thread(void *arg) 64868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 64878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_mcore_ctrl *wkq; 64898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_mcore_queue *qent; 64908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wkq = (struct sctp_mcore_ctrl *)arg; 64928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct mbuf *m; 64938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int off, v6; 64948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 64958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Wait for first tickle */ 64968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_LOCK(wkq); 64978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wkq->running = 0; 64988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen msleep(&wkq->running, 64998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &wkq->core_mtx, 65008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, "wait for pkt", 0); 65018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_UNLOCK(wkq); 65028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 65038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Bind to our cpu */ 65048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen thread_lock(curthread); 65058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sched_bind(curthread, wkq->cpuid); 65068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen thread_unlock(curthread); 65078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 65088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now lets start working */ 65098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_LOCK(wkq); 65108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now grab lock and go */ 65110ac02f34d6041cd0018437596a5a9a94685e6919tuexen for (;;) { 65128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_QLOCK(wkq); 65138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen skip_sleep: 65148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wkq->running = 1; 65158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen qent = TAILQ_FIRST(&wkq->que); 65168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (qent) { 65178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&wkq->que, qent, next); 65188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_QUNLOCK(wkq); 65198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 65208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen CURVNET_SET(qent->vn); 65218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 65228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m = qent->m; 65238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen off = qent->off; 65248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen v6 = qent->v6; 65258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(qent, SCTP_M_MCORE); 65268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (v6 == 0) { 65278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_input_with_port(m, off, 0); 65288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 652947a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("V6 not yet supported\n"); 65308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(m); 65318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 65328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 65338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen CURVNET_RESTORE(); 65348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 65358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_QLOCK(wkq); 65368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 65378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen wkq->running = 0; 65388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!TAILQ_EMPTY(&wkq->que)) { 65398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto skip_sleep; 65408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 65418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_QUNLOCK(wkq); 65428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen msleep(&wkq->running, 65438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &wkq->core_mtx, 65448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, "wait for pkt", 0); 6545b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen } 65468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 65478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 65488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 65498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_startup_mcore_threads(void) 65508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 65518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i, cpu; 65528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 65538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (mp_ncpus == 1) 65548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 65558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 65568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_mcore_workers != NULL) { 65578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Already been here in some previous 65588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * vnet? 65598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 65608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 65618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 65628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(sctp_mcore_workers, struct sctp_mcore_ctrl *, 65638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((mp_maxid+1) * sizeof(struct sctp_mcore_ctrl)), 65648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_MCORE); 65658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_mcore_workers == NULL) { 65668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* TSNH I hope */ 65678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 65688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 656932a191a90b5c914a02047389c5b3197e08fc9841tuexen memset(sctp_mcore_workers, 0 , ((mp_maxid+1) * 65708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_mcore_ctrl))); 65718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Init the structures */ 6572b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen for (i = 0; i<=mp_maxid; i++) { 65738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INIT(&sctp_mcore_workers[i].que); 65748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_LOCK_INIT(&sctp_mcore_workers[i]); 65758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_QLOCK_INIT(&sctp_mcore_workers[i]); 65768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_mcore_workers[i].cpuid = i; 65778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 65788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_cpuarry == NULL) { 65798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(sctp_cpuarry, int *, 65808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (mp_ncpus * sizeof(int)), 65818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_MCORE); 6582b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen i = 0; 65838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen CPU_FOREACH(cpu) { 65848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_cpuarry[i] = cpu; 65858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen i++; 65868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 65878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 65888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 65898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now start them all */ 65908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen CPU_FOREACH(cpu) { 65918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version <= 701000 65928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)kthread_create(sctp_mcore_thread, 65938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void *)&sctp_mcore_workers[cpu], 65948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &sctp_mcore_workers[cpu].thread_proc, 65958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen RFPROC, 65968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_KTHREAD_PAGES, 65978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_NAME); 65988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 65998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 66008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)kproc_create(sctp_mcore_thread, 66018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void *)&sctp_mcore_workers[cpu], 66028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &sctp_mcore_workers[cpu].thread_proc, 66038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen RFPROC, 66048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_KTHREAD_PAGES, 66058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MCORE_NAME); 66068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 660732a191a90b5c914a02047389c5b3197e08fc9841tuexen 66088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 66098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 66108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 66111a542d480adbafad25892b0b931819d63eb0fd53t#if defined(__FreeBSD__) && __FreeBSD_cc_version >= 1200000 66128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf * 66138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_netisr_hdlr(struct mbuf *m, uintptr_t source) 66148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 66158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct ip *ip; 66168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctphdr *sh; 66178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int offset; 66188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t flowid, tag; 6619881279179f74ee26ebf175006ca7ffd7bbafd284tuexen 66208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 66218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * No flow id built by lower layers fix it so we 66228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * create one. 66238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 66248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ip = mtod(m, struct ip *); 6625e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen offset = (ip->ip_hl << 2) + sizeof(struct sctphdr); 66268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BUF_LEN(m) < offset) { 6627e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen if ((m = m_pullup(m, offset)) == NULL) { 66288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_hdrops); 66298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (NULL); 66308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 66318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ip = mtod(m, struct ip *); 66328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 66338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2)); 66348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen tag = htonl(sh->v_tag); 66358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port); 66368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->m_pkthdr.flowid = flowid; 66378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen m->m_flags |= M_FLOWID; 66388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (m); 66398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 66408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 66418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 66428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 66438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_pcb_init() 66448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 66458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 66468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SCTP initialization for the PCB structures should be called by 66478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the sctp_init() funciton. 66488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 66498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 66508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct timeval tv; 665181616c6a3e184f46276632dd15aa489cd06d94dftuexen 66528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_VAR(sctp_pcb_initialized) != 0) { 66538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* error I was called twice */ 66548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 66558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 66568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_VAR(sctp_pcb_initialized) = 1; 66578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 66588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_LOCAL_TRACE_BUF) 66598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Windows__) 66608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_log) != NULL) { 66618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(SCTP_BASE_SYSCTL(sctp_log), sizeof(struct sctp_log)); 66628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 66638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 66648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(&SCTP_BASE_SYSCTL(sctp_log), sizeof(struct sctp_log)); 66658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 66668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 66678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) 66688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(SCTP_BASE_STATS, struct sctpstat *, 66698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((mp_maxid+1) * sizeof(struct sctpstat)), 66708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_MCORE); 66718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 66728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_GETTIME_TIMEVAL(&tv); 66738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) 66748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(SCTP_BASE_STATS, (sizeof(struct sctpstat) * (mp_maxid+1))); 66758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_sec = (uint32_t)tv.tv_sec; 66768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_STATS[PCPU_GET(cpuid)].sctps_discontinuitytime.tv_usec = (uint32_t)tv.tv_usec; 66778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 66788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bzero(&SCTP_BASE_STATS, sizeof(struct sctpstat)); 66798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_STAT(sctps_discontinuitytime).tv_sec = (uint32_t)tv.tv_sec; 66808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_STAT(sctps_discontinuitytime).tv_usec = (uint32_t)tv.tv_usec; 66818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 66828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* init the empty list of (All) Endpoints */ 66838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&SCTP_BASE_INFO(listhead)); 66848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 66858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&SCTP_BASE_INFO(inplisthead)); 66867fbcb406549bdf370031d2ad5befb44e39b95ffft#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION) 66877fbcb406549bdf370031d2ad5befb44e39b95ffft SCTP_BASE_INFO(sctbinfo).listhead = &SCTP_BASE_INFO(inplisthead); 66887fbcb406549bdf370031d2ad5befb44e39b95ffft SCTP_BASE_INFO(sctbinfo).mtx_grp_attr = lck_grp_attr_alloc_init(); 66897fbcb406549bdf370031d2ad5befb44e39b95ffft lck_grp_attr_setdefault(SCTP_BASE_INFO(sctbinfo).mtx_grp_attr); 66907fbcb406549bdf370031d2ad5befb44e39b95ffft SCTP_BASE_INFO(sctbinfo).mtx_grp = lck_grp_alloc_init("sctppcb", SCTP_BASE_INFO(sctbinfo).mtx_grp_attr); 66917fbcb406549bdf370031d2ad5befb44e39b95ffft SCTP_BASE_INFO(sctbinfo).mtx_attr = lck_attr_alloc_init(); 66927fbcb406549bdf370031d2ad5befb44e39b95ffft lck_attr_setdefault(SCTP_BASE_INFO(sctbinfo).mtx_attr); 66937fbcb406549bdf370031d2ad5befb44e39b95ffft#else 66947fbcb406549bdf370031d2ad5befb44e39b95ffft SCTP_BASE_INFO(sctbinfo).ipi_listhead = &SCTP_BASE_INFO(inplisthead); 66957fbcb406549bdf370031d2ad5befb44e39b95ffft SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr = lck_grp_attr_alloc_init(); 66967fbcb406549bdf370031d2ad5befb44e39b95ffft lck_grp_attr_setdefault(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr); 66977fbcb406549bdf370031d2ad5befb44e39b95ffft SCTP_BASE_INFO(sctbinfo).ipi_lock_grp = lck_grp_alloc_init("sctppcb", SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr); 66987fbcb406549bdf370031d2ad5befb44e39b95ffft SCTP_BASE_INFO(sctbinfo).ipi_lock_attr = lck_attr_alloc_init(); 66997fbcb406549bdf370031d2ad5befb44e39b95ffft lck_attr_setdefault(SCTP_BASE_INFO(sctbinfo).ipi_lock_attr); 67007fbcb406549bdf370031d2ad5befb44e39b95ffft#endif 67017fbcb406549bdf370031d2ad5befb44e39b95ffft#if !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) 67027fbcb406549bdf370031d2ad5befb44e39b95ffft SCTP_BASE_INFO(sctbinfo).ipi_gc = sctp_gc; 67037fbcb406549bdf370031d2ad5befb44e39b95ffft in_pcbinfo_attach(&SCTP_BASE_INFO(sctbinfo)); 67047fbcb406549bdf370031d2ad5befb44e39b95ffft#endif 67058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 67068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* init the hash table of endpoints */ 67098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) 67108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD_cc_version) && __FreeBSD_cc_version >= 440000 67118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TUNABLE_INT_FETCH("net.inet.sctp.tcbhashsize", &SCTP_BASE_SYSCTL(sctp_hashtblsize)); 67128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TUNABLE_INT_FETCH("net.inet.sctp.pcbhashsize", &SCTP_BASE_SYSCTL(sctp_pcbtblsize)); 67138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TUNABLE_INT_FETCH("net.inet.sctp.chunkscale", &SCTP_BASE_SYSCTL(sctp_chunkscale)); 67148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 67158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TUNABLE_INT_FETCH("net.inet.sctp.tcbhashsize", SCTP_TCBHASHSIZE, 67168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_SYSCTL(sctp_hashtblsize)); 67178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TUNABLE_INT_FETCH("net.inet.sctp.pcbhashsize", SCTP_PCBHASHSIZE, 67188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_SYSCTL(sctp_pcbtblsize)); 67198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TUNABLE_INT_FETCH("net.inet.sctp.chunkscale", SCTP_CHUNKQUEUE_SCALE, 67208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_SYSCTL(sctp_chunkscale)); 67218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 67228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 67238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(sctp_asochash) = SCTP_HASH_INIT((SCTP_BASE_SYSCTL(sctp_hashtblsize) * 31), 67248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &SCTP_BASE_INFO(hashasocmark)); 67258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(sctp_ephash) = SCTP_HASH_INIT(SCTP_BASE_SYSCTL(sctp_hashtblsize), 67268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &SCTP_BASE_INFO(hashmark)); 67278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(sctp_tcpephash) = SCTP_HASH_INIT(SCTP_BASE_SYSCTL(sctp_hashtblsize), 67288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &SCTP_BASE_INFO(hashtcpmark)); 67298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(hashtblsize) = SCTP_BASE_SYSCTL(sctp_hashtblsize); 67308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(sctp_vrfhash) = SCTP_HASH_INIT(SCTP_SIZE_OF_VRF_HASH, 67338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &SCTP_BASE_INFO(hashvrfmark)); 67348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(vrf_ifn_hash) = SCTP_HASH_INIT(SCTP_VRF_IFN_HASH_SIZE, 67368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen &SCTP_BASE_INFO(vrf_ifn_hashmark)); 67378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* init the zones */ 67388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 67398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FIX ME: Should check for NULL returns, but if it does fail we are 67408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * doomed to panic anyways... add later maybe. 67418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 67428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_ep), "sctp_ep", 67438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_inpcb), maxsockets); 67448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_asoc), "sctp_asoc", 67468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_tcb), sctp_max_number_of_assoc); 67478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_laddr), "sctp_laddr", 67498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_laddr), 67508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_max_number_of_assoc * sctp_scale_up_for_address)); 67518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_net), "sctp_raddr", 67538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_nets), 67548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_max_number_of_assoc * sctp_scale_up_for_address)); 67558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_chunk), "sctp_chunk", 67578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_tmit_chunk), 67588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); 67598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_readq), "sctp_readq", 67618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_queued_to_read), 67628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); 67638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_strmoq), "sctp_stream_msg_out", 67658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_stream_queue_pending), 67668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); 67678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_asconf), "sctp_asconf", 67698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_asconf), 67708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); 67718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_INIT(SCTP_BASE_INFO(ipi_zone_asconf_ack), "sctp_asconf_ack", 67738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_asconf_ack), 67748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sctp_max_number_of_assoc * SCTP_BASE_SYSCTL(sctp_chunkscale))); 67758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67760ac02f34d6041cd0018437596a5a9a94685e6919tuexen 67778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Master Lock INIT for info structure */ 67788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_LOCK_INIT(); 67798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STATLOG_INIT_LOCK(); 67808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_COUNT_INIT(); 67828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_INIT(); 67838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_PACKET_LOGGING 67848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IP_PKTLOG_INIT(); 67858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 67868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&SCTP_BASE_INFO(addr_wq)); 67878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 67888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_WQ_ADDR_INIT(); 67898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* not sure if we need all the counts */ 67908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(ipi_count_ep) = 0; 67918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* assoc/tcb zone info */ 67928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(ipi_count_asoc) = 0; 67938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* local addrlist zone info */ 67948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(ipi_count_laddr) = 0; 67958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remote addrlist zone info */ 67968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(ipi_count_raddr) = 0; 67978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* chunk info */ 67988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(ipi_count_chunk) = 0; 67998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 68008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* socket queue zone info */ 68018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(ipi_count_readq) = 0; 68028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 68038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* stream out queue cont */ 68048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(ipi_count_strmoq) = 0; 68058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 68068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(ipi_free_strmoq) = 0; 68078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(ipi_free_chunks) = 0; 68088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 68098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_INIT(&SCTP_BASE_INFO(addr_wq_timer.timer)); 68108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 68118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Init the TIMEWAIT list */ 68128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) { 68138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_INIT(&SCTP_BASE_INFO(vtag_timewait)[i]); 68148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 68158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_PROCESS_LEVEL_LOCKS) 68161a0a058c2e170a7749bd410bdeff477bbd75a615tuexen#if defined(__Userspace_os_Windows) 681781616c6a3e184f46276632dd15aa489cd06d94dftuexen InitializeConditionVariable(&sctp_it_ctl.iterator_wakeup); 681881616c6a3e184f46276632dd15aa489cd06d94dftuexen#else 68198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)pthread_cond_init(&sctp_it_ctl.iterator_wakeup, NULL); 68208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 682181616c6a3e184f46276632dd15aa489cd06d94dftuexen#endif 68228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_startup_iterator(); 68238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 68248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 68258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_startup_mcore_threads(); 68268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 68278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 68288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __Panda__ 68298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 68308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INIT the default VRF which for BSD is the only one, other O/S's 68318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * may have more. But initially they must start with one and then 68328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * add the VRF's as addresses are added. 68338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 68348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_init_vrf_list(SCTP_DEFAULT_VRF); 68358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 68361a542d480adbafad25892b0b931819d63eb0fd53t#if defined(__FreeBSD__) && __FreeBSD_cc_version >= 1200000 68378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ip_register_flow_handler(sctp_netisr_hdlr, IPPROTO_SCTP)) { 683847a306d634abf33223ef347472c4b1cd441d139ftuexen SCTP_PRINTF("***SCTP- Error can't register netisr handler***\n"); 68398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 68408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 68418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(_SCTP_NEEDS_CALLOUT_) || defined(_USER_SCTP_NEEDS_CALLOUT_) 68428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* allocate the lock for the callout/timer queue */ 68438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TIMERQ_LOCK_INIT(); 68448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INIT(&SCTP_BASE_INFO(callqueue)); 68458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 68468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__) 68478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen mbuf_init(NULL); 68488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_init(); 6849c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen#if defined(INET) || defined(INET6) 6850a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen recv_thread_init(); 68518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6852c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen#endif 68538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 68548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 68558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 68568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Assumes that the SCTP_BASE_INFO() lock is NOT held. 68578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 68588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 68598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_pcb_finish(void) 68608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 68618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrflist *vrf_bucket; 68628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_vrf *vrf, *nvrf; 68638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifn *ifn, *nifn; 68648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ifa *ifa, *nifa; 68658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpvtaghead *chain; 68668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tagblock *twait_block, *prev_twait_block; 68678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_laddr *wi, *nwi; 68688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 686930655d7d93468251c11cffdb6f6addf77a6d8feet struct sctp_iterator *it, *nit; 687030655d7d93468251c11cffdb6f6addf77a6d8feet 6871de91ed386d1b5f46ff1b86f855ccc811c2837d96t#if !defined(__FreeBSD__) 68728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Notify the iterator to exit. */ 68738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ITERATOR_WQ_LOCK(); 68748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_MUST_EXIT; 68758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_wakeup_iterator(); 68768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ITERATOR_WQ_UNLOCK(); 68778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 68788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 68797fbcb406549bdf370031d2ad5befb44e39b95ffft#if !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) 68807fbcb406549bdf370031d2ad5befb44e39b95ffft in_pcbinfo_detach(&SCTP_BASE_INFO(sctbinfo)); 68817fbcb406549bdf370031d2ad5befb44e39b95ffft#endif 68828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ITERATOR_WQ_LOCK(); 68838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen do { 68848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen msleep(&sctp_it_ctl.iterator_flags, 68858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_it_ctl.ipi_iterator_wq_mtx, 68868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 0, "waiting_for_work", 0); 68878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } while ((sctp_it_ctl.iterator_flags & SCTP_ITERATOR_EXITED) == 0); 68888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen thread_deallocate(sctp_it_ctl.thread_proc); 68898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ITERATOR_WQ_UNLOCK(); 68908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 68918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Windows__) 68928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_it_ctl.iterator_thread_obj != NULL) { 68938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen NTSTATUS status = STATUS_SUCCESS; 68948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 68958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen KeSetEvent(&sctp_it_ctl.iterator_wakeup[1], IO_NO_INCREMENT, FALSE); 68968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen status = KeWaitForSingleObject(sctp_it_ctl.iterator_thread_obj, 68978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen Executive, 68988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen KernelMode, 68998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen FALSE, 69008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen NULL); 69018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ObDereferenceObject(sctp_it_ctl.iterator_thread_obj); 69028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 69038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 69044a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t#if defined(__Userspace__) 69054a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t if (sctp_it_ctl.thread_proc) { 69064a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t#if defined(__Userspace_os_Windows) 69074a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t WaitForSingleObject(sctp_it_ctl.thread_proc, INFINITE); 69084a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t CloseHandle(sctp_it_ctl.thread_proc); 69094a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t sctp_it_ctl.thread_proc = NULL; 69104a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t#else 69114a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t pthread_join(sctp_it_ctl.thread_proc, NULL); 69124a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t sctp_it_ctl.thread_proc = 0; 69134a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t#endif 69144a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t } 69154a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t#endif 69164a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t#if defined(SCTP_PROCESS_LEVEL_LOCKS) 69174a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t#if defined(__Userspace_os_Windows) 69184a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t DeleteConditionVariable(&sctp_it_ctl.iterator_wakeup); 69194a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t#else 69204a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t pthread_cond_destroy(&sctp_it_ctl.iterator_wakeup); 69214a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t#endif 69224a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t#endif 6923de91ed386d1b5f46ff1b86f855ccc811c2837d96t /* In FreeBSD the iterator thread never exits 6924de91ed386d1b5f46ff1b86f855ccc811c2837d96t * but we do clean up. 6925de91ed386d1b5f46ff1b86f855ccc811c2837d96t * The only way FreeBSD reaches here is if we have VRF's 6926de91ed386d1b5f46ff1b86f855ccc811c2837d96t * but we still add the ifdef to make it compile on old versions. 6927de91ed386d1b5f46ff1b86f855ccc811c2837d96t */ 6928de91ed386d1b5f46ff1b86f855ccc811c2837d96t SCTP_IPI_ITERATOR_WQ_LOCK(); 6929de91ed386d1b5f46ff1b86f855ccc811c2837d96t TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { 6930cf25b08c148539eb2beed86aa77a654af3d6c753t#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 6931de91ed386d1b5f46ff1b86f855ccc811c2837d96t if (it->vn != curvnet) { 6932de91ed386d1b5f46ff1b86f855ccc811c2837d96t continue; 6933de91ed386d1b5f46ff1b86f855ccc811c2837d96t } 6934de91ed386d1b5f46ff1b86f855ccc811c2837d96t#endif 6935de91ed386d1b5f46ff1b86f855ccc811c2837d96t TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); 6936de91ed386d1b5f46ff1b86f855ccc811c2837d96t if (it->function_atend != NULL) { 6937de91ed386d1b5f46ff1b86f855ccc811c2837d96t (*it->function_atend) (it->pointer, it->val); 6938de91ed386d1b5f46ff1b86f855ccc811c2837d96t } 6939de91ed386d1b5f46ff1b86f855ccc811c2837d96t SCTP_FREE(it,SCTP_M_ITER); 6940de91ed386d1b5f46ff1b86f855ccc811c2837d96t } 6941de91ed386d1b5f46ff1b86f855ccc811c2837d96t SCTP_IPI_ITERATOR_WQ_UNLOCK(); 6942cf25b08c148539eb2beed86aa77a654af3d6c753t#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 6943de91ed386d1b5f46ff1b86f855ccc811c2837d96t SCTP_ITERATOR_LOCK(); 6944de91ed386d1b5f46ff1b86f855ccc811c2837d96t if ((sctp_it_ctl.cur_it) && 6945de91ed386d1b5f46ff1b86f855ccc811c2837d96t (sctp_it_ctl.cur_it->vn == curvnet)) { 6946de91ed386d1b5f46ff1b86f855ccc811c2837d96t sctp_it_ctl.iterator_flags |= SCTP_ITERATOR_STOP_CUR_IT; 6947de91ed386d1b5f46ff1b86f855ccc811c2837d96t } 6948de91ed386d1b5f46ff1b86f855ccc811c2837d96t SCTP_ITERATOR_UNLOCK(); 6949de91ed386d1b5f46ff1b86f855ccc811c2837d96t#endif 695030655d7d93468251c11cffdb6f6addf77a6d8feet#if !defined(__FreeBSD__) 69514a19fdc8f3cb21a4e6598e609563c6cfcd6906b4t SCTP_IPI_ITERATOR_WQ_DESTROY(); 6952e2828360ea9cf8951730d46f5c14626c9425cb30t SCTP_ITERATOR_LOCK_DESTROY(); 695330655d7d93468251c11cffdb6f6addf77a6d8feet#endif 69548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_OS_TIMER_STOP(&SCTP_BASE_INFO(addr_wq_timer.timer)); 69558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_WQ_ADDR_LOCK(); 69568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) { 69578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(wi, sctp_nxt_addr); 69588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_LADDR_COUNT(); 695980e1c8a8de188f825a15f950e46a2dd65d406e06t if (wi->action == SCTP_DEL_IP_ADDRESS) { 696080e1c8a8de188f825a15f950e46a2dd65d406e06t SCTP_FREE(wi->ifa, SCTP_M_IFA); 696180e1c8a8de188f825a15f950e46a2dd65d406e06t } 69628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), wi); 69638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 69648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_WQ_ADDR_UNLOCK(); 696532a191a90b5c914a02047389c5b3197e08fc9841tuexen 69668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 69678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * free the vrf/ifn/ifa lists and hashes (be sure address monitor 69688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is destroyed first). 69698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 69708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen vrf_bucket = &SCTP_BASE_INFO(sctp_vrfhash)[(SCTP_DEFAULT_VRFID & SCTP_BASE_INFO(hashvrfmark))]; 69718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(vrf, vrf_bucket, next_vrf, nvrf) { 69728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(ifn, &vrf->ifnlist, next_ifn, nifn) { 69738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH_SAFE(ifa, &ifn->ifalist, next_ifa, nifa) { 69748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the ifa */ 69758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(ifa, next_bucket); 69768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(ifa, next_ifa); 69778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(ifa, SCTP_M_IFA); 69788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 69798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the ifn */ 69808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(ifn, next_bucket); 69818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(ifn, next_ifn); 69828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(ifn, SCTP_M_IFN); 69838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 69848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(vrf->vrf_addr_hash, vrf->vrf_addr_hashmark); 69858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the vrf */ 69868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_REMOVE(vrf, next_vrf); 69878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(vrf, SCTP_M_VRF); 69888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 69898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the vrf hashes */ 69908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_vrfhash), SCTP_BASE_INFO(hashvrfmark)); 69918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(SCTP_BASE_INFO(vrf_ifn_hash), SCTP_BASE_INFO(vrf_ifn_hashmark)); 69920ac02f34d6041cd0018437596a5a9a94685e6919tuexen#if defined(__Userspace__) && !defined(__Userspace_os_Windows) 69938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free memory allocated by getifaddrs call */ 6994fcc753d4316c720a771fc1147a9b2bc6340a0469t#if defined(INET) || defined(INET6) 69958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen freeifaddrs(g_interfaces); 69968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 6997fcc753d4316c720a771fc1147a9b2bc6340a0469t#endif 69988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 69998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the TIMEWAIT list elements malloc'd in the function 70008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_add_vtag_to_timewait()... 70018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 70028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < SCTP_STACK_VTAG_HASH_SIZE; i++) { 70038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chain = &SCTP_BASE_INFO(vtag_timewait)[i]; 70048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!LIST_EMPTY(chain)) { 70058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev_twait_block = NULL; 70068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { 70078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (prev_twait_block) { 70088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(prev_twait_block, SCTP_M_TIMW); 70098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 70108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen prev_twait_block = twait_block; 70118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 70128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_FREE(prev_twait_block, SCTP_M_TIMW); 70138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 70148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 70158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 70168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* free the locks and mutexes */ 70178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 70188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TIMERQ_LOCK_DESTROY(); 70198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 70208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_PACKET_LOGGING 70218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IP_PKTLOG_DESTROY(); 70228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 70238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ADDR_DESTROY(); 70248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 70258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_COUNT_DESTROY(); 70268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 70278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STATLOG_DESTROY(); 70288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_LOCK_DESTROY(); 702932a191a90b5c914a02047389c5b3197e08fc9841tuexen 70308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_WQ_ADDR_DESTROY(); 703132a191a90b5c914a02047389c5b3197e08fc9841tuexen 70328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__) 70337fbcb406549bdf370031d2ad5befb44e39b95ffft#if defined(APPLE_LEOPARD) || defined(APPLE_SNOWLEOPARD) || defined(APPLE_LION) || defined(APPLE_MOUNTAINLION) 70347fbcb406549bdf370031d2ad5befb44e39b95ffft lck_grp_attr_free(SCTP_BASE_INFO(sctbinfo).mtx_grp_attr); 70357fbcb406549bdf370031d2ad5befb44e39b95ffft lck_grp_free(SCTP_BASE_INFO(sctbinfo).mtx_grp); 70367fbcb406549bdf370031d2ad5befb44e39b95ffft lck_attr_free(SCTP_BASE_INFO(sctbinfo).mtx_attr); 70377fbcb406549bdf370031d2ad5befb44e39b95ffft#else 70387fbcb406549bdf370031d2ad5befb44e39b95ffft lck_grp_attr_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp_attr); 70397fbcb406549bdf370031d2ad5befb44e39b95ffft lck_grp_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_grp); 70407fbcb406549bdf370031d2ad5befb44e39b95ffft lck_attr_free(SCTP_BASE_INFO(sctbinfo).ipi_lock_attr); 70417fbcb406549bdf370031d2ad5befb44e39b95ffft#endif 70428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 70438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__) 70448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TIMERQ_LOCK_DESTROY(); 70458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(zone_mbuf); 70468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(zone_clust); 70478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(zone_ext_refcnt); 70488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 70498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Windows__) || defined(__FreeBSD__) || defined(__Userspace__) 70508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_ep)); 70518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_asoc)); 70528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_laddr)); 70538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_net)); 70548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_chunk)); 70558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_readq)); 70568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_strmoq)); 70578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_asconf)); 70588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_DESTROY(SCTP_BASE_INFO(ipi_zone_asconf_ack)); 70598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 70608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Get rid of other stuff to */ 70618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_INFO(sctp_asochash) != NULL) 70628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_asochash), SCTP_BASE_INFO(hashasocmark)); 70638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_INFO(sctp_ephash) != NULL) 70648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_ephash), SCTP_BASE_INFO(hashmark)); 70658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_INFO(sctp_tcpephash) != NULL) 70668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_HASH_FREE(SCTP_BASE_INFO(sctp_tcpephash), SCTP_BASE_INFO(hashtcpmark)); 70678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT) 706832a191a90b5c914a02047389c5b3197e08fc9841tuexen SCTP_FREE(SCTP_BASE_STATS, SCTP_M_MCORE); 70698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 70708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 70718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 70728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 70738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 70748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m, 7075e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen int offset, int limit, 7076e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen struct sockaddr *src, struct sockaddr *dst, 70770ac02f34d6041cd0018437596a5a9a94685e6919tuexen struct sockaddr *altsa) 70788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 70798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 70808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * grub through the INIT pulling addresses and loading them to the 70818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * nets structure in the asoc. The from address in the mbuf should 70828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * also be loaded (if it is not already). This routine can be called 70838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * with either INIT or INIT-ACK's as long as the m points to the IP 70848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * packet and the offset points to the beginning of the parameters. 70858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 7086b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen struct sctp_inpcb *inp; 70878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net, *nnet, *net_tmp; 70888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_paramhdr *phdr, parm_buf; 70898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb_tmp; 70908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t ptype, plen; 70918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *sa; 70928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t random_store[SCTP_PARAM_BUFFER_SIZE]; 70938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_auth_random *p_random = NULL; 70948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t random_len = 0; 70958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t hmacs_store[SCTP_PARAM_BUFFER_SIZE]; 70968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_auth_hmac_algo *hmacs = NULL; 70978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t hmacs_len = 0; 7098b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen uint8_t saw_asconf = 0; 7099b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen uint8_t saw_asconf_ack = 0; 71008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t chunks_store[SCTP_PARAM_BUFFER_SIZE]; 71018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_auth_chunk_list *chunks = NULL; 71028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint16_t num_chunks = 0; 71038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_key_t *new_key; 71048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t keylen; 71058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int got_random = 0, got_hmacs = 0, got_chklist = 0; 7106fb3816eaffe5878bb1286adb120fd160da178a05t uint8_t peer_supports_ecn; 7107fb3816eaffe5878bb1286adb120fd160da178a05t uint8_t peer_supports_prsctp; 7108fb3816eaffe5878bb1286adb120fd160da178a05t uint8_t peer_supports_auth; 7109fb3816eaffe5878bb1286adb120fd160da178a05t uint8_t peer_supports_asconf; 7110fb3816eaffe5878bb1286adb120fd160da178a05t uint8_t peer_supports_asconf_ack; 7111fb3816eaffe5878bb1286adb120fd160da178a05t uint8_t peer_supports_reconfig; 7112fb3816eaffe5878bb1286adb120fd160da178a05t uint8_t peer_supports_nrsack; 7113fb3816eaffe5878bb1286adb120fd160da178a05t uint8_t peer_supports_pktdrop; 71148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 71158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in sin; 71168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 71178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 71188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr_in6 sin6; 71198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 71208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 71218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* First get the destination address setup too. */ 71228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 71238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&sin, 0, sizeof(sin)); 71248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin.sin_family = AF_INET; 71257b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN 71268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin.sin_len = sizeof(sin); 71278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 71288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin.sin_port = stcb->rport; 71298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 71308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 71318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(&sin6, 0, sizeof(sin6)); 71328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6.sin6_family = AF_INET6; 71337b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN 71348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6.sin6_len = sizeof(struct sockaddr_in6); 71358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 71368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin6.sin6_port = stcb->rport; 71378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 7138e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen if (altsa) { 7139e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sa = altsa; 7140e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen } else { 7141e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen sa = src; 71428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7143fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_ecn = 0; 7144fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_prsctp = 0; 7145fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_auth = 0; 7146fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_asconf = 0; 7147fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_reconfig = 0; 7148fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_nrsack = 0; 7149fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_pktdrop = 0; 71508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 71518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* mark all addresses that we have currently on the list */ 71528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state |= SCTP_ADDR_NOT_IN_ASSOC; 71538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 71548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* does the source address already exist? if so skip it */ 7155b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen inp = stcb->sctp_ep; 71568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 7157e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net_tmp, dst, stcb); 71588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, -1); 71598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 71608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb_tmp == NULL && inp == stcb->sctp_ep) || inp == NULL) { 71618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we must add the source address */ 71628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* no scope set here since we have a tcb already. */ 71638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (sa->sa_family) { 71648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 71658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET: 71667988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.ipv4_addr_legal) { 71678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) { 71688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 71698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 71708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 71718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 71728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 71738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 71748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case AF_INET6: 71757988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.ipv6_addr_legal) { 71768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) { 71778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-2); 71788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 71798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 71808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 71818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 718288f9b8b5aa8f1114e04706be5caca037f21f1ae8tuexen#if defined(__Userspace__) 718388f9b8b5aa8f1114e04706be5caca037f21f1ae8tuexen case AF_CONN: 71847988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.conn_addr_legal) { 71857988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) { 71867988ea8f0c067cf3757e798b473b1ae4d34b6dfdt return (-2); 71877988ea8f0c067cf3757e798b473b1ae4d34b6dfdt } 718888f9b8b5aa8f1114e04706be5caca037f21f1ae8tuexen } 718988f9b8b5aa8f1114e04706be5caca037f21f1ae8tuexen break; 719088f9b8b5aa8f1114e04706be5caca037f21f1ae8tuexen#endif 71918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 71928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 71938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 71948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 71958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net_tmp != NULL && stcb_tmp == stcb) { 71968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net_tmp->dest_state &= ~SCTP_ADDR_NOT_IN_ASSOC; 71978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (stcb_tmp != stcb) { 71988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* It belongs to another association? */ 71998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb_tmp) 72008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb_tmp); 72018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-3); 72028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state == 0) { 72058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* the assoc was freed? */ 72068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-4); 72078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* now we must go through each of the params. */ 72098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, &parm_buf, sizeof(parm_buf)); 72108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen while (phdr) { 72118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ptype = ntohs(phdr->param_type); 72128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen plen = ntohs(phdr->param_length); 72138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 721447a306d634abf33223ef347472c4b1cd441d139ftuexen * SCTP_PRINTF("ptype => %0x, plen => %d\n", (uint32_t)ptype, 72158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (int)plen); 72168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 72178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (offset + plen > limit) { 72188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 72198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen == 0) { 72218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 72228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 72248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ptype == SCTP_IPV4_ADDRESS) { 72257988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.ipv4_addr_legal) { 72268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv4addr_param *p4, p4_buf; 72278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 72288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ok get the v4 address and check/add */ 72298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, 72308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_paramhdr *)&p4_buf, 72318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(p4_buf)); 72328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen != sizeof(struct sctp_ipv4addr_param) || 72338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr == NULL) { 72348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-5); 72358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p4 = (struct sctp_ipv4addr_param *)phdr; 72378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin.sin_addr.s_addr = p4->addr; 72388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) { 72398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Skip multi-cast addresses */ 72408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_param; 72418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((sin.sin_addr.s_addr == INADDR_BROADCAST) || 72438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (sin.sin_addr.s_addr == INADDR_ANY)) { 72448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_param; 72458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sa = (struct sockaddr *)&sin; 72478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = stcb->sctp_ep; 72488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 72498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net, 7250e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen dst, stcb); 72518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, -1); 72528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 72538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((stcb_tmp == NULL && inp == stcb->sctp_ep) || 72548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp == NULL) { 72558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* we must add the source address */ 72568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 72578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * no scope set since we have a tcb 72588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * already 72598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 72608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 72618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 72628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we must validate the state again 72638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * here 72648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 72658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen add_it_now: 72668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state == 0) { 72678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* the assoc was freed? */ 72688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-7); 72698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_4)) { 72718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-8); 72728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (stcb_tmp == stcb) { 72748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state == 0) { 72758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* the assoc was freed? */ 72768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-10); 72778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net != NULL) { 72798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clear flag */ 72808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state &= 72818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ~SCTP_ADDR_NOT_IN_ASSOC; 72828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 72848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 72858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * strange, address is in another 72868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assoc? straighten out locks. 72878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 72888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb_tmp) { 72898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) { 72908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* in setup state we abort this guy */ 72918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_abort_an_association(stcb_tmp->sctp_ep, 729247674b651417d493ff4e0318113fd7beeef119dbtuexen stcb_tmp, NULL, SCTP_SO_NOT_LOCKED); 72938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto add_it_now; 72948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb_tmp); 72968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 72978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 72988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state == 0) { 72998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* the assoc was freed? */ 73008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-12); 73018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-13); 73038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else 73068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 73078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 73088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ptype == SCTP_IPV6_ADDRESS) { 73097988ea8f0c067cf3757e798b473b1ae4d34b6dfdt if (stcb->asoc.scope.ipv6_addr_legal) { 73108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* ok get the v6 address and check/add */ 73118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_ipv6addr_param *p6, p6_buf; 73128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 73138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, 73148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_paramhdr *)&p6_buf, 73158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(p6_buf)); 73168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen != sizeof(struct sctp_ipv6addr_param) || 73178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr == NULL) { 73188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-14); 73198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p6 = (struct sctp_ipv6addr_param *)phdr; 73218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy((caddr_t)&sin6.sin6_addr, p6->addr, 73228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(p6->addr)); 73238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_MULTICAST(&sin6.sin6_addr)) { 73248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Skip multi-cast addresses */ 73258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_param; 73268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)) { 73288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Link local make no sense without scope */ 73298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_param; 73308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sa = (struct sockaddr *)&sin6; 73328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp = stcb->sctp_ep; 73338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, 1); 73348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net, 7335e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen dst, stcb); 73368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen atomic_add_int(&stcb->asoc.refcnt, -1); 73378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb_tmp == NULL && 73388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (inp == stcb->sctp_ep || inp == NULL)) { 73398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 73408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we must validate the state again 73418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * here 73428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 73438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen add_it_now6: 73448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state == 0) { 73458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* the assoc was freed? */ 73468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-16); 73478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 73498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we must add the address, no scope 73508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * set 73518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 73528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_5)) { 73538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-17); 73548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (stcb_tmp == stcb) { 73568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 73578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * we must validate the state again 73588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * here 73598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 73608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state == 0) { 73618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* the assoc was freed? */ 73628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-19); 73638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net != NULL) { 73658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* clear flag */ 73668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state &= 73678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ~SCTP_ADDR_NOT_IN_ASSOC; 73688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 73708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 73718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * strange, address is in another 73728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assoc? straighten out locks. 73738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 73748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb_tmp) 73758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) { 73768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* in setup state we abort this guy */ 73778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_abort_an_association(stcb_tmp->sctp_ep, 737847674b651417d493ff4e0318113fd7beeef119dbtuexen stcb_tmp, NULL, SCTP_SO_NOT_LOCKED); 73798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto add_it_now6; 73808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb_tmp); 73828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 73838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state == 0) { 73848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* the assoc was freed? */ 73858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-21); 73868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-22); 73888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 73908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else 73918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 73928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ptype == SCTP_ECN_CAPABLE) { 7393fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_ecn = 1; 73948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_ULP_ADAPTATION) { 73958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.state != SCTP_STATE_OPEN) { 73968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_adaptation_layer_indication ai, *aip; 73978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 73988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, 73998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_paramhdr *)&ai, sizeof(ai)); 74008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen aip = (struct sctp_adaptation_layer_indication *)phdr; 74018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (aip) { 74028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peers_adaptation = ntohl(aip->indication); 74038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.adaptation_needed = 1; 74048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 74058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 74068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_SET_PRIM_ADDR) { 74078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addr_param lstore, *fee; 74088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int lptype; 74098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sockaddr *lsa = NULL; 74108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 74118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_asconf_addrv4_param *fii; 74128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 74138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 7414fb3816eaffe5878bb1286adb120fd160da178a05t if (stcb->asoc.asconf_supported == 0) { 7415fb3816eaffe5878bb1286adb120fd160da178a05t return (-100); 7416fb3816eaffe5878bb1286adb120fd160da178a05t } 74178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen > sizeof(lstore)) { 74188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-23); 74198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 74208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, 74218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_paramhdr *)&lstore, 74228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min(plen,sizeof(lstore))); 74238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (phdr == NULL) { 74248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-24); 74258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 74268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fee = (struct sctp_asconf_addr_param *)phdr; 74278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lptype = ntohs(fee->addrp.ph.param_type); 74288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (lptype) { 74298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET 74308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV4_ADDRESS: 74318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen != 74328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_asconf_addrv4_param)) { 74338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Sizeof setprim in init/init ack not %d but %d - ignored\n", 74348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (int)sizeof(struct sctp_asconf_addrv4_param), 74358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen plen); 74368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 74378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fii = (struct sctp_asconf_addrv4_param *)fee; 74388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sin.sin_addr.s_addr = fii->addrp.addr; 74398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lsa = (struct sockaddr *)&sin; 74408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 74418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 74428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 74438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6 74448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_IPV6_ADDRESS: 74458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen != 74468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(struct sctp_asconf_addr_param)) { 74478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_PRINTF("Sizeof setprim (v6) in init/init ack not %d but %d - ignored\n", 74488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (int)sizeof(struct sctp_asconf_addr_param), 74498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen plen); 74508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 74518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memcpy(sin6.sin6_addr.s6_addr, 74528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fee->addrp.addr, 74538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(fee->addrp.addr)); 74548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen lsa = (struct sockaddr *)&sin6; 74558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 74568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 74578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 74588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 74598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 74608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 74618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (lsa) { 74628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_set_primary_addr(stcb, sa, NULL); 74638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 74648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_HAS_NAT_SUPPORT) { 74658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peer_supports_nat = 1; 74668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_PRSCTP_SUPPORTED) { 74678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Peer supports pr-sctp */ 7468fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_prsctp = 1; 74698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_SUPPORTED_CHUNK_EXT) { 74708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* A supported extension chunk */ 74718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_supported_chunk_types_param *pr_supported; 74728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t local_store[SCTP_PARAM_BUFFER_SIZE]; 74738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int num_ent, i; 74748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 74758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, 74768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_paramhdr *)&local_store, min(sizeof(local_store),plen)); 74778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (phdr == NULL) { 74788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-25); 74798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 74808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen pr_supported = (struct sctp_supported_chunk_types_param *)phdr; 74818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_ent = plen - sizeof(struct sctp_paramhdr); 74828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < num_ent; i++) { 74838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen switch (pr_supported->chunk_types[i]) { 74848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ASCONF: 7485fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_asconf = 1; 74868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_ASCONF_ACK: 7487fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_asconf_ack = 1; 74888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 74898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_FORWARD_CUM_TSN: 7490fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_prsctp = 1; 74918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 74928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_PACKET_DROPPED: 7493fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_pktdrop = 1; 74948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 74958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_NR_SELECTIVE_ACK: 7496fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_nrsack = 1; 74978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 74988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_STREAM_RESET: 7499fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_reconfig = 1; 75008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 75018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen case SCTP_AUTHENTICATION: 7502fb3816eaffe5878bb1286adb120fd160da178a05t peer_supports_auth = 1; 75038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 75048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen default: 75058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* one I have not learned yet */ 75068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 75078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 75088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 75098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 75108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_RANDOM) { 75118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen > sizeof(random_store)) 75128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 75138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (got_random) { 75148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* already processed a RANDOM */ 75158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_param; 75168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 75178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, 75188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_paramhdr *)random_store, 75198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min(sizeof(random_store),plen)); 75208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (phdr == NULL) 75218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-26); 75228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen p_random = (struct sctp_auth_random *)phdr; 75238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen random_len = plen - sizeof(*p_random); 75248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* enforce the random length */ 75258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (random_len != SCTP_AUTH_RANDOM_SIZE_REQUIRED) { 75268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_AUTH1, "SCTP: invalid RANDOM len\n"); 75278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-27); 75288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 75298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen got_random = 1; 75308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_HMAC_LIST) { 75318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int num_hmacs; 75328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 75338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 75348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen > sizeof(hmacs_store)) 75358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 75368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (got_hmacs) { 75378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* already processed a HMAC list */ 75388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_param; 75398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 75408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, 75418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_paramhdr *)hmacs_store, 75428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min(plen,sizeof(hmacs_store))); 75438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (phdr == NULL) 75448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-28); 75458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen hmacs = (struct sctp_auth_hmac_algo *)phdr; 75468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen hmacs_len = plen - sizeof(*hmacs); 75478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_hmacs = hmacs_len / sizeof(hmacs->hmac_ids[0]); 75488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* validate the hmac list */ 75498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_verify_hmac_param(hmacs, num_hmacs)) { 75508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-29); 75518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 75528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.peer_hmacs != NULL) 75538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_hmaclist(stcb->asoc.peer_hmacs); 75548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peer_hmacs = sctp_alloc_hmaclist(num_hmacs); 75558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.peer_hmacs != NULL) { 75568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < num_hmacs; i++) { 75578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_auth_add_hmacid(stcb->asoc.peer_hmacs, 75588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ntohs(hmacs->hmac_ids[i])); 75598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 75608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 75618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen got_hmacs = 1; 75628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if (ptype == SCTP_CHUNK_LIST) { 75638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 75648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 75658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (plen > sizeof(chunks_store)) 75668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 75678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (got_chklist) { 75688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* already processed a Chunks list */ 75698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto next_param; 75708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 75718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, 75728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (struct sctp_paramhdr *)chunks_store, 75738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen min(plen,sizeof(chunks_store))); 75748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (phdr == NULL) 75758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-30); 75768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chunks = (struct sctp_auth_chunk_list *)phdr; 75778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen num_chunks = plen - sizeof(*chunks); 75788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.peer_auth_chunks != NULL) 75798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_clear_chunklist(stcb->asoc.peer_auth_chunks); 75808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 75818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peer_auth_chunks = sctp_alloc_chunklist(); 75828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = 0; i < num_chunks; i++) { 75838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)sctp_auth_add_chunk(chunks->chunk_types[i], 75848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.peer_auth_chunks); 75858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* record asconf/asconf-ack if listed */ 75868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chunks->chunk_types[i] == SCTP_ASCONF) 75878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen saw_asconf = 1; 75888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chunks->chunk_types[i] == SCTP_ASCONF_ACK) 75898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen saw_asconf_ack = 1; 75908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 75918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 75928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen got_chklist = 1; 75938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else if ((ptype == SCTP_HEARTBEAT_INFO) || 75948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ptype == SCTP_STATE_COOKIE) || 75958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ptype == SCTP_UNRECOG_PARAM) || 75968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ptype == SCTP_COOKIE_PRESERVE) || 75978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ptype == SCTP_SUPPORTED_ADDRTYPE) || 75988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ptype == SCTP_ADD_IP_ADDRESS) || 75998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ptype == SCTP_DEL_IP_ADDRESS) || 76008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ptype == SCTP_ERROR_CAUSE_IND) || 76018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (ptype == SCTP_SUCCESS_REPORT)) { 76028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* don't care */ ; 76038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 76048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((ptype & 0x8000) == 0x0000) { 76058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 76068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * must stop processing the rest of the 76078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * param's. Any report bits were handled 76088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * with the call to 76098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_arethere_unrecognized_parameters() 76108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * when the INIT or INIT-ACK was first seen. 76118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 76128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 76138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 76148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 761532a191a90b5c914a02047389c5b3197e08fc9841tuexen 76168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen next_param: 76178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen offset += SCTP_SIZE32(plen); 76188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (offset >= limit) { 76198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 76208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 76218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen phdr = sctp_get_next_param(m, offset, &parm_buf, 76228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(parm_buf)); 76238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 76248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now check to see if we need to purge any addresses */ 76258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(net, &stcb->asoc.nets, sctp_next, nnet) { 76268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if ((net->dest_state & SCTP_ADDR_NOT_IN_ASSOC) == 76278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ADDR_NOT_IN_ASSOC) { 76288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* This address has been removed from the asoc */ 76298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* remove and free it */ 76308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.numnets--; 76318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&stcb->asoc.nets, net, sctp_next); 76328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(net); 76338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == stcb->asoc.primary_destination) { 76348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination = NULL; 76358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_select_primary_destination(stcb); 76368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 76378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 76388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7639fb3816eaffe5878bb1286adb120fd160da178a05t if ((stcb->asoc.ecn_supported == 1) && 7640fb3816eaffe5878bb1286adb120fd160da178a05t (peer_supports_ecn == 0)) { 7641fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.ecn_supported = 0; 76428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7643fb3816eaffe5878bb1286adb120fd160da178a05t if ((stcb->asoc.prsctp_supported == 1) && 7644fb3816eaffe5878bb1286adb120fd160da178a05t (peer_supports_prsctp == 0)) { 7645fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.prsctp_supported = 0; 7646fb3816eaffe5878bb1286adb120fd160da178a05t } 7647fb3816eaffe5878bb1286adb120fd160da178a05t if ((stcb->asoc.auth_supported == 1) && 7648fb3816eaffe5878bb1286adb120fd160da178a05t ((peer_supports_auth == 0) || 7649fb3816eaffe5878bb1286adb120fd160da178a05t (got_random == 0) || (got_hmacs == 0))) { 7650fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.auth_supported = 0; 7651fb3816eaffe5878bb1286adb120fd160da178a05t } 7652fb3816eaffe5878bb1286adb120fd160da178a05t if ((stcb->asoc.asconf_supported == 1) && 7653fb3816eaffe5878bb1286adb120fd160da178a05t ((peer_supports_asconf == 0) || (peer_supports_asconf_ack == 0) || 7654fb3816eaffe5878bb1286adb120fd160da178a05t (stcb->asoc.auth_supported == 0) || 7655fb3816eaffe5878bb1286adb120fd160da178a05t (saw_asconf == 0) || (saw_asconf_ack == 0))) { 7656fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.asconf_supported = 0; 7657fb3816eaffe5878bb1286adb120fd160da178a05t } 7658fb3816eaffe5878bb1286adb120fd160da178a05t if ((stcb->asoc.reconfig_supported == 1) && 7659fb3816eaffe5878bb1286adb120fd160da178a05t (peer_supports_reconfig == 0)) { 7660fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.reconfig_supported = 0; 7661fb3816eaffe5878bb1286adb120fd160da178a05t } 7662fb3816eaffe5878bb1286adb120fd160da178a05t if ((stcb->asoc.nrsack_supported == 1) && 7663fb3816eaffe5878bb1286adb120fd160da178a05t (peer_supports_nrsack == 0)) { 7664fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.nrsack_supported = 0; 7665fb3816eaffe5878bb1286adb120fd160da178a05t } 7666fb3816eaffe5878bb1286adb120fd160da178a05t if ((stcb->asoc.pktdrop_supported == 1) && 7667fb3816eaffe5878bb1286adb120fd160da178a05t (peer_supports_pktdrop == 0)){ 7668fb3816eaffe5878bb1286adb120fd160da178a05t stcb->asoc.pktdrop_supported = 0; 7669fb3816eaffe5878bb1286adb120fd160da178a05t } 7670fb3816eaffe5878bb1286adb120fd160da178a05t /* validate authentication required parameters */ 7671fb3816eaffe5878bb1286adb120fd160da178a05t if ((peer_supports_auth == 0) && (got_chklist == 1)) { 76728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* peer does not support auth but sent a chunks list? */ 76738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-31); 76748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 7675fb3816eaffe5878bb1286adb120fd160da178a05t if ((peer_supports_asconf == 1) && (peer_supports_auth == 0)) { 76768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* peer supports asconf but not auth? */ 76778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-32); 7678fb3816eaffe5878bb1286adb120fd160da178a05t } else if ((peer_supports_asconf == 1) && 7679fb3816eaffe5878bb1286adb120fd160da178a05t (peer_supports_auth == 1) && 76808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ((saw_asconf == 0) || (saw_asconf_ack == 0))) { 76818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-33); 76828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 76838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* concatenate the full random key */ 76848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen keylen = sizeof(*p_random) + random_len + sizeof(*hmacs) + hmacs_len; 76858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chunks != NULL) { 76868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen keylen += sizeof(*chunks) + num_chunks; 76878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 76888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen new_key = sctp_alloc_key(keylen); 76898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (new_key != NULL) { 76908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* copy in the RANDOM */ 76918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (p_random != NULL) { 76928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen keylen = sizeof(*p_random) + random_len; 76938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bcopy(p_random, new_key->key, keylen); 76948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 76958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* append in the AUTH chunks */ 76968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chunks != NULL) { 76978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bcopy(chunks, new_key->key + keylen, 76988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(*chunks) + num_chunks); 76998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen keylen += sizeof(*chunks) + num_chunks; 77008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* append in the HMACs */ 77028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (hmacs != NULL) { 77038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen bcopy(hmacs, new_key->key + keylen, 77048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sizeof(*hmacs) + hmacs_len); 77058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 77078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* failed to get memory for the key */ 77088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-34); 77098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.authinfo.peer_random != NULL) 77118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_key(stcb->asoc.authinfo.peer_random); 77128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.authinfo.peer_random = new_key; 77138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.assoc_keyid); 77148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_clear_cachedkeys(stcb, stcb->asoc.authinfo.recv_keyid); 77158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 77168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 77178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 77188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 77198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 77208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_set_primary_addr(struct sctp_tcb *stcb, struct sockaddr *sa, 77218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_nets *net) 77228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 77238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* make sure the requested primary address exists in the assoc */ 77248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == NULL && sa) 77258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net = sctp_findnet(stcb, sa); 77268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 77278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net == NULL) { 77288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* didn't find the requested primary address! */ 77298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 77308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 77318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* set the primary address */ 77328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net->dest_state & SCTP_ADDR_UNCONFIRMED) { 77338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Must be confirmed, so queue to set */ 77348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net->dest_state |= SCTP_ADDR_REQ_PRIMARY; 77358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 77368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.primary_destination = net; 77388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!(net->dest_state & SCTP_ADDR_PF) && (stcb->asoc.alternate)) { 77398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(stcb->asoc.alternate); 77408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stcb->asoc.alternate = NULL; 77418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen net = TAILQ_FIRST(&stcb->asoc.nets); 77438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (net != stcb->asoc.primary_destination) { 77448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* first one on the list is NOT the primary 77458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_cmpaddr() is much more efficient if 77468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the primary is the first on the list, make it 77478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * so. 77488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 77498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&stcb->asoc.nets, stcb->asoc.primary_destination, sctp_next); 77508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_HEAD(&stcb->asoc.nets, stcb->asoc.primary_destination, sctp_next); 77518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 77538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 77558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 77568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 77570ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_is_vtag_good(uint32_t tag, uint16_t lport, uint16_t rport, struct timeval *now) 77588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 77598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 77608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * This function serves two purposes. It will see if a TAG can be 77618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * re-used and return 1 for yes it is ok and 0 for don't use that 77628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * tag. A secondary function it will do is purge out old tags that 77638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * can be removed. 77648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 77658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpvtaghead *chain; 77668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tagblock *twait_block; 77678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctpasochead *head; 77688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 77698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int i; 77708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 77718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RLOCK(); 77728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag, 77738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_BASE_INFO(hashasocmark))]; 77748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (head == NULL) { 77758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* invalid vtag */ 77768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen goto skip_vtag_check; 77778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(stcb, head, sctp_asocs) { 77798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We choose not to lock anything here. TCB's can't be 77808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * removed since we have the read lock, so they can't 77818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * be freed on us, same thing for the INP. I may 77828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * be wrong with this assumption, but we will go 77838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * with it for now :-) 77848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 77858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) { 77868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 77878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->asoc.my_vtag == tag) { 77898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* candidate */ 77908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->rport != rport) { 77918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 77928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (stcb->sctp_ep->sctp_lport != lport) { 77948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 77958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 77968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Its a used tag set */ 77978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 77988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 77998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenskip_vtag_check: 78028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 78038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; 78048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Now what about timed wait ? */ 780515aed6e434dc1aac416f14635bb78920317d60e7t LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { 78068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 78078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Block(s) are present, lets see if we have this tag in the 78088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * list 78098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 781015aed6e434dc1aac416f14635bb78920317d60e7t for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { 781115aed6e434dc1aac416f14635bb78920317d60e7t if (twait_block->vtag_block[i].v_tag == 0) { 781215aed6e434dc1aac416f14635bb78920317d60e7t /* not used */ 781315aed6e434dc1aac416f14635bb78920317d60e7t continue; 781415aed6e434dc1aac416f14635bb78920317d60e7t } else if ((long)twait_block->vtag_block[i].tv_sec_at_expire < 781515aed6e434dc1aac416f14635bb78920317d60e7t now->tv_sec) { 781615aed6e434dc1aac416f14635bb78920317d60e7t /* Audit expires this guy */ 781715aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].tv_sec_at_expire = 0; 781815aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].v_tag = 0; 781915aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].lport = 0; 782015aed6e434dc1aac416f14635bb78920317d60e7t twait_block->vtag_block[i].rport = 0; 782115aed6e434dc1aac416f14635bb78920317d60e7t } else if ((twait_block->vtag_block[i].v_tag == tag) && 782215aed6e434dc1aac416f14635bb78920317d60e7t (twait_block->vtag_block[i].lport == lport) && 782315aed6e434dc1aac416f14635bb78920317d60e7t (twait_block->vtag_block[i].rport == rport)) { 782415aed6e434dc1aac416f14635bb78920317d60e7t /* Bad tag, sorry :< */ 782515aed6e434dc1aac416f14635bb78920317d60e7t SCTP_INP_INFO_RUNLOCK(); 782615aed6e434dc1aac416f14635bb78920317d60e7t return (0); 78278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 78318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (1); 78328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 78338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 78348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void 78350ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_drain_mbufs(struct sctp_tcb *stcb) 78368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 78378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 78388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We must hunt this association for MBUF's past the cumack (i.e. 78398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * out of order data that we can renege on). 78408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 78418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_association *asoc; 78428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tmit_chunk *chk, *nchk; 78438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t cumulative_tsn_p1; 78448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_queued_to_read *ctl, *nctl; 78458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen int cnt, strmat; 78468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t gap, i; 7847b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen int fnd = 0; 78488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 78498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We look for anything larger than the cum-ack + 1 */ 78508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 78518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc = &stcb->asoc; 78528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (asoc->cumulative_tsn == asoc->highest_tsn_inside_map) { 78538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* none we can reneg on. */ 78548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 78558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_protocol_drains_done); 78578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cumulative_tsn_p1 = asoc->cumulative_tsn + 1; 78588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt = 0; 78598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* First look in the re-assembly queue */ 78608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) { 78618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(chk->rec.data.TSN_seq, cumulative_tsn_p1)) { 78628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yep it is above cum-ack */ 78638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt++; 78648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.TSN_seq, asoc->mapping_array_base_tsn); 78658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_reasm_queue = sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size); 78668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_reasm_queue); 78678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); 78688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next); 78698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (chk->data) { 78708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(chk->data); 78718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen chk->data = NULL; 78728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 78748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Ok that was fun, now we will drain all the inbound streams? */ 78778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (strmat = 0; strmat < asoc->streamincnt; strmat++) { 78788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].inqueue, next, nctl) { 78798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_TSN_GT(ctl->sinfo_tsn, cumulative_tsn_p1)) { 78808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Yep it is above cum-ack */ 78818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cnt++; 78828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CALC_TSN_TO_GAP(gap, ctl->sinfo_tsn, asoc->mapping_array_base_tsn); 78838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->size_on_all_streams = sctp_sbspace_sub(asoc->size_on_all_streams, ctl->length); 78848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_ucount_decr(asoc->cnt_on_all_streams); 78858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap); 78868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_REMOVE(&asoc->strmin[strmat].inqueue, ctl, next); 78878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (ctl->data) { 78888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_m_freem(ctl->data); 78898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen ctl->data = NULL; 78908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_free_remote_addr(ctl->whoFrom); 78928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl); 78938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_DECR_READQ_COUNT(); 78948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 78978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (cnt) { 78988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* We must back down to see what the new highest is */ 78998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen for (i = asoc->highest_tsn_inside_map; SCTP_TSN_GE(i, asoc->mapping_array_base_tsn); i--) { 79008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_CALC_TSN_TO_GAP(gap, i, asoc->mapping_array_base_tsn); 79018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_IS_TSN_PRESENT(asoc->mapping_array, gap)) { 79028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_map = i; 79038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen fnd = 1; 79048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen break; 79058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 79068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 79078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (!fnd) { 79088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->highest_tsn_inside_map = asoc->mapping_array_base_tsn - 1; 79098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 79108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 79118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 79128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Question, should we go through the delivery queue? The only 79138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * reason things are on here is the app not reading OR a p-d-api up. 79148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * An attacker COULD send enough in to initiate the PD-API and then 79158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * send a bunch of stuff to other streams... these would wind up on 79168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the delivery queue.. and then we would not get to them. But in 79178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * order to do this I then have to back-track and un-deliver 79188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sequence numbers in streams.. el-yucko. I think for now we will 79198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOT look at the delivery queue and leave it to be something to 79208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * consider later. An alternative would be to abort the P-D-API with 79218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a notification and then deliver the data.... Or another method 79228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * might be to keep track of how many times the situation occurs and 79238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if we see a possible attack underway just abort the association. 79248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 79258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG 79268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTPDBG(SCTP_DEBUG_PCB1, "Freed %d chunks from reneg harvest\n", cnt); 79278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 79288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 79298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Now do we need to find a new 79308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * asoc->highest_tsn_inside_map? 79318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 79328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc->last_revoke_count = cnt; 79338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen (void)SCTP_OS_TIMER_STOP(&stcb->asoc.dack_timer.timer); 79348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /*sa_ignore NO_NULL_CHK*/ 79358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 79368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_DRAIN, SCTP_SO_NOT_LOCKED); 79378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 79388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 79398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Another issue, in un-setting the TSN's in the mapping array we 79408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * DID NOT adjust the highest_tsn marker. This will cause one of two 79418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * things to occur. It may cause us to do extra work in checking for 79428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * our mapping array movement. More importantly it may cause us to 79438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SACK every datagram. This may not be a bad thing though since we 79448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * will recover once we get our cum-ack above and all this stuff we 79458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * dumped recovered. 79468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 79478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 79488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 79498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid 79508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_drain() 79518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 79528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* 79538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * We must walk the PCB lists for ALL associations here. The system 79548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is LOW on MBUF's and needs help. This is where reneging will 79558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * occur. We really hope this does NOT happen! 79568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 79578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 79588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen VNET_ITERATOR_DECL(vnet_iter); 79598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 79608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 79618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 79628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 79638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_protocol_drain_calls); 79648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { 79658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 79668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 79678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 79688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 79698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen VNET_LIST_RLOCK_NOSLEEP(); 79708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen VNET_FOREACH(vnet_iter) { 79718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen CURVNET_SET(vnet_iter); 79728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *inp; 79738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_tcb *stcb; 79748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 79758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 79768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 79778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_STAT_INCR(sctps_protocol_drain_calls); 79788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) { 79798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef VIMAGE 79808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen continue; 79818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else 79828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return; 798332a191a90b5c914a02047389c5b3197e08fc9841tuexen#endif 79848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 79858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 79868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RLOCK(); 79878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) { 79888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* For each endpoint */ 79898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RLOCK(inp); 79908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 79918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* For each association */ 79928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_LOCK(stcb); 79930ac02f34d6041cd0018437596a5a9a94685e6919tuexen sctp_drain_mbufs(stcb); 79948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_TCB_UNLOCK(stcb); 79958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 79968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_RUNLOCK(inp); 79978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 79988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 79998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 80008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen CURVNET_RESTORE(); 80018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 80028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen VNET_LIST_RUNLOCK_NOSLEEP(); 80038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif 80048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 80058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 80068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* 80078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * start a new iterator 80088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * iterates through all endpoints and associations based on the pcb_state 80098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * flags and asoc_state. "af" (mandatory) is executed for all matching 80108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assocs and "ef" (optional) is executed when the iterator completes. 80118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "inpf" (optional) is executed for each new endpoint as it is being 80128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * iterated through. inpe (optional) is called when the inp completes 80138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * its way through all the stcbs. 80148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */ 80158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint 80168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_initiate_iterator(inp_func inpf, 80178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen asoc_func af, 80188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen inp_func inpe, 80198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t pcb_state, 80208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t pcb_features, 80218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t asoc_state, 80228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen void *argp, 80238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint32_t argi, 80248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen end_func ef, 80258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_inpcb *s_inp, 80268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen uint8_t chunk_output_off) 80278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{ 80288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen struct sctp_iterator *it = NULL; 80298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 80308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (af == NULL) { 80318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (-1); 80328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 80338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_MALLOC(it, struct sctp_iterator *, sizeof(struct sctp_iterator), 80348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_M_ITER); 80358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (it == NULL) { 80368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOMEM); 80378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (ENOMEM); 80388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 80398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen memset(it, 0, sizeof(*it)); 80408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->function_assoc = af; 80418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->function_inp = inpf; 80428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (inpf) 80438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->done_current_ep = 0; 80448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen else 80458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->done_current_ep = 1; 80468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->function_atend = ef; 80478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->pointer = argp; 80488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->val = argi; 80498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->pcb_flags = pcb_state; 80508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->pcb_features = pcb_features; 80518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->asoc_state = asoc_state; 80528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->function_inp_end = inpe; 80538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->no_chunk_output = chunk_output_off; 80548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 80558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->vn = curvnet; 805632a191a90b5c914a02047389c5b3197e08fc9841tuexen#endif 80578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (s_inp) { 80588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* Assume lock is held here */ 80598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->inp = s_inp; 80608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INCR_REF(it->inp); 80618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->iterator_flags = SCTP_ITERATOR_DO_SINGLE_INP; 80628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } else { 80638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RLOCK(); 80648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->inp = LIST_FIRST(&SCTP_BASE_INFO(listhead)); 80658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (it->inp) { 80668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INCR_REF(it->inp); 80678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 80688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_INP_INFO_RUNLOCK(); 80698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen it->iterator_flags = SCTP_ITERATOR_DO_ALL_INP; 80708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 80718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 80728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ITERATOR_WQ_LOCK(); 80738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 80748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen TAILQ_INSERT_TAIL(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); 80758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen if (sctp_it_ctl.iterator_running == 0) { 80768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_wakeup_iterator(); 80778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen } 80788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen SCTP_IPI_ITERATOR_WQ_UNLOCK(); 80798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen /* sa_ignore MEMLEAK {memory is put on the tailq for the iterator} */ 80808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen return (0); 80818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen} 8082