129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen/*-
229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
3ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen *
629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * Redistribution and use in source and binary forms, with or without
729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * modification, are permitted provided that the following conditions are met:
829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen *
929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * a) Redistributions of source code must retain the above copyright notice,
1029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen *    this list of conditions and the following disclaimer.
1129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen *
1229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * b) Redistributions in binary form must reproduce the above copyright
1329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen *    notice, this list of conditions and the following disclaimer in
1429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen *    the documentation and/or other materials provided with the distribution.
1529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen *
1629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * c) Neither the name of Cisco Systems, Inc. nor the names of its
1729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen *    contributors may be used to endorse or promote products derived
1829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen *    from this software without specific prior written permission.
1929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen *
2029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * THE POSSIBILITY OF SUCH DAMAGE.
3129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen */
3229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
3329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef __FreeBSD__
3429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <sys/cdefs.h>
35bfb1bf7e665a02b48026482bf33d05c83dfad73bt__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 271221 2014-09-07 09:06:26Z tuexen $");
3629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
3729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
3829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_os.h>
39c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen#ifdef INET6
4029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef __FreeBSD__
4129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <sys/proc.h>
4229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
4329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_pcb.h>
4429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_header.h>
4529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_var.h>
46e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET6
4729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet6/sctp6_var.h>
4829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
4929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_sysctl.h>
5029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_output.h>
5129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_uio.h>
5229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_asconf.h>
5329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctputil.h>
5429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_indata.h>
5529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_timer.h>
5629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_auth.h>
5729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_input.h>
5829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_output.h>
5929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_bsd_addr.h>
6029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/sctp_crc32.h>
6159caa502fe5258530a6f6eab10155a6dac5d8d5atuexen#if !defined(__Userspace_os_Windows)
6229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netinet/udp.h>
6359caa502fe5258530a6f6eab10155a6dac5d8d5atuexen#endif
6429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
6529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__APPLE__)
6629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#define APPLE_FILE_NO 9
6729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
6829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef IPSEC
6929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netipsec/ipsec.h>
70e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET6
7129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#include <netipsec/ipsec6.h>
7229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif /* INET6 */
7329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif /* IPSEC */
7429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
750612043f643c9b26245564c05defca64d472060etuexen#if !defined(__Userspace__)
7629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenextern struct protosw inetsw[];
7729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
780612043f643c9b26245564c05defca64d472060etuexen#if defined(__Panda__) || defined(__Userspace__)
7929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint ip6_v6only=0;
8029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
810cfdc9964570b9773086305f77ec1dc609daec56tuexen#if defined(__Userspace__)
8229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenvoid
8329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenin6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
8429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
8559caa502fe5258530a6f6eab10155a6dac5d8d5atuexen#if defined(__Userspace_os_Windows)
8659caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	uint32_t temp;
8759caa502fe5258530a6f6eab10155a6dac5d8d5atuexen#endif
8829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	bzero(sin, sizeof(*sin));
897b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
9029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin->sin_len = sizeof(struct sockaddr_in);
9129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
9229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin->sin_family = AF_INET;
9329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin->sin_port = sin6->sin6_port;
9459caa502fe5258530a6f6eab10155a6dac5d8d5atuexen#if defined(__Userspace_os_Windows)
9559caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	temp = sin6->sin6_addr.s6_addr16[7];
9659caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	temp = temp << 16;
9759caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	temp = temp | sin6->sin6_addr.s6_addr16[6];
9859caa502fe5258530a6f6eab10155a6dac5d8d5atuexen	sin->sin_addr.s_addr = temp;
99000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	sctp_print_address((struct sockaddr*)sin);
10059caa502fe5258530a6f6eab10155a6dac5d8d5atuexen#else
10129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
10259caa502fe5258530a6f6eab10155a6dac5d8d5atuexen#endif
10329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
10429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
10529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenvoid
10629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenin6_sin6_2_sin_in_sock(struct sockaddr *nam)
10729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
10829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in *sin_p;
10929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in6 sin6;
11029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
11129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* save original sockaddr_in6 addr and convert it to sockaddr_in  */
11229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin6 = *(struct sockaddr_in6 *)nam;
11329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin_p = (struct sockaddr_in *)nam;
11429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	in6_sin6_2_sin(sin_p, &sin6);
11529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
1160cfdc9964570b9773086305f77ec1dc609daec56tuexen#endif
11729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
118cbc99d79b7130a379a4d6c538b25deaa7321ac37t#if !defined(__Userspace__)
11929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
120b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#if defined(__APPLE__) || defined(__FreeBSD__)
12129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
12229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined( __Panda__)
12329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_input(pakhandle_type *i_pak)
12429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
12529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_input(struct mbuf **i_pak, int *offp, int proto)
12629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
12729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
12829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct mbuf *m;
129923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	int iphlen;
13066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	uint32_t vrf_id;
131923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	uint8_t ecn_bits;
132e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	struct sockaddr_in6 src, dst;
13329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct ip6_hdr *ip6;
13429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctphdr *sh;
13529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_chunkhdr *ch;
136923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	int length, offset;
13766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if !defined(SCTP_WITH_NO_CSUM)
13866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	uint8_t compute_crc;
13966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif
1406a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#if defined(__FreeBSD__)
1416a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen	uint32_t mflowid;
1426a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen	uint8_t use_mflowid;
1436a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#endif
144b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#if !(defined(__APPLE__) || defined (__FreeBSD__))
14529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	uint16_t port = 0;
14629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
147923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen
148923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#if defined(__Panda__)
149923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	/* This is Evil, but its the only way to make panda work right. */
150923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	iphlen = sizeof(struct ip6_hdr);
151923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#else
152923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	iphlen = *offp;
15329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
154923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
15529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_RELEASE_PKT(*i_pak);
156923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen		return (IPPROTO_DONE);
15729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
15829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	m = SCTP_HEADER_TO_CHAIN(*i_pak);
15929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef __Panda__
16029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_DETACH_HEADER_FROM_CHAIN(*i_pak);
16129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	(void)SCTP_RELEASE_HEADER(*i_pak);
16229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
163923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#ifdef SCTP_MBUF_LOGGING
164923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	/* Log in any input mbufs */
165923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
166923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen		struct mbuf *mat;
16729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
168923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen		for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
169923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen			if (SCTP_BUF_IS_EXTENDED(mat)) {
170923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen				sctp_log_mb(mat, SCTP_MBUF_INPUT);
171923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen			}
172923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen		}
173923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	}
174923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#endif
1751b50943bdc80bbed39e89acdb49bd3b3f30c528ctuexen#ifdef SCTP_PACKET_LOGGING
1761b50943bdc80bbed39e89acdb49bd3b3f30c528ctuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
1771b50943bdc80bbed39e89acdb49bd3b3f30c528ctuexen		sctp_packet_log(m);
1781b50943bdc80bbed39e89acdb49bd3b3f30c528ctuexen	}
17929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
1806a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#if defined(__FreeBSD__)
18132ce34e90f7862d56c81f432a802a00110f7b427t#if __FreeBSD_version > 1000049
18232ce34e90f7862d56c81f432a802a00110f7b427t	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
18332ce34e90f7862d56c81f432a802a00110f7b427t	        "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%b.\n",
18432ce34e90f7862d56c81f432a802a00110f7b427t	        m->m_pkthdr.len,
18532ce34e90f7862d56c81f432a802a00110f7b427t	        if_name(m->m_pkthdr.rcvif),
18632ce34e90f7862d56c81f432a802a00110f7b427t	        (int)m->m_pkthdr.csum_flags, CSUM_BITS);
1878d509612af0dc2e1895434112897cf049b463063t#elif __FreeBSD_version >= 800000
18866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
18966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
19066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.len,
19166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        if_name(m->m_pkthdr.rcvif),
19266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.csum_flags);
19366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#else
19466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
19566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
19666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.len,
19766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.rcvif->if_xname,
19866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.csum_flags);
19966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif
20066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif
20166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if defined(__APPLE__)
20266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
20366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        "sctp6_input(): Packet of length %d received on %s%d with csum_flags 0x%x.\n",
20466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.len,
20566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.rcvif->if_name,
20666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.rcvif->if_unit,
20766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.csum_flags);
20866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif
20966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if defined(__Windows__)
21066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
21166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
21266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.len,
21366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.rcvif->if_xname,
21466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	        m->m_pkthdr.csum_flags);
21566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif
21666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if defined(__FreeBSD__)
2176a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen	if (m->m_flags & M_FLOWID) {
2186a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen		mflowid = m->m_pkthdr.flowid;
2196a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen		use_mflowid = 1;
2206a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen	} else {
2216a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen		mflowid = 0;
2226a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen		use_mflowid = 0;
2236a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen	}
2246a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#endif
225923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	SCTP_STAT_INCR(sctps_recvpackets);
226923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
227923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	/* Get IP, SCTP, and first chunk header together in the first mbuf. */
228923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
22966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	ip6 = mtod(m, struct ip6_hdr *);
230923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen,
231923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen		       (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)));
23229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (sh == NULL) {
23329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_STAT_INCR(sctps_hdrops);
234f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (IPPROTO_DONE);
23529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
23629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
237923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	offset -= sizeof(struct sctp_chunkhdr);
238e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	memset(&src, 0, sizeof(struct sockaddr_in6));
239e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	src.sin6_family = AF_INET6;
2407b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
241e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	src.sin6_len = sizeof(struct sockaddr_in6);
242e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#endif
243e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	src.sin6_port = sh->src_port;
244e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	src.sin6_addr = ip6->ip6_src;
245e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#if defined(__FreeBSD__)
246e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#if defined(__APPLE__)
247e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	/* XXX: This code should also be used on Apple */
248e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#endif
249e2828360ea9cf8951730d46f5c14626c9425cb30t	if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
25066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		goto out;
251e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	}
252e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#endif
253e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	memset(&dst, 0, sizeof(struct sockaddr_in6));
254e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	dst.sin6_family = AF_INET6;
2557b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
256e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	dst.sin6_len = sizeof(struct sockaddr_in6);
257e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#endif
258e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	dst.sin6_port = sh->dest_port;
259e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	dst.sin6_addr = ip6->ip6_dst;
260e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#if defined(__FreeBSD__)
261e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#if defined(__APPLE__)
262e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	/* XXX: This code should also be used on Apple */
263e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#endif
264e2828360ea9cf8951730d46f5c14626c9425cb30t	if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
26566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		goto out;
266e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	}
267e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen#endif
26829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef __FreeBSD__
269e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	if (faithprefix_p != NULL && (*faithprefix_p) (&dst.sin6_addr)) {
27029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* XXX send icmp6 host/port unreach? */
27166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		goto out;
27229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
273923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#endif
274923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#if defined(__APPLE__)
275923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#if defined(NFAITH) && 0 < NFAITH
276e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	if (faithprefix(&dst.sin6_addr)) {
27766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		goto out;
278923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	}
27929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
280923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#endif
281923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	length = ntohs(ip6->ip6_plen) + iphlen;
282923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	/* Validate mbuf chain length with IP payload length. */
28366bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	if (SCTP_HEADER_LEN(m) != length) {
284923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen		SCTPDBG(SCTP_DEBUG_INPUT1,
28566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		        "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
286923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen		SCTP_STAT_INCR(sctps_hdrops);
28766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		goto out;
28829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
289923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
29066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		goto out;
291923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	}
29266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
29329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(SCTP_WITH_NO_CSUM)
29429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_STAT_INCR(sctps_recvnocrc);
29529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
29629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
29729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
29829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_STAT_INCR(sctps_recvhwcrc);
29966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		compute_crc = 0;
30066bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	} else {
30166bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#else
30266bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	if (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
303e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	    (IN6_ARE_ADDR_EQUAL(&src.sin6_addr, &dst.sin6_addr))) {
30429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_STAT_INCR(sctps_recvnocrc);
30566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		compute_crc = 0;
30666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	} else {
3076a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#endif
30866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		SCTP_STAT_INCR(sctps_recvswcrc);
30966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen		compute_crc = 1;
31029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
311923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen#endif
312e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	sctp_common_input_processing(&m, iphlen, offset, length,
313e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	                             (struct sockaddr *)&src,
31466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	                             (struct sockaddr *)&dst,
31566bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	                             sh, ch,
31666bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#if !defined(SCTP_WITH_NO_CSUM)
31766bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	                             compute_crc,
31866bfb48e8d1df0adff2c330f249edcff464a5a25tuexen#endif
31966bfb48e8d1df0adff2c330f249edcff464a5a25tuexen	                             ecn_bits,
3206a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#if defined(__FreeBSD__)
3216a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen	                             use_mflowid, mflowid,
3226a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#endif
3236a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen	                             vrf_id, port);
32466bfb48e8d1df0adff2c330f249edcff464a5a25tuexen out:
325923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	if (m) {
32629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		sctp_m_freem(m);
327923cf3e0f34bc13ed0c9510886aa189a5a5e7183tuexen	}
328f840325bb9bca0f8732b3f8179ce54fa594160abtuexen	return (IPPROTO_DONE);
32929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
33029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
33129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__APPLE__)
33229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
33329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_input(struct mbuf **i_pak, int *offp)
33429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
33529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	return (sctp6_input_with_port(i_pak, offp, 0));
33629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
33729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
33829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
339b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#if defined(__FreeBSD__)
340b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72tint
341b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72tsctp6_input(struct mbuf **i_pak, int *offp, int proto SCTP_UNUSED)
342b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t{
343b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	return (sctp6_input_with_port(i_pak, offp, 0));
344b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t}
345b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
346b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t
34729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__Panda__)
34829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenvoid
34929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
35029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic void
35129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
35229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_notify_mbuf(struct sctp_inpcb *inp, struct icmp6_hdr *icmp6,
35329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		  struct sctphdr *sh, struct sctp_tcb *stcb, struct sctp_nets *net)
35429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
35529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	uint32_t nxtsz;
35629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
35729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
35829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (icmp6 == NULL) || (sh == NULL)) {
35929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		goto out;
36029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
36129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* First do we even look at it? */
36229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag))
36329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		goto out;
36429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
36529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (icmp6->icmp6_type != ICMP6_PACKET_TOO_BIG) {
36629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* not PACKET TO BIG */
36729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		goto out;
36829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
36929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/*
37029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * ok we need to look closely. We could even get smarter and look at
37129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * anyone that we sent to in case we get a different ICMP that tells
37229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * us there is no way to reach a host, but for this impl, all we
37329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * care about is MTU discovery.
37429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 */
37529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	nxtsz = ntohl(icmp6->icmp6_mtu);
37629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* Stop any PMTU timer */
37729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL, SCTP_FROM_SCTP6_USRREQ+SCTP_LOC_1);
37829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
37929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* Adjust destination size limit */
38029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (net->mtu > nxtsz) {
38129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		net->mtu = nxtsz;
38229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (net->port) {
38329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			net->mtu -= sizeof(struct udphdr);
38429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
38529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
38629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* now what about the ep? */
38729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (stcb->asoc.smallest_mtu > nxtsz) {
38829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		struct sctp_tmit_chunk *chk;
38929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
39029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* Adjust that too */
39129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		stcb->asoc.smallest_mtu = nxtsz;
39229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* now off to subtract IP_DF flag if needed */
39329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
39429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
39529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if ((uint32_t) (chk->send_size + IP_HDR_SIZE) > nxtsz) {
39629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
39729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
39829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
39929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
40029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if ((uint32_t) (chk->send_size + IP_HDR_SIZE) > nxtsz) {
40129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				/*
40229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				 * For this guy we also mark for immediate
40329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				 * resend since we sent to big of chunk
40429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				 */
40529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
40629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				if (chk->sent != SCTP_DATAGRAM_RESEND)
40729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen					stcb->asoc.sent_queue_retran_cnt++;
40829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				chk->sent = SCTP_DATAGRAM_RESEND;
40929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				chk->rec.data.doing_fast_retransmit = 0;
41029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
41129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				chk->sent = SCTP_DATAGRAM_RESEND;
41229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				/* Clear any time so NO RTT is being done */
41329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				chk->sent_rcv_time.tv_sec = 0;
41429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				chk->sent_rcv_time.tv_usec = 0;
41529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				stcb->asoc.total_flight -= chk->send_size;
41629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				net->flight_size -= chk->send_size;
41729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
41829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
41929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
42029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL);
42129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenout:
42229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (stcb) {
42329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_TCB_UNLOCK(stcb);
42429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
42529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
42662652de4033658198a44c989a8396f0461be889btuexen#endif
42729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
4287ec5951ec04f35070419877f6b015541f6b9728dtuexen
42929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenvoid
43029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_notify(struct sctp_inpcb *inp,
43129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    struct icmp6_hdr *icmph,
43229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    struct sctphdr *sh,
43329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    struct sockaddr *to,
43429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    struct sctp_tcb *stcb,
43529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    struct sctp_nets *net)
43629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
4370612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
43829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct socket *so;
43929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
44029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
44129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
44247674b651417d493ff4e0318113fd7beeef119dbtuexen	/* protection */
44329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
44429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (sh == NULL) || (to == NULL)) {
44529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (stcb)
44629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_TCB_UNLOCK(stcb);
44729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return;
44829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
44929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* First job is to verify the vtag matches what I would send */
45029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
45129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_TCB_UNLOCK(stcb);
45229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return;
45329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
45429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (icmph->icmp6_type != ICMP_UNREACH) {
45529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* We only care about unreachable */
45629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_TCB_UNLOCK(stcb);
45729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return;
45829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
45929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if ((icmph->icmp6_code == ICMP_UNREACH_NET) ||
46029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (icmph->icmp6_code == ICMP_UNREACH_HOST) ||
46129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (icmph->icmp6_code == ICMP_UNREACH_NET_UNKNOWN) ||
46229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (icmph->icmp6_code == ICMP_UNREACH_HOST_UNKNOWN) ||
46329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (icmph->icmp6_code == ICMP_UNREACH_ISOLATED) ||
46429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (icmph->icmp6_code == ICMP_UNREACH_NET_PROHIB) ||
46529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (icmph->icmp6_code == ICMP_UNREACH_HOST_PROHIB) ||
46622a33a1debfe70529be4aa018a2912bfe5dcd8dat#if defined(__Panda__)
46729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen            (icmph->icmp6_code == ICMP_UNREACH_ADMIN)) {
46822a33a1debfe70529be4aa018a2912bfe5dcd8dat#elif defined(__Userspace_os_NetBSD)
46922a33a1debfe70529be4aa018a2912bfe5dcd8dat            (icmph->icmp6_code == ICMP_UNREACH_ADMIN_PROHIBIT)) {
47029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
47129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen            (icmph->icmp6_code == ICMP_UNREACH_FILTER_PROHIB)) {
47229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
47329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
47429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/*
47529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * Hmm reachablity problems we must examine closely. If its
47629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * not reachable, we may have lost a network. Or if there is
47729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * NO protocol at the other end named SCTP. well we consider
47829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * it a OOTB abort.
47929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 */
48029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (net->dest_state & SCTP_ADDR_REACHABLE) {
481000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			/* Ok that destination is NOT reachable */
48229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			net->dest_state &= ~SCTP_ADDR_REACHABLE;
48329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			net->dest_state &= ~SCTP_ADDR_PF;
48429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
48547674b651417d493ff4e0318113fd7beeef119dbtuexen					stcb, 0, (void *)net, SCTP_SO_NOT_LOCKED);
48629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
48729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_TCB_UNLOCK(stcb);
48829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	} else  if ((icmph->icmp6_code == ICMP_UNREACH_PROTOCOL) ||
48929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		    (icmph->icmp6_code == ICMP_UNREACH_PORT)) {
49029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/*
49129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * Here the peer is either playing tricks on us,
49229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * including an address that belongs to someone who
49329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * does not support SCTP OR was a userland
49429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * implementation that shutdown and now is dead. In
49529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * either case treat it like a OOTB abort with no
49629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * TCB
49729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 */
49847674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
4990612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
50029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		so = SCTP_INP_SO(inp);
50129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
50229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_TCB_UNLOCK(stcb);
50329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_SOCKET_LOCK(so, 1);
50429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_TCB_LOCK(stcb);
50529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
50629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
50729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_2);
5080612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
50929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_SOCKET_UNLOCK(so, 1);
51029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/
51129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
51229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* no need to unlock here, since the TCB is gone */
51329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	} else {
51429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_TCB_UNLOCK(stcb);
51529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
51629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
51729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
51829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
51929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
5200612043f643c9b26245564c05defca64d472060etuexen#if !defined(__Panda__) && !defined(__Userspace__)
52129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenvoid
52229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
52329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
52429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctphdr sh;
52529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct ip6ctlparam *ip6cp = NULL;
52629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	uint32_t vrf_id;
52729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
52829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
52929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	vrf_id = SCTP_DEFAULT_VRFID;
53029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
53129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
532f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
53329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (pktdst->sa_family != AF_INET6 ||
53429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    pktdst->sa_len != sizeof(struct sockaddr_in6))
53529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
53629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (pktdst->sa_family != AF_INET6)
53729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
53829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return;
53929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
54029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if ((unsigned)cmd >= PRC_NCMDS)
54129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return;
54229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (PRC_IS_REDIRECT(cmd)) {
54329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		d = NULL;
54429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	} else if (inet6ctlerrmap[cmd] == 0) {
54529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return;
54629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
54729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* if the parameter is from icmp6, decode it. */
54829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (d != NULL) {
54929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		ip6cp = (struct ip6ctlparam *)d;
55029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	} else {
55129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		ip6cp = (struct ip6ctlparam *)NULL;
55229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
55329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
55429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (ip6cp) {
55529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/*
55629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * XXX: We assume that when IPV6 is non NULL, M and OFF are
55729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * valid.
55829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 */
55929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* check if we can safely examine src and dst ports */
56029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		struct sctp_inpcb *inp = NULL;
56129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		struct sctp_tcb *stcb = NULL;
56229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		struct sctp_nets *net = NULL;
56329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		struct sockaddr_in6 final;
56429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
56529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (ip6cp->ip6c_m == NULL)
56629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			return;
56729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
56829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		bzero(&sh, sizeof(sh));
56929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		bzero(&final, sizeof(final));
57029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		inp = NULL;
57129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		net = NULL;
57229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		m_copydata(ip6cp->ip6c_m, ip6cp->ip6c_off, sizeof(sh),
57329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		    (caddr_t)&sh);
57429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		ip6cp->ip6c_src->sin6_port = sh.src_port;
5757b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
57629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		final.sin6_len = sizeof(final);
57729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
57829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		final.sin6_family = AF_INET6;
57929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) && __FreeBSD_cc_version < 440000
58029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		final.sin6_addr = *ip6cp->ip6c_finaldst;
58129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
58229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		final.sin6_addr = ((struct sockaddr_in6 *)pktdst)->sin6_addr;
58329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif				/* __FreeBSD_cc_version */
58429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		final.sin6_port = sh.dest_port;
585e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen		stcb = sctp_findassociation_addr_sa((struct sockaddr *)&final,
586e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen		    (struct sockaddr *)ip6cp->ip6c_src,
58729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		    &inp, &net, 1, vrf_id);
58829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* inp's ref-count increased && stcb locked */
58929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
59029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (cmd == PRC_MSGSIZE) {
59129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				sctp6_notify_mbuf(inp,
59229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				    ip6cp->ip6c_icmp6,
59329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				    &sh,
59429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				    stcb,
59529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				    net);
59629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				/* inp's ref-count reduced && stcb unlocked */
59729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			} else {
59829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				sctp6_notify(inp, ip6cp->ip6c_icmp6, &sh,
59929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				    (struct sockaddr *)&final,
60029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				    stcb, net);
60129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				/* inp's ref-count reduced && stcb unlocked */
60229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
60329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		} else {
60429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if !defined(__Windows__)
60529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (PRC_IS_REDIRECT(cmd) && inp) {
60629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				in6_rtchange((struct in6pcb *)inp,
60729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				    inet6ctlerrmap[cmd]);
60829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
60929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
61029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (inp) {
61129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				/* reduce inp's ref-count */
61229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				SCTP_INP_WLOCK(inp);
61329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				SCTP_INP_DECR_REF(inp);
61429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				SCTP_INP_WUNLOCK(inp);
61529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
61629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (stcb)
61729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				SCTP_TCB_UNLOCK(stcb);
61829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
61929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
62029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
62129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
62229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
62329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen/*
62429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * this routine can probably be collasped into the one in sctp_userreq.c
62529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen * since they do the same thing and now we lookup with a sockaddr
62629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen */
62729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef __FreeBSD__
62829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
62929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_getcred(SYSCTL_HANDLER_ARGS)
63029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
63129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct xucred xuc;
63229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in6 addrs[2];
63329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_inpcb *inp;
63429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_nets *net;
63529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_tcb *stcb;
63629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int error;
63729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	uint32_t vrf_id;
63829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
63929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__)
64029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	vrf_id = SCTP_DEFAULT_VRFID;
64129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
64229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	vrf_id = panda_get_vrf_from_call(); /* from connectx call? */
64329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
64429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
64529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) && __FreeBSD_version > 602000
64629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	error = priv_check(req->td, PRIV_NETINET_GETCRED);
64729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__FreeBSD__) && __FreeBSD_version >= 500000
64829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	error = suser(req->td);
64929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
65029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	error = suser(req->p);
65129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
65229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (error)
65329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (error);
65429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
65529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (req->newlen != sizeof(addrs)) {
65629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
65729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (EINVAL);
65829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
65929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (req->oldlen != sizeof(struct ucred)) {
66029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
66129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (EINVAL);
66229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
66329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	error = SYSCTL_IN(req, addrs, sizeof(addrs));
66429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (error)
66529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (error);
66629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
667e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[1]),
668e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	    sin6tosa(&addrs[0]),
66929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    &inp, &net, 1, vrf_id);
67029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
67129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if ((inp != NULL) && (stcb == NULL)) {
67229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			/* reduce ref-count */
67329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_INP_WLOCK(inp);
67429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_INP_DECR_REF(inp);
67529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			goto cred_can_cont;
67629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
67729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
67829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = ENOENT;
67929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		goto out;
68029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
68129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_TCB_UNLOCK(stcb);
68229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* We use the write lock here, only
68329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * since in the error leg we need it.
68429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * If we used RLOCK, then we would have
68529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * to wlock/decr/unlock/rlock. Which
68629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * in theory could create a hole. Better
68729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * to use higher wlock.
68829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 */
68929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_INP_WLOCK(inp);
69029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen cred_can_cont:
69129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
69229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (error) {
69329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_INP_WUNLOCK(inp);
69429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		goto out;
69529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
69629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	cru2x(inp->sctp_socket->so_cred, &xuc);
69729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_INP_WUNLOCK(inp);
69829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
69929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenout:
70029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	return (error);
70129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
70229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
70329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenSYSCTL_PROC(_net_inet6_sctp6, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
70429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    0, 0,
70529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    sctp6_getcred, "S,ucred", "Get the ucred of a SCTP6 connection");
70629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
70729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
70829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
70929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen/* This is the same as the sctp_abort() could be made common */
71029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 690000) || defined(__Windows__)
71129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic void
71229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Panda__) || defined(__Userspace__)
71329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
71429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
71529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
71629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
71729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_abort(struct socket *so)
71829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
71929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_inpcb *inp;
72029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	uint32_t flags;
72129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
72229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
7232fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
72429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
72529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 690000) || defined(__Windows__)
72629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return;
72729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
728f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (EINVAL);
72929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
73029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
73129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen sctp_must_try_again:
73229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	flags = inp->sctp_flags;
73329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef SCTP_LOG_CLOSING
73429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_log_closing(inp, NULL, 17);
73529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
73629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
73729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
73829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef SCTP_LOG_CLOSING
73929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		sctp_log_closing(inp, NULL, 16);
74029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
74129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
74229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
74329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SOCK_LOCK(so);
74429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_SB_CLEAR(so->so_snd);
74529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* same for the rcv ones, they are only
74629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * here for the accounting/select.
74729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 */
74829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_SB_CLEAR(so->so_rcv);
74929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__APPLE__)
75029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		so->so_usecount--;
75129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
75229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* Now null out the reference, we are completely detached. */
75329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		so->so_pcb = NULL;
75429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
75529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SOCK_UNLOCK(so);
75629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	} else {
75729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		flags = inp->sctp_flags;
75829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
75929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			goto sctp_must_try_again;
76029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
76129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
76229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 690000) || defined(__Windows__)
76329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	return;
76429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
76529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	return (0);
76629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
76729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
76829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
76929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
77029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
77129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
77229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Panda__) || defined(__Userspace__)
77329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
77429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
77529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Windows__)
77629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
77729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_attach(struct socket *so, int proto SCTP_UNUSED, PKTHREAD p SCTP_UNUSED)
77829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
77929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
78029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED)
78129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
78229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
78329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct in6pcb *inp6;
78429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int error;
78529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_inpcb *inp;
78629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if !defined(__Panda__) && !defined(__Userspace__)
78729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	uint32_t vrf_id = SCTP_DEFAULT_VRFID;
78829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
78929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
79029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
79129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (inp != NULL) {
79229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
793f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (EINVAL);
79429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
79529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
79629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
79729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
79829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (error)
799f840325bb9bca0f8732b3f8179ce54fa594160abtuexen			return (error);
80029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
80129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	error = sctp_inpcb_alloc(so, vrf_id);
80229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (error)
803f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (error);
80429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
80529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_INP_WLOCK(inp);
80629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6;	/* I'm v6! */
80729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp6 = (struct in6pcb *)inp;
80829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
8090612043f643c9b26245564c05defca64d472060etuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
81029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp6->inp_vflag |= INP_IPV6;
81129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
81229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp->inp_vflag |= INP_IPV6;
81329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
81429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if !defined(__Panda__)
81529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp6->in6p_hops = -1;	/* use kernel default */
81629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp6->in6p_cksum = -1;	/* just to be sure */
81729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
81829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
81929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/*
82029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * XXX: ugly!! IPv4 TTL initialization is necessary for an IPv6
82129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * socket as well, because the socket may be bound to an IPv6
82229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * wildcard address, which may match an IPv4-mapped IPv6 address.
82329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 */
82429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp6->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
82529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
82629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/*
82729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * Hmm what about the IPSEC stuff that is missing here but in
82829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * sctp_attach()?
82929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 */
83029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_INP_WUNLOCK(inp);
831f840325bb9bca0f8732b3f8179ce54fa594160abtuexen	return (0);
83229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
83329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
83429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
83529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
83629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
83729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
83829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__FreeBSD__) || defined(__APPLE__)
83929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
84029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_bind(struct socket *so, struct sockaddr *addr, struct proc *p)
84129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
84229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Panda__) || defined(__Userspace__)
84329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
84429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_bind(struct socket *so, struct sockaddr *addr, void * p)
84529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
84629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Windows__)
84729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
84829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_bind(struct socket *so, struct sockaddr *addr, PKTHREAD p)
84929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
85029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
85129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
85229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_bind(struct socket *so, struct mbuf *nam, struct proc *p)
85329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
85429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
85529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
85629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
85729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_inpcb *inp;
85829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct in6pcb *inp6;
85929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int error;
86029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
86129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
8622fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
86329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
864f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (EINVAL);
86529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
86629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
86729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if !defined(__Windows__)
86829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (addr) {
86929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		switch (addr->sa_family) {
87029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
87129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		case AF_INET:
872f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
87329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (addr->sa_len != sizeof(struct sockaddr_in)) {
87429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
875f840325bb9bca0f8732b3f8179ce54fa594160abtuexen				return (EINVAL);
87629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
87729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
87829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			break;
87929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
88029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET6
88129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		case AF_INET6:
882f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
88329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (addr->sa_len != sizeof(struct sockaddr_in6)) {
88429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
885f840325bb9bca0f8732b3f8179ce54fa594160abtuexen				return (EINVAL);
88629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
88729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
88829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			break;
88929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
89029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		default:
89129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
892f840325bb9bca0f8732b3f8179ce54fa594160abtuexen			return (EINVAL);
89329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
89429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
89529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
89629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp6 = (struct in6pcb *)inp;
8970612043f643c9b26245564c05defca64d472060etuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
89829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp6->inp_vflag &= ~INP_IPV4;
89929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp6->inp_vflag |= INP_IPV6;
90029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
90129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp->inp_vflag &= ~INP_IPV4;
90229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp->inp_vflag |= INP_IPV6;
90329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
90429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp6) == 0)) {
90529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		switch (addr->sa_family) {
90629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
90729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		case AF_INET:
90829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			/* binding v4 addr to v6 socket, so reset flags */
9090612043f643c9b26245564c05defca64d472060etuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
91029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			inp6->inp_vflag |= INP_IPV4;
91129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			inp6->inp_vflag &= ~INP_IPV6;
91229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
91329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			inp->inp_vflag |= INP_IPV4;
91429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			inp->inp_vflag &= ~INP_IPV6;
91529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
91629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			break;
91729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
91829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET6
91929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		case AF_INET6:
92029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		{
92129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			struct sockaddr_in6 *sin6_p;
92229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
92329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			sin6_p = (struct sockaddr_in6 *)addr;
92429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
92529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
9260612043f643c9b26245564c05defca64d472060etuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
92729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				inp6->inp_vflag |= INP_IPV4;
92829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
92929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				inp->inp_vflag |= INP_IPV4;
93029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
93129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
93229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
93329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
93429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				struct sockaddr_in sin;
93529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
93629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				in6_sin6_2_sin(&sin, sin6_p);
9370612043f643c9b26245564c05defca64d472060etuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
93829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				inp6->inp_vflag |= INP_IPV4;
93929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				inp6->inp_vflag &= ~INP_IPV6;
94029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
94129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				inp->inp_vflag |= INP_IPV4;
94229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				inp->inp_vflag &= ~INP_IPV6;
94329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
94429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
945f840325bb9bca0f8732b3f8179ce54fa594160abtuexen				return (error);
94629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
94729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
94829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			break;
94929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
95029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
95129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		default:
95229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			break;
95329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
95429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	} else if (addr != NULL) {
95529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		struct sockaddr_in6 *sin6_p;
95629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
95729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* IPV6_V6ONLY socket */
95829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
95929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (addr->sa_family == AF_INET) {
96029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			/* can't bind v4 addr to v6 only socket! */
96129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
962f840325bb9bca0f8732b3f8179ce54fa594160abtuexen			return (EINVAL);
96329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
96429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
96529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		sin6_p = (struct sockaddr_in6 *)addr;
96629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
96729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
96829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			/* can't bind v4-mapped addrs either! */
96929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			/* NOTE: we don't support SIIT */
97029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
971f840325bb9bca0f8732b3f8179ce54fa594160abtuexen			return (EINVAL);
97229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
97329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
97429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	error = sctp_inpcb_bind(so, addr, NULL, p);
975f840325bb9bca0f8732b3f8179ce54fa594160abtuexen	return (error);
97629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
97729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
9787ec5951ec04f35070419877f6b015541f6b9728dtuexen
9798a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 690000) || defined(__Windows__) || defined(__Userspace__)
9808a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen#if !defined(__Userspace__)
9817ec5951ec04f35070419877f6b015541f6b9728dtuexenstatic void
9827ec5951ec04f35070419877f6b015541f6b9728dtuexen#else
9838a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexenvoid
9847ec5951ec04f35070419877f6b015541f6b9728dtuexen#endif
98529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_close(struct socket *so)
98629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
98729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_close(so);
98829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
98929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
99029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen/* This could be made common with sctp_detach() since they are identical */
99129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
99229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
99329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if !defined(__Panda__)
99429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic
99529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
99629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
99729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_detach(struct socket *so)
99829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
9990612043f643c9b26245564c05defca64d472060etuexen#if defined(__Userspace__)
100029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_close(so);
100129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	return (0);
100229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
100329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	return (sctp_detach(so));
100429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
100529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
100629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
100729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
100829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
10098a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen#if !defined(__Panda__) && !defined(__Userspace__)
101029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic
101129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
101229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
101329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_disconnect(struct socket *so)
101429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
1015f57cf83923be449d11806a31f62bcc17e58832d6t	return (sctp_disconnect(so));
101629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
101729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
101829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
101929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
102029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
102129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
102229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    struct mbuf *control, struct thread *p);
102329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
102429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
102529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
102629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    struct mbuf *control, struct proc *p);
102729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
102829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
102929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
10308a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen#if !defined(__Panda__) && !defined(__Windows__) && !defined(__Userspace__)
103129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
103229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
103329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
103429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    struct mbuf *control, struct thread *p)
103529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
103629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__FreeBSD__) || defined(__APPLE__)
103729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
103829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
103929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    struct mbuf *control, struct proc *p)
104029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
104129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
104229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
104329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam,
104429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen    struct mbuf *control, struct proc *p)
104529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
104629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
104729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
104829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_inpcb *inp;
104929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct in6pcb *inp6;
105029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
105129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
105229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in6 *sin6;
105329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif /* INET */
105429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* No SPL needed since sctp_output does this */
105529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
105629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
105729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (inp == NULL) {
105829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (control) {
105929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_RELEASE_PKT(control);
106029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			control = NULL;
106129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
106229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_RELEASE_PKT(m);
106329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1064f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (EINVAL);
106529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
106629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp6 = (struct in6pcb *)inp;
106729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/*
106829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * For the TCP model we may get a NULL addr, if we are a connected
106929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * socket thats ok.
107029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 */
107129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) &&
107229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (addr == NULL)) {
107329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		goto connected_type;
107429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
107529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (addr == NULL) {
107629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_RELEASE_PKT(m);
107729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (control) {
107829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_RELEASE_PKT(control);
107929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			control = NULL;
108029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
108129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EDESTADDRREQ);
108229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (EDESTADDRREQ);
108329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
108429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
108529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin6 = (struct sockaddr_in6 *)addr;
108629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (SCTP_IPV6_V6ONLY(inp6)) {
108729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/*
108829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * if IPV6_V6ONLY flag, we discard datagrams destined to a
108929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * v4 addr or v4-mapped addr
109029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 */
109129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (addr->sa_family == AF_INET) {
109229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1093f840325bb9bca0f8732b3f8179ce54fa594160abtuexen			return (EINVAL);
109429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
109529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
109629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1097f840325bb9bca0f8732b3f8179ce54fa594160abtuexen			return (EINVAL);
109829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
109929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
110029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1101202f563d266291cbdec3bacf7844172ebfabed95t		struct sockaddr_in sin;
110229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
1103202f563d266291cbdec3bacf7844172ebfabed95t		/* convert v4-mapped into v4 addr and send */
1104202f563d266291cbdec3bacf7844172ebfabed95t		in6_sin6_2_sin(&sin, sin6);
1105202f563d266291cbdec3bacf7844172ebfabed95t		return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin, control, p));
110629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
110729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif				/* INET */
110829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenconnected_type:
110929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* now what about control */
111029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (control) {
111129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (inp->control) {
111229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_PRINTF("huh? control set?\n");
111329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_RELEASE_PKT(inp->control);
111429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			inp->control = NULL;
111529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
111629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		inp->control = control;
111729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
111829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* Place the data */
111929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (inp->pkt) {
112029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_BUF_NEXT(inp->pkt_last) = m;
112129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		inp->pkt_last = m;
112229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	} else {
112329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		inp->pkt_last = inp->pkt = m;
112429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
112529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (
112629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__)
112729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* FreeBSD and MacOSX uses a flag passed */
112829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    ((flags & PRUS_MORETOCOME) == 0)
112929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
113029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    1			/* Open BSD does not have any "more to come"
113129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				 * indication */
113229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
113329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    ) {
113429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/*
113529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * note with the current version this code will only be used
113629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * by OpenBSD, NetBSD and FreeBSD have methods for
113729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * re-defining sosend() to use sctp_sosend().  One can
113829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * optionaly switch back to this code (by changing back the
113929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * defininitions but this is not advisable.
114029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 */
114129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		int ret;
114229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
114329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
114429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		inp->pkt = NULL;
114529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		inp->control = NULL;
114629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (ret);
114729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	} else {
114829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (0);
114929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
115029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
115129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
115229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
115329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
115429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
115529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
115629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
115729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__FreeBSD__) || defined(__APPLE__)
115829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
115929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
116029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
116129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Panda__)
116229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
116329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_connect(struct socket *so, struct sockaddr *addr, void *p)
116429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
116529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Windows__)
116629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
116729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
116829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
11690612043f643c9b26245564c05defca64d472060etuexen#elif defined(__Userspace__)
117029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
117129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_connect(struct socket *so, struct sockaddr *addr)
117229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
117329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	void *p = NULL;
117429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
117529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
117629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p)
117729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
117829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr *addr = mtod(nam, struct sockaddr *);
117929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
118029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	uint32_t vrf_id;
118129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int error = 0;
118229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_inpcb *inp;
118329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_tcb *stcb;
118429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
1185590ebded4dce1066b7845150a337c0bd8a00d843t	struct in6pcb *inp6;
118629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in6 *sin6;
1187bfb1bf7e665a02b48026482bf33d05c83dfad73bt	union sctp_sockstore store;
118829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
118929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
1190590ebded4dce1066b7845150a337c0bd8a00d843t#ifdef INET
119129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp6 = (struct in6pcb *)so->so_pcb;
1192590ebded4dce1066b7845150a337c0bd8a00d843t#endif
119329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
11942fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
119529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
119629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (ECONNRESET);	/* I made the same as TCP since we are
119729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen					 * not setup? */
119829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
119929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (addr == NULL) {
120029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
120129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (EINVAL);
120229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
120329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if !defined(__Windows__)
120429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	switch (addr->sa_family) {
120529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
120629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case AF_INET:
1207f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
120829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (addr->sa_len != sizeof(struct sockaddr_in)) {
120929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
121029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			return (EINVAL);
121129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
121229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
121329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
121429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
121529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET6
121629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case AF_INET6:
1217f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
121829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
121929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
122029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			return (EINVAL);
122129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
122229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
122329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
122429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
122529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	default:
122629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
122729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (EINVAL);
122829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
122929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
123029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
123129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	vrf_id = inp->def_vrf_id;
123229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_ASOC_CREATE_LOCK(inp);
123329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_INP_RLOCK(inp);
123429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
123529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    SCTP_PCB_FLAGS_UNBOUND) {
123629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* Bind a ephemeral port */
123729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_INP_RUNLOCK(inp);
123829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp6_bind(so, NULL, p);
123929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (error) {
124029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_ASOC_CREATE_UNLOCK(inp);
124129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
124229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			return (error);
124329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
124429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_INP_RLOCK(inp);
124529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
124629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
124729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
124829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* We are already connected AND the TCP model */
124929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_INP_RUNLOCK(inp);
125029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_ASOC_CREATE_UNLOCK(inp);
125129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EADDRINUSE);
125229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (EADDRINUSE);
125329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
125429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
125529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin6 = (struct sockaddr_in6 *)addr;
125629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (SCTP_IPV6_V6ONLY(inp6)) {
125729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/*
125829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * if IPV6_V6ONLY flag, ignore connections destined to a v4
125929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * addr or v4-mapped addr
126029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 */
126129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (addr->sa_family == AF_INET) {
126229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_INP_RUNLOCK(inp);
126329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_ASOC_CREATE_UNLOCK(inp);
126429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1265f840325bb9bca0f8732b3f8179ce54fa594160abtuexen			return (EINVAL);
126629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
126729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
126829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_INP_RUNLOCK(inp);
126929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_ASOC_CREATE_UNLOCK(inp);
127029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1271f840325bb9bca0f8732b3f8179ce54fa594160abtuexen			return (EINVAL);
127229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
127329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
127429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1275202f563d266291cbdec3bacf7844172ebfabed95t		/* convert v4-mapped into v4 addr */
1276bfb1bf7e665a02b48026482bf33d05c83dfad73bt		in6_sin6_2_sin(&store.sin, sin6);
1277bfb1bf7e665a02b48026482bf33d05c83dfad73bt		addr = &store.sa;
127829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
127929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif				/* INET */
128029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* Now do we connect? */
128129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
128229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		stcb = LIST_FIRST(&inp->sctp_asoc_list);
128329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (stcb) {
128429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_TCB_UNLOCK(stcb);
128529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
128629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_INP_RUNLOCK(inp);
128729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	} else {
128829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_INP_RUNLOCK(inp);
128929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_INP_WLOCK(inp);
129029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_INP_INCR_REF(inp);
129129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_INP_WUNLOCK(inp);
129229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
129329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (stcb == NULL) {
129429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_INP_WLOCK(inp);
129529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_INP_DECR_REF(inp);
129629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_INP_WUNLOCK(inp);
129729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
129829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
129929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
130029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (stcb != NULL) {
130129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* Already have or am bring up an association */
130229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_ASOC_CREATE_UNLOCK(inp);
130329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_TCB_UNLOCK(stcb);
130429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EALREADY);
130529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (EALREADY);
130629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
130729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* We are GOOD to go */
130829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
130929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_ASOC_CREATE_UNLOCK(inp);
131029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (stcb == NULL) {
131129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* Gak! no memory */
131229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (error);
131329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
131429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
131529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
131629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* Set the connected flag so we can queue data */
131729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		soisconnecting(so);
131829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
131929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
132029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
132129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
132229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* initialize authentication parameters for the assoc */
132329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_initialize_auth_params(inp, stcb);
132429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
132529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
132629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_TCB_UNLOCK(stcb);
1327f840325bb9bca0f8732b3f8179ce54fa594160abtuexen	return (error);
132829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
132929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
133029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
133129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
133229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_getaddr(struct socket *so, struct sockaddr **addr)
133329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
133429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in6 *sin6;
133529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Panda__)
133629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_getaddr(struct socket *so, struct sockaddr *addr)
133729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
133829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
133929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
134029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_getaddr(struct socket *so, struct mbuf *nam)
134129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
134229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *);
134329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
134429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_inpcb *inp;
134529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	uint32_t vrf_id;
134629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_ifa *sctp_ifa;
134729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
134829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef SCTP_KAME
134929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int error;
135029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif /* SCTP_KAME */
135129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
135229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/*
135329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 * Do the malloc first in case it blocks.
135429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	 */
135529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
135629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof(*sin6));
135729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (sin6 == NULL)
1358f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (ENOMEM);
135929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Panda__)
136029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	bzero(sin6, sizeof(*sin6));
136129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
136229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_BUF_LEN(nam) = sizeof(*sin6);
136329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	bzero(sin6, sizeof(*sin6));
136429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
136529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin6->sin6_family = AF_INET6;
13667b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
136729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin6->sin6_len = sizeof(*sin6);
136829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
136929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
137029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
137129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (inp == NULL) {
137229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
137329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_FREE_SONAME(sin6);
137429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
137529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1376f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (ECONNRESET);
137729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
137829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_INP_RLOCK(inp);
137929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin6->sin6_port = inp->sctp_lport;
138029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
138129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* For the bound all case you get back 0 */
138229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
138329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			struct sctp_tcb *stcb;
138429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			struct sockaddr_in6 *sin_a6;
138529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			struct sctp_nets *net;
138629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			int fnd;
138729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			stcb = LIST_FIRST(&inp->sctp_asoc_list);
138829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (stcb == NULL) {
138929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				goto notConn6;
139029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
139129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			fnd = 0;
139229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			sin_a6 = NULL;
139329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
139429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
139529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				if (sin_a6 == NULL)
139629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen					/* this will make coverity happy */
139729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen					continue;
139829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
139929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				if (sin_a6->sin6_family == AF_INET6) {
140029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen					fnd = 1;
140129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen					break;
140229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				}
140329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
140429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if ((!fnd) || (sin_a6 == NULL)) {
140529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				/* punt */
140629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				goto notConn6;
140729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
140829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			vrf_id = inp->def_vrf_id;
140929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			sctp_ifa = sctp_source_address_selection(inp, stcb, (sctp_route_t *)&net->ro, net, 0, vrf_id);
141029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (sctp_ifa) {
141129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				sin6->sin6_addr = sctp_ifa->address.sin6.sin6_addr;
141229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
141329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		} else {
141429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			/* For the bound all case you get back 0 */
141529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	notConn6:
141629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
141729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
141829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	} else {
141929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* Take the first IPv6 address in the list */
142029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		struct sctp_laddr *laddr;
142129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		int fnd = 0;
142229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
142329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
142429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			if (laddr->ifa->address.sa.sa_family == AF_INET6) {
142529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				struct sockaddr_in6 *sin_a;
142629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
1427bfb1bf7e665a02b48026482bf33d05c83dfad73bt				sin_a = &laddr->ifa->address.sin6;
142829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				sin6->sin6_addr = sin_a->sin6_addr;
142929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				fnd = 1;
143029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen				break;
143129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			}
143229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
143329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (!fnd) {
143429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
143529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_FREE_SONAME(sin6);
143629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
143729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_INP_RUNLOCK(inp);
143829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1439f840325bb9bca0f8732b3f8179ce54fa594160abtuexen			return (ENOENT);
144029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
144129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
144229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_INP_RUNLOCK(inp);
144329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* Scoping things for v6 */
144429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef SCTP_EMBEDDED_V6_SCOPE
144529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef SCTP_KAME
144629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if ((error = sa6_recoverscope(sin6)) != 0) {
144729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_FREE_SONAME(sin6);
144829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (error);
144929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
145029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
145129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
145229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* skip ifp check below */
145329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		in6_recoverscope(sin6, &sin6->sin6_addr, NULL);
145429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	else
145529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		sin6->sin6_scope_id = 0;	/* XXX */
145629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif /* SCTP_KAME */
145729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
145829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
145929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	(*addr) = (struct sockaddr *)sin6;
146029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
146129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	return (0);
146229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
146329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
146429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
146529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
146629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_peeraddr(struct socket *so, struct sockaddr **addr)
146729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
1468845436a72b5767f30403c3b77c457488703143a9tuexen	struct sockaddr_in6 *sin6;
146929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Panda__)
147029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_peeraddr(struct socket *so, struct sockaddr *addr)
147129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
147229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
147329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
147429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_peeraddr(struct socket *so, struct mbuf *nam)
147529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
147629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *);
147729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
147829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int fnd;
147929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr_in6 *sin_a6;
148029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_inpcb *inp;
148129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_tcb *stcb;
148229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sctp_nets *net;
148329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef SCTP_KAME
148429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int error;
1485f840325bb9bca0f8732b3f8179ce54fa594160abtuexen#endif
148629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
1487f840325bb9bca0f8732b3f8179ce54fa594160abtuexen	/* Do the malloc first in case it blocks. */
148829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
148929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
149029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (sin6 == NULL)
149129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (ENOMEM);
149229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Panda__)
1493f840325bb9bca0f8732b3f8179ce54fa594160abtuexen	memset(sin6, 0, sizeof(*sin6));
149429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
149529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_BUF_LEN(nam) = sizeof(*sin6);
1496f840325bb9bca0f8732b3f8179ce54fa594160abtuexen	memset(sin6, 0, sizeof(*sin6));
149729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
149829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin6->sin6_family = AF_INET6;
14997b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
150029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sin6->sin6_len = sizeof(*sin6);
150129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
150229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
150329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
1504f840325bb9bca0f8732b3f8179ce54fa594160abtuexen	if ((inp == NULL) ||
1505f840325bb9bca0f8732b3f8179ce54fa594160abtuexen	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
1506f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		/* UDP type and listeners will drop out here */
150729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
150829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_FREE_SONAME(sin6);
150929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
1510f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
1511f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (ENOTCONN);
151229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
151329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_INP_RLOCK(inp);
151429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	stcb = LIST_FIRST(&inp->sctp_asoc_list);
151529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (stcb) {
151629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_TCB_LOCK(stcb);
151729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
151829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_INP_RUNLOCK(inp);
151929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (stcb == NULL) {
152029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
152129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_FREE_SONAME(sin6);
152229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
152329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1524f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (ECONNRESET);
152529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
152629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	fnd = 0;
152729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
152829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
152929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (sin_a6->sin6_family == AF_INET6) {
153029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			fnd = 1;
153129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			sin6->sin6_port = stcb->rport;
153229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			sin6->sin6_addr = sin_a6->sin6_addr;
153329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			break;
153429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
153529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
153629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	SCTP_TCB_UNLOCK(stcb);
153729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (!fnd) {
153829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* No IPv4 address */
153929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
154029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_FREE_SONAME(sin6);
154129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
154229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1543f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (ENOENT);
154429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
154529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef SCTP_EMBEDDED_V6_SCOPE
154629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef SCTP_KAME
154729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if ((error = sa6_recoverscope(sin6)) != 0)
154829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (error);
154929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
155029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	in6_recoverscope(sin6, &sin6->sin6_addr, NULL);
155129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif /* SCTP_KAME */
155229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
155329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
155429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	*addr = (struct sockaddr *)sin6;
155529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
155629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	return (0);
155729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
155829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
155929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
156029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
156129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
156229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
156329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
156429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr *addr;
156529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
156629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Panda__)
156729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
156829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_in6getaddr(struct socket *so, struct sockaddr *nam, uint32_t *namelen)
156929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
157029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr *addr = nam;
15718a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen#elif defined(__Userspace__)
15728a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexenint
15738a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexensctp6_in6getaddr(struct socket *so, struct mbuf *nam)
15748a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen{
1575e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET
15768a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen	struct sockaddr *addr = mtod(nam, struct sockaddr *);
15778a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen#endif
157829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
157929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
158029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_in6getaddr(struct socket *so, struct mbuf *nam)
158129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
1582e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET
158329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr *addr = mtod(nam, struct sockaddr *);
158429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
158562652de4033658198a44c989a8396f0461be889btuexen#endif
158629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct in6pcb *inp6 = sotoin6pcb(so);
158729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int error;
158829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
158929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (inp6 == NULL) {
159029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1591f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (EINVAL);
159229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
159329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
159429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* allow v6 addresses precedence */
159529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	error = sctp6_getaddr(so, nam);
159629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
159729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (error) {
159829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* try v4 next if v6 failed */
159929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp_ingetaddr(so, nam);
160029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (error) {
160129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			return (error);
160229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
160329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
160429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		addr = *nam;
160529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
160629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* if I'm V6ONLY, convert it to v4-mapped */
160729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (SCTP_IPV6_V6ONLY(inp6)) {
160829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			struct sockaddr_in6 sin6;
160929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
161029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
161129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
161229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
161329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
161429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
161529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__Panda__)
161629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	*namelen = nam->sa_len;
161729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
161829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	return (error);
161929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
162029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
162129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
162229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
162329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstatic int
162429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
162529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
162629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
162729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr *addr;
162829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
162929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif defined(__Panda__)
163029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
163129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_getpeeraddr(struct socket *so, struct sockaddr *nam, uint32_t *namelen)
163229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
163329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr *addr = (struct sockaddr *)nam;
16348a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen#elif defined(__Userspace__)
16358a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexenint
16368a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexensctp6_getpeeraddr(struct socket *so, struct mbuf *nam)
16378a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen{
1638e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET
16398a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen	struct sockaddr *addr = mtod(nam, struct sockaddr *);
16408a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexen#endif
164129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
16428a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexenstatic
16438a5b814e559643cabe8ac7e88e0b747ea0a76fe3tuexenint
164429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_getpeeraddr(struct socket *so, struct mbuf *nam)
164529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
1646e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET
164729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct sockaddr *addr = mtod(nam, struct sockaddr *);
164862652de4033658198a44c989a8396f0461be889btuexen#endif
164929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
165029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
165129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct in6pcb *inp6 = sotoin6pcb(so);
165229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int error;
165329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
165429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (inp6 == NULL) {
165529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1656f840325bb9bca0f8732b3f8179ce54fa594160abtuexen		return (EINVAL);
165729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
165829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
165929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	/* allow v6 addresses precedence */
166029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	error = sctp6_peeraddr(so, nam);
166129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET
166229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (error) {
166329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* try v4 next if v6 failed */
166429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp_peeraddr(so, nam);
166529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (error) {
166629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			return (error);
166729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
166829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
166929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		addr = *nam;
167029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
167129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* if I'm V6ONLY, convert it to v4-mapped */
167229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (SCTP_IPV6_V6ONLY(inp6)) {
167329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			struct sockaddr_in6 sin6;
167429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
167529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
167629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
167729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
167829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
167929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
168029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__Panda__)
168129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	*namelen = nam->sa_len;
168229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
1683f840325bb9bca0f8732b3f8179ce54fa594160abtuexen	return (error);
168429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
168529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
168629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
168729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenstruct pr_usrreqs sctp6_usrreqs = {
16887fbcb406549bdf370031d2ad5befb44e39b95ffft#if defined(__FreeBSD__)
168929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_abort = sctp6_abort,
169029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_accept = sctp_accept,
169129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_attach = sctp6_attach,
169229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_bind = sctp6_bind,
169329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_connect = sctp6_connect,
169429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_control = in6_control,
169529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#if __FreeBSD_version >= 690000
169629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_close = sctp6_close,
169729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_detach = sctp6_close,
169829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_sopoll = sopoll_generic,
1699000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	.pru_flush = sctp_flush,
170029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#else
170129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_detach = sctp6_detach,
170229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_sopoll = sopoll,
170329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
170429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_disconnect = sctp6_disconnect,
170529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_listen = sctp_listen,
170629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_peeraddr = sctp6_getpeeraddr,
170729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_send = sctp6_send,
170829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_shutdown = sctp_shutdown,
170929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_sockaddr = sctp6_in6getaddr,
171029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_sosend = sctp_sosend,
171129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	.pru_soreceive = sctp_soreceive
17127fbcb406549bdf370031d2ad5befb44e39b95ffft#elif defined(__APPLE__)
17137fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_abort = sctp6_abort,
17147fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_accept = sctp_accept,
17157fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_attach = sctp6_attach,
17167fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_bind = sctp6_bind,
17177fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_connect = sctp6_connect,
17187fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_connect2 = pru_connect2_notsupp,
17197fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_control = in6_control,
17207fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_detach = sctp6_detach,
17217fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_disconnect = sctp6_disconnect,
17227fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_listen = sctp_listen,
17237fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_peeraddr = sctp6_getpeeraddr,
17247fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_rcvd = NULL,
17257fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_rcvoob = pru_rcvoob_notsupp,
17267fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_send = sctp6_send,
17277fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sense = pru_sense_null,
17287fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_shutdown = sctp_shutdown,
17297fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sockaddr = sctp6_in6getaddr,
17307fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sosend = sctp_sosend,
17317fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_soreceive = sctp_soreceive,
1732e2828360ea9cf8951730d46f5c14626c9425cb30t	.pru_sopoll = sopoll
17337fbcb406549bdf370031d2ad5befb44e39b95ffft#elif defined(__Windows__)
173429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp6_abort,
173529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_accept,
173629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp6_attach,
173729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp6_bind,
173829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp6_connect,
173929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	pru_connect2_notsupp,
174029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	NULL,
174129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	NULL,
174229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp6_disconnect,
174329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_listen,
174429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp6_getpeeraddr,
174529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	NULL,
174629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	pru_rcvoob_notsupp,
174729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	NULL,
174829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	pru_sense_null,
174929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_shutdown,
175029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_flush,
175129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp6_in6getaddr,
175229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_sosend,
175329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp_soreceive,
175429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sopoll_generic,
175529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	NULL,
175629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	sctp6_close
175729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
175829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen};
175929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
176029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#elif !defined(__Panda__) && !defined(__Userspace__)
176129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexenint
176229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexensctp6_usrreq(so, req, m, nam, control, p)
176329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct socket *so;
176429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int req;
176529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct mbuf *m, *nam, *control;
176629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	struct proc *p;
176729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen{
176829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int s;
176929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int error = 0;
177029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	int family;
177129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	uint32_t vrf_id;
177229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	family = so->so_proto->pr_domain->dom_family;
177329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
177429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	if (req == PRU_CONTROL) {
177529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		switch (family) {
177629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		case PF_INET:
177729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			error = in_control(so, (long)m, (caddr_t)nam,
177829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			    (struct ifnet *)control
177929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			    );
178029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#ifdef INET6
178129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		case PF_INET6:
178229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			error = in6_control(so, (long)m, (caddr_t)nam,
178329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			    (struct ifnet *)control, p);
178429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
178529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		default:
178629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
178729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			error = EAFNOSUPPORT;
178829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
178929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		return (error);
179029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
179129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	switch (req) {
179229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_ATTACH:
179329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp6_attach(so, family, p);
179429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
179529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_DETACH:
179629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp6_detach(so);
179729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
179829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_BIND:
179929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (nam == NULL) {
180029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
180129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			return (EINVAL);
180229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
180329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp6_bind(so, nam, p);
180429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
180529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_LISTEN:
180629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp_listen(so, p);
180729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
180829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_CONNECT:
180929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (nam == NULL) {
181029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
181129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			return (EINVAL);
181229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
181329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp6_connect(so, nam, p);
181429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
181529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_DISCONNECT:
181629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp6_disconnect(so);
181729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
181829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_ACCEPT:
181929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		if (nam == NULL) {
182029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
182129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen			return (EINVAL);
182229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		}
182329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp_accept(so, nam);
182429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
182529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_SHUTDOWN:
182629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp_shutdown(so);
182729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
182829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
182929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_RCVD:
183029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/*
183129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * For OpenBSD and NetBSD, this is real ugly. The (mbuf *)
183229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * nam that is passed (by soreceive()) is the int flags cast
183329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 * as a (mbuf *) yuck!
183429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		 */
183529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp_usr_recvd(so, (int)((long)nam));
183629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
183729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
183829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_SEND:
183929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		/* Flags are ignored */
184029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp6_send(so, 0, m, nam, control, p);
184129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
184229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_ABORT:
184329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp6_abort(so);
184429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
184529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen
184629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_SENSE:
184729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = 0;
184829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
184929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_RCVOOB:
185029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
185129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = EAFNOSUPPORT;
185229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
185329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_SENDOOB:
185429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
185529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = EAFNOSUPPORT;
185629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
185729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_PEERADDR:
185829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp6_getpeeraddr(so, nam);
185929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
186029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_SOCKADDR:
186129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = sctp6_in6getaddr(so, nam);
186229f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
186329f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	case PRU_SLOWTIMO:
186429f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		error = 0;
186529f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
186629f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	default:
186729f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen		break;
186829f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	}
186929f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen	return (error);
187029f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen}
187129f1aa98c8f38d5c1bb1765358f1edd541250d96tuexen#endif
1872c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen#endif
1873