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