18c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
28c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
3ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
58c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
68c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Redistribution and use in source and binary forms, with or without
78c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * modification, are permitted provided that the following conditions are met:
88c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
98c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) Redistributions of source code must retain the above copyright notice,
100ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    this list of conditions and the following disclaimer.
118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * b) Redistributions in binary form must reproduce the above copyright
138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    notice, this list of conditions and the following disclaimer in
140ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    the documentation and/or other materials provided with the distribution.
158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * c) Neither the name of Cisco Systems, Inc. nor the names of its
178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    contributors may be used to endorse or promote products derived
188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    from this software without specific prior written permission.
198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE POSSIBILITY OF SUCH DAMAGE.
318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__
348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/cdefs.h>
35bfb1bf7e665a02b48026482bf33d05c83dfad73bt__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 271221 2014-09-07 09:06:26Z tuexen $");
368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
37ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen
388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h>
398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__
408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/proc.h>
418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h>
438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_header.h>
448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h>
45e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET6
468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace_os_FreeBSD)
478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet6/sctp6_var.h>
488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h>
518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_output.h>
528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_uio.h>
538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_asconf.h>
548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h>
558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_indata.h>
568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_timer.h>
578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_auth.h>
588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_bsd_addr.h>
596c632b3f6e570981666f8a3ff4be34eaf1735835t#if !defined(__Userspace__)
608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/udp.h>
6181616c6a3e184f46276632dd15aa489cd06d94dftuexen#endif
628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_peeloff.h>
658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* HAVE_SCTP_PEELOFF_SOCKOPT */
668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define APPLE_FILE_NO 7
698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenextern struct sctp_cc_functions sctp_cc_functions[];
728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenextern struct sctp_ss_functions sctp_ss_functions[];
738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
75153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#if defined(__Userspace__)
76b049c47efe2be4692752fdeb90cbc26f5bd3a1c7tuexensctp_init(uint16_t port,
77e6b8257902dfec8b1e5d9b80d5364a78c06777cat          int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df),
78e6b8257902dfec8b1e5d9b80d5364a78c06777cat          void (*debug_printf)(const char *format, ...))
797fbcb406549bdf370031d2ad5befb44e39b95ffft#elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION))
807fbcb406549bdf370031d2ad5befb44e39b95ffftsctp_init(struct protosw *pp SCTP_UNUSED, struct domain *dp SCTP_UNUSED)
81153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#else
828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_init(void)
83153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#endif
848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__Panda__) && !defined(__Userspace__)
868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	u_long sb_max_adj;
878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
88a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
896afa8eeaacc73cac676094ffb23334c1e728c48at#if defined(__Userspace__)
9081616c6a3e184f46276632dd15aa489cd06d94dftuexen#if defined(__Userspace_os_Windows)
919fde21ced28f3314e75a2d90e5dcc7867e2a6b75t#if defined(INET) || defined(INET6)
9281616c6a3e184f46276632dd15aa489cd06d94dftuexen	WSADATA wsaData;
9381616c6a3e184f46276632dd15aa489cd06d94dftuexen
949fde21ced28f3314e75a2d90e5dcc7867e2a6b75t	if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) {
9547a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("WSAStartup failed\n");
9681616c6a3e184f46276632dd15aa489cd06d94dftuexen		exit (-1);
9781616c6a3e184f46276632dd15aa489cd06d94dftuexen	}
989fde21ced28f3314e75a2d90e5dcc7867e2a6b75t#endif
9981616c6a3e184f46276632dd15aa489cd06d94dftuexen	InitializeConditionVariable(&accept_cond);
10081616c6a3e184f46276632dd15aa489cd06d94dftuexen	InitializeCriticalSection(&accept_mtx);
1016afa8eeaacc73cac676094ffb23334c1e728c48at#else
1026afa8eeaacc73cac676094ffb23334c1e728c48at	pthread_cond_init(&accept_cond, NULL);
1036afa8eeaacc73cac676094ffb23334c1e728c48at	pthread_mutex_init(&accept_mtx, NULL);
1046afa8eeaacc73cac676094ffb23334c1e728c48at#endif
10581616c6a3e184f46276632dd15aa489cd06d94dftuexen#endif
1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Initialize and modify the sysctled variables */
1078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_init_sysctls();
1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
1090612043f643c9b26245564c05defca64d472060etuexen#if defined(__Userspace_os_Windows)
11081616c6a3e184f46276632dd15aa489cd06d94dftuexen	srand((unsigned int)time(NULL));
11181616c6a3e184f46276632dd15aa489cd06d94dftuexen#else
11281616c6a3e184f46276632dd15aa489cd06d94dftuexen	srandom(getpid()); /* so inp->sctp_ep.random_numbers are truly random... */
11381616c6a3e184f46276632dd15aa489cd06d94dftuexen#endif
1148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__)
1168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sendspace = SB_MAX;
1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_recvspace = SB_MAX;
1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Userspace__)
1208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_sendspace) = SB_MAX;
1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_recvspace) = SB_RAW;
122153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = port;
1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__)
1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
1278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
1298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Allow a user to take no more than 1/2 the number of clusters or
1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the SB_MAX whichever is smaller for the send window.
1318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sb_max_adj = (u_long)((u_quad_t) (sb_max) * MCLBYTES / (MSIZE + MCLBYTES));
1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
1358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sb_max_adj = (u_long)((u_quad_t) (SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_sendspace) = sb_max_adj;
1398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
1408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (((uint32_t)nmbclusters / 2) * SCTP_DEFAULT_MAXSEGMENT));
1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
1448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now for the recv window, should we take the same amount? or
1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * now I will just copy.
1478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
1488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_VAR(first_time) = 0;
1518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
152a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#if defined(__Userspace__)
153a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#if !defined(__Userspace_os_Windows)
154a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#if defined(INET) || defined(INET6)
155a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	SCTP_BASE_VAR(userspace_route) = -1;
156a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
157a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
158a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#ifdef INET
159a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	SCTP_BASE_VAR(userspace_rawsctp) = -1;
160a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	SCTP_BASE_VAR(userspace_udpsctp) = -1;
161a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
162a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#ifdef INET6
163a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	SCTP_BASE_VAR(userspace_rawsctp6) = -1;
164a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	SCTP_BASE_VAR(userspace_udpsctp6) = -1;
165a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
166a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	SCTP_BASE_VAR(timer_thread_should_exit) = 0;
167b049c47efe2be4692752fdeb90cbc26f5bd3a1c7tuexen	SCTP_BASE_VAR(conn_output) = conn_output;
168e6b8257902dfec8b1e5d9b80d5364a78c06777cat	SCTP_BASE_VAR(debug_printf) = debug_printf;
169a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_pcb_init();
17173e265d74b8dddf404a3200cc2a4b593025158e7tuexen#if defined(__Userspace__)
17273e265d74b8dddf404a3200cc2a4b593025158e7tuexen	sctp_start_timer();
17373e265d74b8dddf404a3200cc2a4b593025158e7tuexen#endif
1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_PACKET_LOGGING)
1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_VAR(packet_log_writers) = 0;
1768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_VAR(packet_log_end) = 0;
1778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE);
1788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
1808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_VAR(sctp_main_timer_ticks) = 0;
1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_start_main_timer();
1827fbcb406549bdf370031d2ad5befb44e39b95ffft	timeout(sctp_delayed_startup, NULL, 1);
1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_finish(void)
1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
1907fbcb406549bdf370031d2ad5befb44e39b95ffft	untimeout(sctp_delayed_startup, NULL);
1918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_over_udp_stop();
1928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_address_monitor_stop();
1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_stop_main_timer();
1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19514d7b0ffb5f8052c2291203059092157c65d3e10tuexen#if defined(__Userspace__)
196c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen#if defined(INET) || defined(INET6)
19714d7b0ffb5f8052c2291203059092157c65d3e10tuexen	recv_thread_destroy();
198c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen#endif
199a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#if !defined(__Userspace_os_Windows)
200a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#if defined(INET) || defined(INET6)
2010d50fd1e0425ccd187b9530411e5675413362f82tuexen	if (SCTP_BASE_VAR(userspace_route) != -1) {
2020d50fd1e0425ccd187b9530411e5675413362f82tuexen		pthread_join(SCTP_BASE_VAR(recvthreadroute), NULL);
2030d50fd1e0425ccd187b9530411e5675413362f82tuexen	}
204a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
205a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
206e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET
2070d50fd1e0425ccd187b9530411e5675413362f82tuexen	if (SCTP_BASE_VAR(userspace_rawsctp) != -1) {
208a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#if defined(__Userspace_os_Windows)
209a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen		WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw), INFINITE);
2100e516dd1fe21e9101c233c725a7ebc2dca6a7d8et		CloseHandle(SCTP_BASE_VAR(recvthreadraw));
211a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#else
212a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen		pthread_join(SCTP_BASE_VAR(recvthreadraw), NULL);
213a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
214a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	}
2150d50fd1e0425ccd187b9530411e5675413362f82tuexen	if (SCTP_BASE_VAR(userspace_udpsctp) != -1) {
216a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#if defined(__Userspace_os_Windows)
217a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen		WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp), INFINITE);
2180e516dd1fe21e9101c233c725a7ebc2dca6a7d8et		CloseHandle(SCTP_BASE_VAR(recvthreadudp));
219a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#else
220a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen		pthread_join(SCTP_BASE_VAR(recvthreadudp), NULL);
221a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
222a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	}
223a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
224e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET6
2250d50fd1e0425ccd187b9530411e5675413362f82tuexen	if (SCTP_BASE_VAR(userspace_rawsctp6) != -1) {
226a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#if defined(__Userspace_os_Windows)
227a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen		WaitForSingleObject(SCTP_BASE_VAR(recvthreadraw6), INFINITE);
2280e516dd1fe21e9101c233c725a7ebc2dca6a7d8et		CloseHandle(SCTP_BASE_VAR(recvthreadraw6));
229a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#else
230a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen		pthread_join(SCTP_BASE_VAR(recvthreadraw6), NULL);
231a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
232a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	}
2330d50fd1e0425ccd187b9530411e5675413362f82tuexen	if (SCTP_BASE_VAR(userspace_udpsctp6) != -1) {
234a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#if defined(__Userspace_os_Windows)
235a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen		WaitForSingleObject(SCTP_BASE_VAR(recvthreadudp6), INFINITE);
2360e516dd1fe21e9101c233c725a7ebc2dca6a7d8et		CloseHandle(SCTP_BASE_VAR(recvthreadudp6));
237a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#else
238a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen		pthread_join(SCTP_BASE_VAR(recvthreadudp6), NULL);
239a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
240a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	}
241a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
242a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	SCTP_BASE_VAR(timer_thread_should_exit) = 1;
243a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#if defined(__Userspace_os_Windows)
244a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	WaitForSingleObject(SCTP_BASE_VAR(timer_thread), INFINITE);
2450e516dd1fe21e9101c233c725a7ebc2dca6a7d8et	CloseHandle(SCTP_BASE_VAR(timer_thread));
246a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#else
247a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen	pthread_join(SCTP_BASE_VAR(timer_thread), NULL);
248a1f4f8b6475213e9fcf527fd5404b74733885f7btuexen#endif
24914d7b0ffb5f8052c2291203059092157c65d3e10tuexen#endif
2508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_pcb_finish();
251334aac245024f2dd2de46c4b8f3b28e833d88592t#if defined(__Userspace__)
252334aac245024f2dd2de46c4b8f3b28e833d88592t#if defined(__Userspace_os_Windows)
253334aac245024f2dd2de46c4b8f3b28e833d88592t	DeleteConditionVariable(&accept_cond);
254334aac245024f2dd2de46c4b8f3b28e833d88592t	DeleteCriticalSection(&accept_mtx);
255334aac245024f2dd2de46c4b8f3b28e833d88592t#else
256334aac245024f2dd2de46c4b8f3b28e833d88592t	pthread_cond_destroy(&accept_cond);
257334aac245024f2dd2de46c4b8f3b28e833d88592t	pthread_mutex_destroy(&accept_mtx);
258334aac245024f2dd2de46c4b8f3b28e833d88592t#endif
259334aac245024f2dd2de46c4b8f3b28e833d88592t#endif
2608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Windows__)
2618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_finish_sysctls();
2626f4c08134ae7f03bbbe3299d3ebcd331e7bf9ad5t#if defined(INET) || defined(INET6)
2636f4c08134ae7f03bbbe3299d3ebcd331e7bf9ad5t	WSACleanup();
2646f4c08134ae7f03bbbe3299d3ebcd331e7bf9ad5t#endif
2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
2710ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
2728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk;
2748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t overhead;
2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Adjust that too */
2778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.smallest_mtu = nxtsz;
2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now off to subtract IP_DF flag if needed */
2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	overhead = IP_HDR_SIZE;
2808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
2818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		overhead += sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
2848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((chk->send_size + overhead) > nxtsz) {
2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
2898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((chk->send_size + overhead) > nxtsz) {
2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * For this guy we also mark for immediate resend
2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * since we sent to big of chunk
2938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->sent < SCTP_DATAGRAM_RESEND) {
2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_flight_size_decrease(chk);
2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_total_flight_decrease(stcb, chk);
2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
2998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->sent != SCTP_DATAGRAM_RESEND) {
3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
3018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk->sent = SCTP_DATAGRAM_RESEND;
3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk->rec.data.doing_fast_retransmit = 0;
3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
3058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
3068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       chk->whoTo->flight_size,
3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       chk->book_size,
3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       (uintptr_t)chk->whoTo,
3098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       chk->rec.data.TSN_seq);
3108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Clear any time so NO RTT is being done */
3128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk->do_rtt = 0;
3138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
31814ba474e7d8520db1b04d650c6a788bdc5dab9e0tuexen#if !defined(__Userspace__)
3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__) || defined(__Windows__)
3208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
3228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_notify_mbuf(struct sctp_inpcb *inp,
3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_tcb *stcb,
3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_nets *net,
3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct ip *ip,
3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctphdr *sh)
3298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct icmp *icmph;
3318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int totsz, tmr_stopped = 0;
3328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t nxtsz;
3338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* protection */
3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (ip == NULL) || (sh == NULL)) {
3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb != NULL) {
3388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* First job is to verify the vtag matches what I would send */
3438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
3448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
3458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
3468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
3488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sizeof(struct ip)));
3498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (icmph->icmp_type != ICMP_UNREACH) {
3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We only care about unreachable */
3518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
3528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
3538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (icmph->icmp_code != ICMP_UNREACH_NEEDFRAG) {
3558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* not a unreachable message due to frag. */
3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
3588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3594bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#if defined(__FreeBSD__) && __FreeBSD_version >= 1000000
3604bda18bd6192b29406d04eeb576f5d5d7bd32fc7t	totsz = ntohs(ip->ip_len);
3614bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#else
3628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	totsz = ip->ip_len;
3634bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#endif
3648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	nxtsz = ntohs(icmph->icmp_nextmtu);
3668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (nxtsz == 0) {
3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
3688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * old type router that does not tell us what the next size
3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * mtu is. Rats we will have to guess (in a educated fashion
3708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * of course)
3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
3728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		nxtsz = sctp_get_prev_mtu(totsz);
3738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Stop any PMTU timer */
3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr_stopped = 1;
3778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
3788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_FROM_SCTP_USRREQ+SCTP_LOC_1);
3798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Adjust destination size limit */
3818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->mtu > nxtsz) {
3828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->mtu = nxtsz;
3838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->port) {
3848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->mtu -= sizeof(struct udphdr);
3858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now what about the ep? */
3888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.smallest_mtu > nxtsz) {
3890ac02f34d6041cd0018437596a5a9a94685e6919tuexen		sctp_pathmtu_adjustment(stcb, nxtsz);
3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (tmr_stopped)
3928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
3958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
3988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_notify(struct sctp_inpcb *inp,
3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct ip *ip,
4008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctphdr *sh,
4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sockaddr *to,
4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_tcb *stcb,
4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_nets *net)
4048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
4050612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *so;
4078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct icmp *icmph;
4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41147674b651417d493ff4e0318113fd7beeef119dbtuexen	/* protection */
4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
4138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (sh == NULL) || (to == NULL)) {
4148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb)
4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* First job is to verify the vtag matches what I would send */
4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
4228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       sizeof(struct ip)));
4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (icmph->icmp_type != ICMP_UNREACH) {
4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We only care about unreachable */
4288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
4298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
4328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_HOST) ||
4338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
4378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
43822a33a1debfe70529be4aa018a2912bfe5dcd8dat#if defined(__Panda__)
4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_ADMIN)) {
44022a33a1debfe70529be4aa018a2912bfe5dcd8dat#elif defined(__Userspace_os_NetBSD)
44122a33a1debfe70529be4aa018a2912bfe5dcd8dat	    (icmph->icmp_code == ICMP_UNREACH_ADMIN_PROHIBIT)) {
4428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Hmm reachablity problems we must examine closely. If its
4488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * not reachable, we may have lost a network. Or if there is
4498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * NO protocol at the other end named SCTP. well we consider
4508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * it a OOTB abort.
4518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->dest_state & SCTP_ADDR_REACHABLE) {
4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Ok that destination is NOT reachable */
4548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->dest_state &= ~SCTP_ADDR_REACHABLE;
4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->dest_state &= ~SCTP_ADDR_PF;
4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
45747674b651417d493ff4e0318113fd7beeef119dbtuexen					stcb, 0,
4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(void *)net, SCTP_SO_NOT_LOCKED);
4598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
4618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else  if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
4628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (icmph->icmp_code == ICMP_UNREACH_PORT)) {
4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Here the peer is either playing tricks on us,
4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * including an address that belongs to someone who
4668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * does not support SCTP OR was a userland
4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * implementation that shutdown and now is dead. In
4688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * either case treat it like a OOTB abort with no
4698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * TCB
4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
47147674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
4720612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so = SCTP_INP_SO(inp);
4748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
4758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_LOCK(so, 1);
4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
4788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_2);
4810612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_UNLOCK(so, 1);
4838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/
4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no need to unlock here, since the TCB is gone */
4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
4906c632b3f6e570981666f8a3ff4be34eaf1735835t#endif
4916c632b3f6e570981666f8a3ff4be34eaf1735835t#endif
4928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
4948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__Panda__) && !defined(__Userspace__)
4958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
4968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
4978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
4988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid *
4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_ctlinput(cmd, sa, vip)
5018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int cmd;
5028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *sa;
5038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	void *vip;
5048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
5058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct ip *ip = vip;
5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctphdr *sh;
5078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* FIX, for non-bsd is this right? */
5098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf_id = SCTP_DEFAULT_VRFID;
5108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sa->sa_family != AF_INET ||
5118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
5138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
5168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (PRC_IS_REDIRECT(cmd)) {
5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ip = 0;
5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
5218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
5248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ip) {
5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_inpcb *inp = NULL;
5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_tcb *stcb = NULL;
5308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net = NULL;
5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in to, from;
5328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2));
5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero(&to, sizeof(to));
5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero(&from, sizeof(from));
5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		from.sin_family = to.sin_family = AF_INET;
5377b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
5388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		from.sin_len = to.sin_len = sizeof(to);
5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		from.sin_port = sh->src_port;
5418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		from.sin_addr = ip->ip_src;
5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to.sin_port = sh->dest_port;
5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to.sin_addr = ip->ip_dst;
5448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
5468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * 'to' holds the dest of the packet that failed to be sent.
5478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * 'from' holds our local endpoint address. Thus we reverse
5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the to and the from in the lookup.
5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
550e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen		stcb = sctp_findassociation_addr_sa((struct sockaddr *)&to,
551e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen		    (struct sockaddr *)&from,
5528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    &inp, &net, 1, vrf_id);
5538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
5548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (cmd != PRC_MSGSIZE) {
5558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_notify(inp, ip, sh,
5568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (struct sockaddr *)&to, stcb,
5578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    net);
5588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
5598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* handle possible ICMP size messages */
5608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_notify_mbuf(inp, stcb, net, ip, sh);
5618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
5638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 500000
5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * XXX must be fixed for 5.x and higher, leave for
5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * 4.x
5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
5688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (PRC_IS_REDIRECT(cmd) && inp) {
5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				in_rtchange((struct inpcb *)inp,
5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    inetctlerrmap[cmd]);
5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((stcb == NULL) && (inp != NULL)) {
5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* reduce ref-count */
5758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
5768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
5778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
5788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
5808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
5818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return;
5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
5878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (NULL);
5888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__)
5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_getcred(SYSCTL_HANDLER_ARGS)
5968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct xucred xuc;
5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in addrs[2];
5998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
6008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb;
6028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error;
6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* FIX, for non-bsd is this right? */
6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf_id = SCTP_DEFAULT_VRFID;
6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version > 602000
6098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = priv_check(req->td, PRIV_NETINET_GETCRED);
6108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif __FreeBSD_version >= 500000
6128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = suser(req->td);
6138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
6148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = suser(req->p);
6158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
6168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error)
6178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (error);
6188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = SYSCTL_IN(req, addrs, sizeof(addrs));
6208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error)
6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (error);
6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
623e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	stcb = sctp_findassociation_addr_sa(sintosa(&addrs[1]),
624e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	    sintosa(&addrs[0]),
6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    &inp, &net, 1, vrf_id);
6268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
6278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp != NULL) && (stcb == NULL)) {
6288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* reduce ref-count */
6298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WLOCK(inp);
6308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_DECR_REF(inp);
6318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto cred_can_cont;
6328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = ENOENT;
6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
6398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* We use the write lock here, only
6408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * since in the error leg we need it.
6418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * If we used RLOCK, then we would have
6428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * to wlock/decr/unlock/rlock. Which
6438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * in theory could create a hole. Better
6448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * to use higher wlock.
6458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
6468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_WLOCK(inp);
6478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen cred_can_cont:
6488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
6498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error) {
6508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
6518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
6528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cru2x(inp->sctp_socket->so_cred, &xuc);
6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_WUNLOCK(inp);
6558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenout:
6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
6598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenSYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
6618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* #if defined(__FreeBSD__) */
6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
6668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__) || defined(__Windows__) || defined(__Userspace__)
6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__FreeBSD__) && __FreeBSD_version > 690000
6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
6708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
6718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
6738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_abort(struct socket *so)
6748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
6758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
6768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t flags;
6778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
6792fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
6808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version > 690000
6818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
6828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
6838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
684b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
6858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
6868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_must_try_again:
6898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	flags = inp->sctp_flags;
6908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING
6918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_log_closing(inp, NULL, 17);
6928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
6938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
6958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING
6968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_closing(inp, NULL, 16);
6978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
6988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
6998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
7008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_LOCK(so);
7018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SB_CLEAR(so->so_snd);
7028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* same for the rcv ones, they are only
7038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * here for the accounting/select.
7048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SB_CLEAR(so->so_rcv);
7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
7088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_usecount--;
7098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
7108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Now null out the reference, we are completely detached. */
7118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_pcb = NULL;
7128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_UNLOCK(so);
7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
7158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		flags = inp->sctp_flags;
7168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
7178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto sctp_must_try_again;
7188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version > 690000
7218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return;
7228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
723b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (0);
7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7270612043f643c9b26245564c05defca64d472060etuexen#if defined(__Panda__) || defined(__Userspace__)
7288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
7298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
7318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
7330ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
7348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__) || defined(__Userspace__)
7350ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
7368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__)
7370ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_attach(struct socket *so, int proto SCTP_UNUSED, PKTHREAD p SCTP_UNUSED)
7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
7390ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED)
7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct inpcb *ip_inp;
7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error;
7458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__Panda__) && !defined(__Userspace__)
7468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id = SCTP_DEFAULT_VRFID;
7478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef IPSEC
7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t flags;
7508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
7538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp != 0) {
7548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
755b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
7568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
7588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
760b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			return (error);
7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = sctp_inpcb_alloc(so, vrf_id);
7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error) {
765b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (error);
7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_WLOCK(inp);
7698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;	/* I'm not v6! */
7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ip_inp = &inp->ip_inp.inp;
7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ip_inp->inp_vflag |= INP_IPV4;
7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef IPSEC
7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__APPLE__))
7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = ipsec_init_policy(so, &ip_inp->inp_sp);
7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING
7778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_log_closing(inp, NULL, 17);
7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error != 0) {
7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	try_again:
7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		flags = inp->sctp_flags;
7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING
7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_closing(inp, NULL, 15);
7868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WUNLOCK(inp);
7888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
7898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
7908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
7918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			flags = inp->sctp_flags;
7928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((flags &  SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
7938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto try_again;
7948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
7978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
798b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (error);
7998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* IPSEC */
8028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_WUNLOCK(inp);
803b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (0);
8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8057a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
8067a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
8077a9f1edd34bf82c194a2f9d0c64394f431175138tuexenstatic int
8087a9f1edd34bf82c194a2f9d0c64394f431175138tuexensctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
8097a9f1edd34bf82c194a2f9d0c64394f431175138tuexen{
8107a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#elif defined(__FreeBSD__) || defined(__APPLE__)
8117a9f1edd34bf82c194a2f9d0c64394f431175138tuexenstatic int
8127a9f1edd34bf82c194a2f9d0c64394f431175138tuexensctp_bind(struct socket *so, struct sockaddr *addr, struct proc *p) {
8137a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#elif defined(__Panda__) || defined(__Userspace__)
8147a9f1edd34bf82c194a2f9d0c64394f431175138tuexenint
8157a9f1edd34bf82c194a2f9d0c64394f431175138tuexensctp_bind(struct socket *so, struct sockaddr *addr) {
8167a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	void *p = NULL;
8177a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#elif defined(__Windows__)
8187a9f1edd34bf82c194a2f9d0c64394f431175138tuexenstatic int
8197a9f1edd34bf82c194a2f9d0c64394f431175138tuexensctp_bind(struct socket *so, struct sockaddr *addr, PKTHREAD p) {
8207a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#else
8217a9f1edd34bf82c194a2f9d0c64394f431175138tuexenstatic int
8227a9f1edd34bf82c194a2f9d0c64394f431175138tuexensctp_bind(struct socket *so, struct mbuf *nam, struct proc *p)
8237a9f1edd34bf82c194a2f9d0c64394f431175138tuexen{
8247a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
8257a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
8267a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
8279ac77419b79fa1b61bed4326c4ef825a19335704t	struct sctp_inpcb *inp;
8287a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
8299ac77419b79fa1b61bed4326c4ef825a19335704t	inp = (struct sctp_inpcb *)so->so_pcb;
8309ac77419b79fa1b61bed4326c4ef825a19335704t	if (inp == NULL) {
8317a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8327a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		return (EINVAL);
8337a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
8349ac77419b79fa1b61bed4326c4ef825a19335704t	if (addr != NULL) {
835f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
8369ac77419b79fa1b61bed4326c4ef825a19335704t		if ((addr->sa_family != AF_INET) ||
8379ac77419b79fa1b61bed4326c4ef825a19335704t		    (addr->sa_len != sizeof(struct sockaddr_in))) {
8389ac77419b79fa1b61bed4326c4ef825a19335704t#else
8399ac77419b79fa1b61bed4326c4ef825a19335704t		if (addr->sa_family != AF_INET) {
8407a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
8419ac77419b79fa1b61bed4326c4ef825a19335704t			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8429ac77419b79fa1b61bed4326c4ef825a19335704t			return (EINVAL);
8439ac77419b79fa1b61bed4326c4ef825a19335704t		}
8447a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
8459ac77419b79fa1b61bed4326c4ef825a19335704t	return (sctp_inpcb_bind(so, addr, NULL, p));
8467a9f1edd34bf82c194a2f9d0c64394f431175138tuexen}
8477a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
8487a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
849dad58c401bed435161454933c0b0a6d27ac03e48tuexen#if defined(__Userspace__)
850dad58c401bed435161454933c0b0a6d27ac03e48tuexen
851dad58c401bed435161454933c0b0a6d27ac03e48tuexenint
852dad58c401bed435161454933c0b0a6d27ac03e48tuexensctpconn_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
853dad58c401bed435161454933c0b0a6d27ac03e48tuexen{
854dad58c401bed435161454933c0b0a6d27ac03e48tuexen	struct sctp_inpcb *inp;
855dad58c401bed435161454933c0b0a6d27ac03e48tuexen	struct inpcb *ip_inp;
856dad58c401bed435161454933c0b0a6d27ac03e48tuexen	int error;
857dad58c401bed435161454933c0b0a6d27ac03e48tuexen
858dad58c401bed435161454933c0b0a6d27ac03e48tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
859dad58c401bed435161454933c0b0a6d27ac03e48tuexen	if (inp != NULL) {
860dad58c401bed435161454933c0b0a6d27ac03e48tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
861dad58c401bed435161454933c0b0a6d27ac03e48tuexen		return (EINVAL);
862dad58c401bed435161454933c0b0a6d27ac03e48tuexen	}
863dad58c401bed435161454933c0b0a6d27ac03e48tuexen	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
864dad58c401bed435161454933c0b0a6d27ac03e48tuexen		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
865dad58c401bed435161454933c0b0a6d27ac03e48tuexen		if (error) {
866dad58c401bed435161454933c0b0a6d27ac03e48tuexen			return (error);
867dad58c401bed435161454933c0b0a6d27ac03e48tuexen		}
868dad58c401bed435161454933c0b0a6d27ac03e48tuexen	}
869dad58c401bed435161454933c0b0a6d27ac03e48tuexen	error = sctp_inpcb_alloc(so, vrf_id);
870dad58c401bed435161454933c0b0a6d27ac03e48tuexen	if (error) {
871dad58c401bed435161454933c0b0a6d27ac03e48tuexen		return (error);
872dad58c401bed435161454933c0b0a6d27ac03e48tuexen	}
873dad58c401bed435161454933c0b0a6d27ac03e48tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
874dad58c401bed435161454933c0b0a6d27ac03e48tuexen	SCTP_INP_WLOCK(inp);
8757a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;
8767988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_CONN;
877dad58c401bed435161454933c0b0a6d27ac03e48tuexen	ip_inp = &inp->ip_inp.inp;
87875cd23222c96d5ebe5a9082c57a263f917f1462btuexen	ip_inp->inp_vflag |= INP_CONN;
879dad58c401bed435161454933c0b0a6d27ac03e48tuexen	ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
880dad58c401bed435161454933c0b0a6d27ac03e48tuexen	SCTP_INP_WUNLOCK(inp);
881dad58c401bed435161454933c0b0a6d27ac03e48tuexen	return (0);
882dad58c401bed435161454933c0b0a6d27ac03e48tuexen}
8838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
885dcb94e06c8e8dde2dde9f254e245728c75cdefd7tuexensctpconn_bind(struct socket *so, struct sockaddr *addr)
886dcb94e06c8e8dde2dde9f254e245728c75cdefd7tuexen{
8879ac77419b79fa1b61bed4326c4ef825a19335704t	struct sctp_inpcb *inp;
8888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8899ac77419b79fa1b61bed4326c4ef825a19335704t	inp = (struct sctp_inpcb *)so->so_pcb;
8909ac77419b79fa1b61bed4326c4ef825a19335704t	if (inp == NULL) {
8919ac77419b79fa1b61bed4326c4ef825a19335704t		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
892b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
8938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8949ac77419b79fa1b61bed4326c4ef825a19335704t	if (addr != NULL) {
895f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
8969ac77419b79fa1b61bed4326c4ef825a19335704t		if ((addr->sa_family != AF_CONN) ||
8979ac77419b79fa1b61bed4326c4ef825a19335704t		    (addr->sa_len != sizeof(struct sockaddr_conn))) {
8989ac77419b79fa1b61bed4326c4ef825a19335704t#else
8999ac77419b79fa1b61bed4326c4ef825a19335704t		if (addr->sa_family != AF_CONN) {
9008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9019ac77419b79fa1b61bed4326c4ef825a19335704t			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
9029ac77419b79fa1b61bed4326c4ef825a19335704t			return (EINVAL);
9039ac77419b79fa1b61bed4326c4ef825a19335704t		}
904dcb94e06c8e8dde2dde9f254e245728c75cdefd7tuexen	}
9059ac77419b79fa1b61bed4326c4ef825a19335704t	return (sctp_inpcb_bind(so, addr, NULL, NULL));
9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 690000) || defined(__Windows__) || defined(__Userspace__)
9108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
9118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_close(struct socket *so)
9128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
9138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
9148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t flags;
9158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
9172fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL)
9188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
9198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Inform all the lower layer assoc that we
9218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * are done.
9228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_must_try_again:
9248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	flags = inp->sctp_flags;
9258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING
9268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_log_closing(inp, NULL, 17);
9278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
9298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
930907b9e7d7c75f02c3d1f6c70016127990e8fe648t#if defined(__Userspace__)
931907b9e7d7c75f02c3d1f6c70016127990e8fe648t		if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
932907b9e7d7c75f02c3d1f6c70016127990e8fe648t		    (so->so_rcv.sb_cc > 0)) {
933907b9e7d7c75f02c3d1f6c70016127990e8fe648t#else
9348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
9358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (so->so_rcv.sb_cc > 0)) {
936907b9e7d7c75f02c3d1f6c70016127990e8fe648t#endif
9378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING
9388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_closing(inp, NULL, 13);
9398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
9418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
9428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
9438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING
9448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_closing(inp, NULL, 14);
9458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
9478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
9488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
9498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* The socket is now detached, no matter what
9508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the state of the SCTP association.
9518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
9528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_LOCK(so);
9538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SB_CLEAR(so->so_snd);
9548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* same for the rcv ones, they are only
9558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * here for the accounting/select.
9568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
9578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SB_CLEAR(so->so_rcv);
9588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__)
9608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Now null out the reference, we are completely detached. */
9618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_pcb = NULL;
9628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_UNLOCK(so);
9648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
9658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		flags = inp->sctp_flags;
9668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
9678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto sctp_must_try_again;
9688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
9698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return;
9718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
9728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
9748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
9778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_detach(struct socket *so)
9788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
9798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
9808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t flags;
9818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
9832fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
9848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version > 690000
9858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
9868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
9878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
988b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
9898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen sctp_must_try_again:
9928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	flags = inp->sctp_flags;
9938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING
9948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_log_closing(inp, NULL, 17);
9958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
9978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
998907b9e7d7c75f02c3d1f6c70016127990e8fe648t#if defined(__Userspace__)
999907b9e7d7c75f02c3d1f6c70016127990e8fe648t		if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
1000907b9e7d7c75f02c3d1f6c70016127990e8fe648t		    (so->so_rcv.sb_cc > 0)) {
1001907b9e7d7c75f02c3d1f6c70016127990e8fe648t#else
10028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
10038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (so->so_rcv.sb_cc > 0)) {
1004907b9e7d7c75f02c3d1f6c70016127990e8fe648t#endif
10058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING
10068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_closing(inp, NULL, 13);
10078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
10098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
10108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
10118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOG_CLOSING
10128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_closing(inp, NULL, 13);
10138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
10158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
10168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* The socket is now detached, no matter what
10188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the state of the SCTP association.
10198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
10208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SB_CLEAR(so->so_snd);
10218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* same for the rcv ones, they are only
10228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * here for the accounting/select.
10238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
10248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SB_CLEAR(so->so_rcv);
10258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__)
10268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Now disconnect */
10278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_pcb = NULL;
10288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
10308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		flags = inp->sctp_flags;
10318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
10328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto sctp_must_try_again;
10338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version > 690000
10368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return;
10378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
1038b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (0);
10398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
10418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
10448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* __Userspace__ is not calling sctp_sendm */
10458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__Panda__) || defined(__Windows__))
10478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
10488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
10498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
10508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct mbuf *control, struct thread *p);
10518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
10538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
10548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct mbuf *control, struct proc *p);
10558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
10598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
10608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
10618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct mbuf *control, struct thread *p)
10628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
10638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
10648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
10658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct mbuf *control, struct proc *p)
10668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
10678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
10698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error;
10708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
10722fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
10738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control) {
10748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(control);
10758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control = NULL;
10768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
10788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m);
1079b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
10808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Got to have an to address if we are NOT a connected socket */
10828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((addr == NULL) &&
10838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
1084b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) {
10858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto connected_type;
10868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (addr == NULL) {
10878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
10888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EDESTADDRREQ;
10898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m);
10908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control) {
10918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(control);
10928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control = NULL;
10938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (error);
10958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
10978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (addr->sa_family != AF_INET) {
10988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* must be a v4 address! */
10998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
11008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m);
11018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control) {
11028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(control);
11038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control = NULL;
11048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EDESTADDRREQ;
11068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (error);
11078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* INET6 */
11098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenconnected_type:
11108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now what about control */
11118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control) {
11128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->control) {
11138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("huh? control set?\n");
11148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(inp->control);
11158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->control = NULL;
11168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->control = control;
11188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Place the data */
11208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->pkt) {
11218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_BUF_NEXT(inp->pkt_last) = m;
11228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->pkt_last = m;
11238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
11248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->pkt_last = inp->pkt = m;
11258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (
11270612043f643c9b26245564c05defca64d472060etuexen#if defined(__FreeBSD__) || defined(__APPLE__)
11288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* FreeBSD uses a flag passed */
11298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    ((flags & PRUS_MORETOCOME) == 0)
11308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
11318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    1			/* Open BSD does not have any "more to come"
11328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * indication */
11338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
11348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    ) {
11358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
11368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * note with the current version this code will only be used
11378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
11388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * re-defining sosend to use the sctp_sosend. One can
11398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * optionally switch back to this code (by changing back the
11408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * definitions) but this is not advisable. This code is used
11418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * by FreeBSD when sending a file with sendfile() though.
11428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
11438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int ret;
11448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
11468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->pkt = NULL;
11478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->control = NULL;
11488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ret);
11498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
11508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
11518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
11538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
11548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
11568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_disconnect(struct socket *so)
11578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
11588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
11598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
11618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL) {
11628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
11638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOTCONN);
11648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
11668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
11678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
11688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (LIST_EMPTY(&inp->sctp_asoc_list)) {
11698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* No connection */
11708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
11718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
11728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
11738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_association *asoc;
11748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_tcb *stcb;
11758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = LIST_FIRST(&inp->sctp_asoc_list);
11778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
11788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
11798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
11808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EINVAL);
11818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(stcb);
11838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc = &stcb->asoc;
11848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
11858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* We are about to be freed, out of here */
11868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (0);
11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
1190907b9e7d7c75f02c3d1f6c70016127990e8fe648t#if defined(__Userspace__)
1191907b9e7d7c75f02c3d1f6c70016127990e8fe648t			if (((so->so_options & SCTP_SO_LINGER) &&
119215aed6e434dc1aac416f14635bb78920317d60e7t			     (so->so_linger == 0)) ||
1193907b9e7d7c75f02c3d1f6c70016127990e8fe648t			    (so->so_rcv.sb_cc > 0)) {
1194907b9e7d7c75f02c3d1f6c70016127990e8fe648t#else
11958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (((so->so_options & SO_LINGER) &&
119615aed6e434dc1aac416f14635bb78920317d60e7t			     (so->so_linger == 0)) ||
11978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (so->so_rcv.sb_cc > 0)) {
1198907b9e7d7c75f02c3d1f6c70016127990e8fe648t#endif
11998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_GET_STATE(asoc) !=
12008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_STATE_COOKIE_WAIT) {
12018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Left with Data unread */
12028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					struct mbuf *err;
12038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
120468beeca578347438d9c434680197647ed551935ft					err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA);
12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (err) {
12068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/*
12078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * Fill in the user
12088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 * initiated abort
12098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 */
12108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						struct sctp_paramhdr *ph;
12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						ph = mtod(err, struct sctp_paramhdr *);
12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr);
12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						ph->param_length = htons(SCTP_BUF_LEN(err));
12168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
12228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
12238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
12248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
12258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_3);
12268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* No unlock tcb assoc is gone */
12278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (0);
12288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
12298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (TAILQ_EMPTY(&asoc->send_queue) &&
12308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    TAILQ_EMPTY(&asoc->sent_queue) &&
12318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (asoc->stream_queue_cnt == 0)) {
12328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* there is nothing queued to send, so done */
12338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (asoc->locked_on_sending) {
12348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto abort_anyway;
12358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
12368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
12378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
12388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* only send SHUTDOWN 1st time thru */
12398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					struct sctp_nets *netp;
12407988ea8f0c067cf3757e798b473b1ae4d34b6dfdt
12418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
12428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
12438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
12448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
12458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
12468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
12477988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					sctp_stop_timers_for_shutdown(stcb);
12487988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					if (stcb->asoc.alternate) {
12497988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						netp = stcb->asoc.alternate;
12507988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					} else {
12517988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						netp = stcb->asoc.primary_destination;
12527988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					}
12537988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					sctp_send_shutdown(stcb,netp);
12548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
12558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 stcb->sctp_ep, stcb, netp);
12568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
12578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 stcb->sctp_ep, stcb, netp);
12587988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
12618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * we still got (or just got) data to send,
12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * so set SHUTDOWN_PENDING
12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * XXX sockets draft says that SCTP_EOF
12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * should be sent with no data. currently,
12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * we will allow user data to be sent first
12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * and move to SHUTDOWN-PENDING
12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_nets *netp;
12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb->asoc.alternate) {
12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					netp = stcb->asoc.alternate;
12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					netp = stcb->asoc.primary_destination;
12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
12798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 netp);
12818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (asoc->locked_on_sending) {
12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Locked to send out the data */
12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					struct sctp_stream_queue_pending *sp;
12848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
12858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sp == NULL) {
12868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    asoc->locked_on_sending->stream_no);
12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
12898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((sp->length == 0) && (sp->msg_is_complete == 0))
12908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
12918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
12938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (TAILQ_EMPTY(&asoc->send_queue) &&
12948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    TAILQ_EMPTY(&asoc->sent_queue) &&
12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
12968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					struct mbuf *op_err;
12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				abort_anyway:
12988f9e45fea288542b24a6bda01269c6fc184d991at					op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ+SCTP_LOC_4;
13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RUNLOCK(inp);
13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_5);
13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (0);
13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
13138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			soisdisconnecting(so);
13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
13178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* not reached */
13198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
13208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* UDP model does not support this */
13218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
13228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1323b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EOPNOTSUPP);
13248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1327e5acde438f3c0c70f50751fa4c6a8209650f67cbtuexen#if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
13288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
13298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_flush(struct socket *so, int how)
13308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        /*
13328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * We will just clear out the values and let
13338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * subsequent close clear out the data, if any.
13348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Note if the user did a shutdown(SHUT_RD) they
13358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * will not be able to read the data, the socket
13368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * will block that from happening.
13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
13418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL) {
13428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1343b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
13448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
13468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* For the 1 to many model this does nothing */
13478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
13488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
13498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
13508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(inp);
13528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
13538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* First make sure the sb will be happy, we don't
13548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * use these except maybe the count
13558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
13568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
13578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_LOCK(inp);
1358e5acde438f3c0c70f50751fa4c6a8209650f67cbtuexen		inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
13598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_UNLOCK(inp);
13608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_rcv.sb_cc = 0;
13628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_rcv.sb_mbcnt = 0;
13638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_rcv.sb_mb = NULL;
13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) {
13668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* First make sure the sb will be happy, we don't
13678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * use these except maybe the count
13688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
13698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_snd.sb_cc = 0;
13708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_snd.sb_mbcnt = 0;
13718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_snd.sb_mb = NULL;
13728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
13758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
13798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_shutdown(struct socket *so)
13808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
13828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
13842fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1386b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* For UDP model this is a invalid call */
1390e2fb489e7481204003db964c24f54c4ba99d327et	if (!((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1391e2fb489e7481204003db964c24f54c4ba99d327et	      (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
13928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Restore the flags that the soshutdown took away. */
13938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version >= 502115) || defined(__Windows__)
13948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_LOCK(&so->so_rcv);
13958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
13968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_UNLOCK(&so->so_rcv);
13978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
13988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_state &= ~SS_CANTRCVMORE;
13998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
14008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* This proc will wakeup for read and do nothing (I hope) */
14018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
14028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EOPNOTSUPP);
14048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
14068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Ok if we reach here its the TCP model and it is either a SHUT_WR
14078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * or SHUT_RDWR. This means we put the shutdown flag against it.
14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
14108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_tcb *stcb;
14118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_association *asoc;
14128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((so->so_state &
14148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (SS_ISCONNECTED|SS_ISCONNECTING|SS_ISDISCONNECTING)) == 0) {
14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
14168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (ENOTCONN);
14178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		socantsendmore(so);
14198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = LIST_FIRST(&inp->sctp_asoc_list);
14218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
14228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
14238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Ok we hit the case that the shutdown call was
14248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * made after an abort or something. Nothing to do
14258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * now.
14268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
14278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
14288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
14298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
14318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc = &stcb->asoc;
14328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (TAILQ_EMPTY(&asoc->send_queue) &&
14338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    TAILQ_EMPTY(&asoc->sent_queue) &&
14348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (asoc->stream_queue_cnt == 0)) {
14358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->locked_on_sending) {
14368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto abort_anyway;
14378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
14388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* there is nothing queued to send, so I'm done... */
14398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
14408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* only send SHUTDOWN the first time through */
14418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_nets *netp;
14427988ea8f0c067cf3757e798b473b1ae4d34b6dfdt
14438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
14448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
14458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
14468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
14497988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				sctp_stop_timers_for_shutdown(stcb);
14507988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				if (stcb->asoc.alternate) {
14517988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					netp = stcb->asoc.alternate;
14527988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				} else {
14537988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					netp = stcb->asoc.primary_destination;
14547988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				}
14557988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				sctp_send_shutdown(stcb, netp);
14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 stcb->sctp_ep, stcb, netp);
14588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 stcb->sctp_ep, stcb, netp);
14607988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * we still got (or just got) data to send, so set
14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * SHUTDOWN_PENDING
14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_nets *netp;
14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.alternate) {
14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				netp = stcb->asoc.alternate;
14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
14718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				netp = stcb->asoc.primary_destination;
14728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
14738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
14758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
14768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 netp);
14778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asoc->locked_on_sending) {
14798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Locked to send out the data */
14808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_stream_queue_pending *sp;
14818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
14828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sp == NULL) {
14838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
14848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    asoc->locked_on_sending->stream_no);
14858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
14868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((sp->length == 0)  && (sp-> msg_is_complete == 0)) {
14878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
14888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
14898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
14908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
14918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (TAILQ_EMPTY(&asoc->send_queue) &&
14928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    TAILQ_EMPTY(&asoc->sent_queue) &&
14938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
14948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct mbuf *op_err;
14958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			abort_anyway:
14968f9e45fea288542b24a6bda01269c6fc184d991at				op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
14978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6;
14988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_abort_an_association(stcb->sctp_ep, stcb,
14998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							  op_err, SCTP_SO_LOCKED);
15008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto skip_unlock;
15018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
15048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen skip_unlock:
15088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(inp);
1509b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (0);
15108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
15138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * copies a "user" presentable address and removes embedded scope, etc.
15148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns 0 on success, 1 on error
15158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t
15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE)
15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in6 lsa6;
15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sa = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)sa,
15248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    &lsa6);
15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1527f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memcpy(ss, sa, sa->sa_len);
15298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
15307988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	switch (sa->sa_family) {
15317988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET
15327988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	case AF_INET:
15338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(ss, sa, sizeof(struct sockaddr_in));
15347988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		break;
15357988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
15367988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET6
15377988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	case AF_INET6:
15388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(ss, sa, sizeof(struct sockaddr_in6));
15397988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		break;
15407988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
15417988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
15427988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	case AF_CONN:
15437988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		memcpy(ss, sa, sizeof(struct sockaddr_conn));
15447988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		break;
15457988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
15467988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	default:
15477988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		/* TSNH */
15487988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		break;
15498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: assumes addr lock is held
15588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic size_t
15608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   struct sctp_tcb *stcb,
15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   size_t limit,
15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   struct sockaddr_storage *sas,
15648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   uint32_t vrf_id)
15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifn *sctp_ifn;
15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *sctp_ifa;
15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	size_t actual;
156927d5428d96bc21c1097c731755876b8ffaef1b23t	int loopback_scope;
157027d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET)
157127d5428d96bc21c1097c731755876b8ffaef1b23t	int ipv4_local_scope, ipv4_addr_legal;
157227d5428d96bc21c1097c731755876b8ffaef1b23t#endif
157327d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET6)
157427d5428d96bc21c1097c731755876b8ffaef1b23t	int local_scope, site_scope, ipv6_addr_legal;
157527d5428d96bc21c1097c731755876b8ffaef1b23t#endif
15767988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
15777988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	int conn_addr_legal;
15787988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_vrf *vrf;
15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	actual = 0;
15828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (limit <= 0)
15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (actual);
15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Turn on all the appropriate scope */
15877988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		loopback_scope = stcb->asoc.scope.loopback_scope;
158827d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET)
15897988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
159027d5428d96bc21c1097c731755876b8ffaef1b23t		ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
159127d5428d96bc21c1097c731755876b8ffaef1b23t#endif
159227d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET6)
15937988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		local_scope = stcb->asoc.scope.local_scope;
15947988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		site_scope = stcb->asoc.scope.site_scope;
15957988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
159627d5428d96bc21c1097c731755876b8ffaef1b23t#endif
15977988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
15987988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
15997988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
16017988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		/* Use generic values for endpoints. */
16027988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		loopback_scope = 1;
160327d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET)
16047988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		ipv4_local_scope = 1;
160527d5428d96bc21c1097c731755876b8ffaef1b23t#endif
160627d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET6)
16077988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		local_scope = 1;
16087988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		site_scope = 1;
160927d5428d96bc21c1097c731755876b8ffaef1b23t#endif
16107988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
161127d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET6)
16127988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			ipv6_addr_legal = 1;
161327d5428d96bc21c1097c731755876b8ffaef1b23t#endif
161427d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET)
16157988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			if (SCTP_IPV6_V6ONLY(inp)) {
16167988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				ipv4_addr_legal = 0;
16177988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			} else {
16187988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				ipv4_addr_legal = 1;
16197988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			}
162027d5428d96bc21c1097c731755876b8ffaef1b23t#endif
16217988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
16227988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			conn_addr_legal = 0;
16237988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
16247988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		} else {
162527d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET6)
16267988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			ipv6_addr_legal = 0;
162727d5428d96bc21c1097c731755876b8ffaef1b23t#endif
16287988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
16297988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
16307988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				conn_addr_legal = 1;
163127d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET)
16327988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				ipv4_addr_legal = 0;
163327d5428d96bc21c1097c731755876b8ffaef1b23t#endif
16347988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			} else {
16357988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				conn_addr_legal = 0;
163627d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET)
16377988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				ipv4_addr_legal = 1;
163827d5428d96bc21c1097c731755876b8ffaef1b23t#endif
16397988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			}
16407988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#else
164127d5428d96bc21c1097c731755876b8ffaef1b23t#if defined(INET)
16428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ipv4_addr_legal = 1;
16437988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
164427d5428d96bc21c1097c731755876b8ffaef1b23t#endif
16458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf = sctp_find_vrf(vrf_id);
16488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (vrf == NULL) {
16498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
16508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
16528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
16538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((loopback_scope == 0) &&
16548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
16558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Skip loopback if loopback_scope not set */
16568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
16578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
16588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
16598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb) {
16608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
16618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * For the BOUND-ALL case, the list
16628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * associated with a TCB is Always
16638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * considered a reverse list.. i.e.
16648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * it lists addresses that are NOT
16658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * part of the association. If this
16668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * is one of those we must skip it.
16678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
16688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sctp_is_addr_restricted(stcb,
16698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								    sctp_ifa)) {
16708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
16718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
16728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
16738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				switch (sctp_ifa->address.sa.sa_family) {
16748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
16758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET:
16768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (ipv4_addr_legal) {
16778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						struct sockaddr_in *sin;
16788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1679bfb1bf7e665a02b48026482bf33d05c83dfad73bt						sin = &sctp_ifa->address.sin;
16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (sin->sin_addr.s_addr == 0) {
16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							/*
16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * we skip unspecifed
16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * addresses
16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 */
16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
1687998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
1688998635733088fde643e6d807fa76679c4ceeaa00t						if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
1689998635733088fde643e6d807fa76679c4ceeaa00t						                     &sin->sin_addr) != 0) {
1690998635733088fde643e6d807fa76679c4ceeaa00t							continue;
1691998635733088fde643e6d807fa76679c4ceeaa00t						}
1692998635733088fde643e6d807fa76679c4ceeaa00t#endif
16938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((ipv4_local_scope == 0) &&
16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
16958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
16978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							actual += sizeof(struct sockaddr_in6);
17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else {
17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							memcpy(sas, sin, sizeof(*sin));
17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
17078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							actual += sizeof(*sin);
17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (actual >= limit) {
17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							return (actual);
17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET6:
17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (ipv6_addr_legal) {
17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						struct sockaddr_in6 *sin6;
17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
17268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						struct sockaddr_in6 lsa6;
17278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1728bfb1bf7e665a02b48026482bf33d05c83dfad73bt						sin6 = &sctp_ifa->address.sin6;
17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
17308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							/*
17318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * we skip unspecifed
17328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * addresses
17338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 */
17348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
17358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
1736998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
1737998635733088fde643e6d807fa76679c4ceeaa00t						if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
1738998635733088fde643e6d807fa76679c4ceeaa00t						                     &sin6->sin6_addr) != 0) {
1739998635733088fde643e6d807fa76679c4ceeaa00t							continue;
1740998635733088fde643e6d807fa76679c4ceeaa00t						}
1741998635733088fde643e6d807fa76679c4ceeaa00t#endif
17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (local_scope == 0)
17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								continue;
17458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE)
17468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (sin6->sin6_scope_id == 0) {
17478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								if (sa6_recoverscope(sin6) != 0)
17498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									/*
17508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * bad link
17518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * local
17528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * address
17538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 */
17548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									continue;
17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
17568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								lsa6 = *sin6;
17578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								if (in6_recoverscope(&lsa6,
17588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen										     &lsa6.sin6_addr,
17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen										     NULL))
17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									/*
17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * bad link
17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * local
17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * address
17648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 */
17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								continue;
17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sin6 = &lsa6;
17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* SCTP_KAME */
17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((site_scope == 0) &&
17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
17748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						memcpy(sas, sin6, sizeof(*sin6));
17767988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
17778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
17788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						actual += sizeof(*sin6);
17798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (actual >= limit) {
17808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							return (actual);
17818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
17838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
17848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
17858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
17868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17877988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
17887988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				case AF_CONN:
17897988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					if (conn_addr_legal) {
17907988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						memcpy(sas, &sctp_ifa->address.sconn, sizeof(struct sockaddr_conn));
17917988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
17927988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_conn));
17937988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						actual += sizeof(struct sockaddr_conn);
17947988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						if (actual >= limit) {
17957988ea8f0c067cf3757e798b473b1ae4d34b6dfdt							return (actual);
17967988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						}
17977988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					} else {
17987988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						continue;
17997988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					}
18007988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				default:
18028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* TSNH */
18038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
18048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
18058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_laddr *laddr;
1809f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifndef HAVE_SA_LEN
18108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t sa_len = 0;
18118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18127988ea8f0c067cf3757e798b473b1ae4d34b6dfdt
18138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
18158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
18168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
18178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
18188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
18208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
18217988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			switch (laddr->ifa->address.sa.sa_family) {
18227988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET
18237988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_INET:
18247988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
18257988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18277988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET6
18287988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_INET6:
18297988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
18307988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18317988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18327988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
18337988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_CONN:
18347988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
18357988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18367988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18377988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			default:
18387988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				/* TSNH */
18397988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18407988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			}
1841f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
18428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sas = (struct sockaddr_storage *)((caddr_t)sas +
18438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							  laddr->ifa->address.sa.sa_len);
18448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			actual += laddr->ifa->address.sa.sa_len;
18458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
18467988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			switch (laddr->ifa->address.sa.sa_family) {
18477988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET
18487988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_INET:
18497988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				sa_len = sizeof(struct sockaddr_in);
18507988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18517988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18527988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET6
18537988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_INET6:
18547988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				sa_len = sizeof(struct sockaddr_in6);
18557988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18567988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18577988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
18587988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_CONN:
18597988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				sa_len = sizeof(struct sockaddr_conn);
18607988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18617988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18627988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			default:
18637988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				/* TSNH */
18647988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18657988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			}
18668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sas = (struct sockaddr_storage *)((caddr_t)sas + sa_len);
18678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			actual += sa_len;
18688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (actual >= limit) {
18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (actual);
18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (actual);
18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic size_t
18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_fill_up_addresses(struct sctp_inpcb *inp,
18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                       struct sctp_tcb *stcb,
18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                       size_t limit,
18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                       struct sockaddr_storage *sas)
18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	size_t size = 0;
18848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
18858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t id;
18868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RLOCK();
18898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
18918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FIX ME: ?? this WILL report duplicate addresses if they appear
18928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * in more than one VRF.
18938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
18948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill up addresses for all VRFs on the endpoint */
18958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (id = 0; (id < inp->num_vrfs) && (size < limit); id++) {
18968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size += sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
18978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						   inp->m_vrf_ids[id]);
18988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sas = (struct sockaddr_storage *)((caddr_t)sas + size);
18998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
19018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill up addresses for the endpoint's default vrf */
19028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
19038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  inp->def_vrf_id);
19048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RUNLOCK();
19068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (size);
19078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
19108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: assumes addr lock is held
19118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
19128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
19138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int cnt = 0;
19168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_vrf *vrf = NULL;
19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * In both sub-set bound an bound_all cases we return the MAXIMUM
19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * number of addresses that you COULD get. In reality the sub-set
19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * bound may have an exclusion list for a given TCB OR in the
19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * bound-all case a TCB may NOT include the loopback or other
19238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * addresses as well.
19248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
19258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf = sctp_find_vrf(vrf_id);
19268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (vrf == NULL) {
19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_ifn *sctp_ifn;
19318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_ifa *sctp_ifa;
19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
19348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Count them if they are the right type */
19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				switch (sctp_ifa->address.sa.sa_family) {
19378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
19388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET:
19398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
19408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						cnt += sizeof(struct sockaddr_in6);
19418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					else
19428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						cnt += sizeof(struct sockaddr_in);
19438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
19468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET6:
19478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					cnt += sizeof(struct sockaddr_in6);
19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
19498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19507988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
19517988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				case AF_CONN:
19527988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					cnt += sizeof(struct sockaddr_conn);
19537988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					break;
19547988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				default:
19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
19578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
19618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_laddr *laddr;
19628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
19648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			switch (laddr->ifa->address.sa.sa_family) {
19658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
19668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET:
19678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
19688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					cnt += sizeof(struct sockaddr_in6);
19698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
19708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					cnt += sizeof(struct sockaddr_in);
19718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
19728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
19748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET6:
19758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cnt += sizeof(struct sockaddr_in6);
19768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
19778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
197875cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
197975cd23222c96d5ebe5a9082c57a263f917f1462btuexen			case AF_CONN:
198075cd23222c96d5ebe5a9082c57a263f917f1462btuexen				cnt += sizeof(struct sockaddr_conn);
198175cd23222c96d5ebe5a9082c57a263f917f1462btuexen				break;
198275cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
19838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			default:
19848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
19858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (cnt);
19898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_count_max_addresses(struct sctp_inpcb *inp)
19938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int cnt = 0;
19958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
19968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int id;
19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RLOCK();
20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FIX ME: ?? this WILL count duplicate addresses if they appear
20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * in more than one VRF.
20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* count addresses for all VRFs on the endpoint */
20068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (id = 0; id < inp->num_vrfs; id++) {
20078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cnt += sctp_count_max_addresses_vrf(inp, inp->m_vrf_ids[id]);
20088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
20108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* count addresses for the endpoint's default VRF */
20118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
20128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
20138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RUNLOCK();
20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (cnt);
20158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  size_t optsize, void *p, int delay)
20208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error = 0;
20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int creat_lock_on = 0;
20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb = NULL;
20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *sa;
20258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
2027b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int bad_addresses = 0;
20288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_assoc_t *a_id;
20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
20348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We are already connected AND the TCP model */
20358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
20368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EADDRINUSE);
20378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
20408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2042b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = LIST_FIRST(&inp->sctp_asoc_list);
20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EALREADY);
20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_INCR_REF(inp);
20558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_ASOC_CREATE_LOCK(inp);
20568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	creat_lock_on = 1;
20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
20588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EFAULT;
20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	totaddrp = (int *)optval;
20648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	totaddr = *totaddrp;
20658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sa = (struct sockaddr *)(totaddrp + 1);
2066b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
2067b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((stcb != NULL) || bad_addresses) {
20688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Already have or am bring up an association */
20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_ASOC_CREATE_UNLOCK(inp);
20708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		creat_lock_on = 0;
20718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb)
20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (bad_addresses == 0) {
20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EALREADY;
20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
20788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (num_v6 > 0)) {
20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
20838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
20868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (num_v4 > 0)) {
20878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct in6pcb *inp6;
20888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp6 = (struct in6pcb *)inp;
20908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_IPV6_V6ONLY(inp6)) {
20918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
20928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * if IPV6_V6ONLY flag, ignore connections destined
20938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * to a v4 addr or v4-mapped addr
20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
20968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
20978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_now;
20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* INET6 */
21018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
21028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_PCB_FLAGS_UNBOUND) {
21038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Bind a ephemeral port */
21048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_inpcb_bind(so, NULL, NULL, p);
21058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
21068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_now;
21078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* FIX ME: do we want to pass in a vrf on the connect call? */
21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf_id = inp->def_vrf_id;
2112000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* We are GOOD to go */
21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       (struct thread *)p
21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__)
21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       (PKTHREAD)p
21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       (struct proc *)p
21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		);
21248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
21258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Gak! no memory */
21268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
21278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
21298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
21308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Set the connected flag so we can queue data */
21318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		soisconnecting(so);
21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
21348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* move to second address */
21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (sa->sa_family) {
21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
21398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
21418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
21428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
21438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
21448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
21468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = 0;
21518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_connectx_helper_add(stcb, sa, (totaddr-1), &error);
21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Fill in the return id */
21538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error) {
21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6);
21558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
21568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	a_id = (sctp_assoc_t *)optval;
21588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*a_id = sctp_get_associd(stcb);
21598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* initialize authentication parameters for the assoc */
21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_initialize_auth_params(inp, stcb);
21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (delay) {
21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* doing delayed connection */
21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.delayed_connection = 1;
21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
21688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
21698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
21708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
21738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
21748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Set the connected flag so we can queue data */
21758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		soisconnecting(so);
21768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out_now:
21788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (creat_lock_on) {
21798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_ASOC_CREATE_UNLOCK(inp);
21808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_DECR_REF(inp);
2182b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (error);
21838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp); \
21898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = LIST_FIRST(&inp->sctp_asoc_list); \
21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) { \
21918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(stcb); \
21928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                } \
21938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp); \
21948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (assoc_id > SCTP_ALL_ASSOC) { \
21958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
21968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) { \
21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT; \
21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break; \
22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} \
22018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else { \
22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = NULL; \
22038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        } \
22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  }
22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22070ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (size < sizeof(type)) { \
22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL; \
22118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break; \
22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else { \
22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		destp = (type *)srcp; \
22148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} \
22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen      }
22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__) || defined(__Userspace__)
22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
22228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
22238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    void *p) {
22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp = NULL;
22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error, val = 0;
22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb = NULL;
22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (optval == NULL) {
22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
22308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EINVAL);
22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
22342fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return EINVAL;
22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = 0;
22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (optname) {
22418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NODELAY:
22428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTOCLOSE:
22438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EXPLICIT_EOR:
22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTO_ASCONF:
22458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DISABLE_FRAGMENTS:
22468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_I_WANT_MAPPED_V4_ADDR:
22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_USE_EXT_RCVINFO:
22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
22498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (optname) {
22508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_DISABLE_FRAGMENTS:
22518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
22528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_I_WANT_MAPPED_V4_ADDR:
22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTO_ASCONF:
22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* only valid for bound all sockets */
22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto flags_out;
22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
22658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_EXPLICIT_EOR:
22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_NODELAY:
22708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
22718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_USE_EXT_RCVINFO:
22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
22748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTOCLOSE:
22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
22788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				val = 0;
22808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
22848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOPROTOOPT;
22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} /* end switch (sopt->sopt_name) */
22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*optsize < sizeof(val)) {
22878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
22888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
22898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	flags_out:
22918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
22928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* return the option value */
22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*(int *)optval = val;
22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(val);
22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        case SCTP_GET_PACKET_LOG:
22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef  SCTP_PACKET_LOGGING
23018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint8_t *target;
23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int ret;
23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
23058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ret = sctp_copy_out_packet_log(target , (int)*optsize);
23068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = ret;
23078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
23088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
23098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EOPNOTSUPP;
23108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
23118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_REUSE_PORT:
23148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
23168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
23188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't do this for a 1-m socket */
23198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
23208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
23218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PARTIAL_DELIVERY_POINT:
23288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
23308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
23328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = inp->partial_delivery_point;
23338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_FRAGMENT_INTERLEAVE:
23378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
23398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
23418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
23428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
23438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*value = SCTP_FRAG_LEVEL_2;
23448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
23458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*value = SCTP_FRAG_LEVEL_1;
23468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
23478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
23488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*value = SCTP_FRAG_LEVEL_0;
23498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
23518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CMT_ON_OFF:
23548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
23568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
23588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
23598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
23608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = stcb->asoc.sctp_cmt_on_off;
23618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
23628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
23638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
23648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
23658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
23668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
23678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				av->assoc_value = inp->sctp_cmt_on_off;
23688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
23698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
23708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
23718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
23728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
23738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
23758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
23768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PLUGGABLE_CC:
23808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
23828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
23848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
23858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
23868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = stcb->asoc.congestion_control_module;
23878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
23888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
23898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
23908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
23918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
23928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
23938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
23948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
23958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
23968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
23978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
23988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
23998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
24018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
24028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
24048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CC_OPTION:
24068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
24078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_cc_option *cc_opt;
24088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
24108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
24118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
24128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
24138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
24148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
24158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = ENOTSUP;
24168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
24178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 0, cc_opt);
24188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*optsize = sizeof(struct sctp_cc_option);
24198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
24218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
24238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PLUGGABLE_SS:
24258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
24268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
24278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
24298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
24308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
24318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = stcb->asoc.stream_scheduling_module;
24328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
24338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
24348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
24358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
24368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
24378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
24388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
24398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
24408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
24418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
24428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
24438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
24468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
24478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
24498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SS_VALUE:
24518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
24528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_stream_value *av;
24538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
24558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
24568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
24578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
24588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                                              &av->stream_value) < 0) {
24598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
24608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
24618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
24628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*optsize = sizeof(struct sctp_stream_value);
24638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
24658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
24668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't get stream value without association */
24678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
24688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
24698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
24718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_ADDR_LEN:
24738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
24748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
24758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
24778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
24788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
24798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (av->assoc_value == AF_INET) {
24808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = sizeof(struct sockaddr_in);
24818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = 0;
24828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
24848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
24858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (av->assoc_value == AF_INET6) {
24868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = sizeof(struct sockaddr_in6);
24878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = 0;
24888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
249075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
249175cd23222c96d5ebe5a9082c57a263f917f1462btuexen		if (av->assoc_value == AF_CONN) {
249275cd23222c96d5ebe5a9082c57a263f917f1462btuexen			av->assoc_value = sizeof(struct sockaddr_conn);
249375cd23222c96d5ebe5a9082c57a263f917f1462btuexen			error = 0;
249475cd23222c96d5ebe5a9082c57a263f917f1462btuexen		}
249575cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
24968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
24978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
24988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
24998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
25008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_ASSOC_NUMBER:
25048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value, cnt;
25068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
25088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cnt = 0;
25098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
25108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
25118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt++;
25128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
25148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = cnt;
25158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
25168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_ASSOC_ID_LIST:
25198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_ids *ids;
25218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		unsigned int at, limit;
2522000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
25238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
25248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		at = 0;
25258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		limit = (*optsize-sizeof(uint32_t))/ sizeof(sctp_assoc_t);
25268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
25278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
25288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (at < limit) {
25298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
25308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
25318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
25328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
25338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
25348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
25358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
25378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
25388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ids->gaids_number_of_ids = at;
25398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
25408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CONTEXT:
25448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
25468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
25488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
25498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
25518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = stcb->asoc.context;
25528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
25538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
25548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
25558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
25568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
25578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
25588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				av->assoc_value = inp->sctp_context;
25598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
25608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
25618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
25628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
25638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
25648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
25668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
25678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_VRF_ID:
25718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *default_vrfid;
25738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
25758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*default_vrfid = inp->def_vrf_id;
25768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
25778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_ASOC_VRF:
25808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *id;
25828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
25848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, id->assoc_id);
25858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
25868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
25878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
25888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
25898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			id->assoc_value = stcb->asoc.vrf_id;
25908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
25918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_VRF_IDS:
25958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
25978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int siz_needed;
25988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *vrf_ids;
25998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(vrf_ids, optval, uint32_t, *optsize);
26018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		siz_needed = inp->num_vrfs * sizeof(uint32_t);
26028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*optsize < siz_needed) {
26038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
26048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
26058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
26068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(vrf_ids, inp->m_vrf_ids, siz_needed);
26078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = siz_needed;
26088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
26108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
26118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EOPNOTSUPP;
26128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
26138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
26148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_NONCE_VALUES:
26168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
26178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_get_nonce_values *gnv;
26188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
26208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
26218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
26238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			gnv->gn_peers_tag = stcb->asoc.peer_vtag;
26248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			gnv->gn_local_tag = stcb->asoc.my_vtag;
26258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
26268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_get_nonce_values);
26278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
26288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
26298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOTCONN;
26308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
26328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DELAYED_SACK:
26348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
26358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sack_info *sack;
26368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
26388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
26398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
26408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sack->sack_delay = stcb->asoc.delayed_ack;
26418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sack->sack_freq = stcb->asoc.sack_freq;
26428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
26438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
26448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
26458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
26468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
26478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
26488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
26498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
26508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
26518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
26528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
26538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
26548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
26558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
26578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_sack_info);
26588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
26608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_SNDBUF_USE:
26628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
26638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sockstat *ss;
26648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
26668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
26678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
26698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
26708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
26718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 stcb->asoc.size_on_all_streams);
26728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
26738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_sockstat);
26748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
26758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
26768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOTCONN;
26778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
26798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_MAX_BURST:
26818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
26828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 900000
26838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint8_t *value;
26848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint8_t, *optsize);
26868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
26888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_ep.max_burst < 256) {
26898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*value = inp->sctp_ep.max_burst;
26908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
26918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*value = 255;
26928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
26948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint8_t);
26958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
26968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
26978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
26998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
27008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
27028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = stcb->asoc.max_burst;
27038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
27048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
27058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
27068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
27078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
27088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
27098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				av->assoc_value = inp->sctp_ep.max_burst;
27108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
27118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
27128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
27138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
27148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
27158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
27178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
27188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
27208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
27218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
27228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_MAXSEG:
27238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
27248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
27258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int ovh;
27268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
27288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
27298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
27318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
27328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
27338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
27348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
27358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
27368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
27378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
27388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
27398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ovh = SCTP_MED_OVERHEAD;
27408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
27418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ovh = SCTP_MED_V4_OVERHEAD;
27428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
27438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
27448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					av->assoc_value = 0;
27458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
27468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					av->assoc_value = inp->sctp_frag_point - ovh;
27478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
27488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
27498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
27508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
27518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
27528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
27548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
27558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
27578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
27588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_STAT_LOG:
27598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_fill_stat_log(optval, optsize);
27608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
27618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EVENTS:
27628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
27638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_event_subscribe *events;
27648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
27668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memset(events, 0, sizeof(struct sctp_event_subscribe));
27678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
27688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
27698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_data_io_event = 1;
27708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
27728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_association_event = 1;
27738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
27758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_address_event = 1;
27768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
27788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_send_failure_event = 1;
27798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
27818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_peer_error_event = 1;
27828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
27848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_shutdown_event = 1;
27858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
27878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_partial_delivery_event = 1;
27888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
27908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_adaptation_layer_event = 1;
27918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
27938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_authentication_event = 1;
27948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
27968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_sender_dry_event = 1;
27978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
27998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_stream_reset_event = 1;
28008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
28018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(struct sctp_event_subscribe);
28028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
28038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ADAPTATION_LAYER:
28058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
28068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
28078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
28098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
28118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = inp->sctp_ep.adaptation_layer_indicator;
28128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
28138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
28148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
28158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SET_INITIAL_DBG_SEQ:
28178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
28188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
28198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
28218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
28228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = inp->sctp_ep.initial_sequence_debug;
28238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
28248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
28258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
28268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_LOCAL_ADDR_SIZE:
28288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
28298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
28308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
28328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
28338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = sctp_count_max_addresses(inp);
28348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
28358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
28368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
28378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_REMOTE_ADDR_SIZE:
28398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
28408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
28418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t size;
28428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
28438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
28458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* FIXME MT: change to sctp_assoc_value? */
28468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
28478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
28498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			size = 0;
28508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Count the sizes */
28518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
28528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
28538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					size += sizeof(struct sockaddr_in6);
28548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
28558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
28568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
28578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case AF_INET:
28588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						size += sizeof(struct sockaddr_in);
28598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
28608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
28618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
28628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case AF_INET6:
28638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						size += sizeof(struct sockaddr_in6);
28648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
28658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
286675cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
286775cd23222c96d5ebe5a9082c57a263f917f1462btuexen					case AF_CONN:
286875cd23222c96d5ebe5a9082c57a263f917f1462btuexen						size += sizeof(struct sockaddr_conn);
286975cd23222c96d5ebe5a9082c57a263f917f1462btuexen						break;
287075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
28718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					default:
28728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
28738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
28748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
28758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
28768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
28778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*value = (uint32_t) size;
28788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(uint32_t);
28798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
28808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
28818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOTCONN;
28828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
28848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_PEER_ADDRESSES:
28868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
28878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Get the address information, an array is passed in to
28888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * fill up we pack it.
28898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
28908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
28918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t cpsz, left;
28928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_storage *sas;
28938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
28948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_getaddresses *saddr;
28958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
28978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
28988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
29008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			left = (*optsize) - sizeof(struct sctp_getaddresses);
29018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_getaddresses);
29028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sas = (struct sockaddr_storage *)&saddr->addr[0];
29038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
29058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
29068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					cpsz = sizeof(struct sockaddr_in6);
29078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
29088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
29098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
29108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case AF_INET:
29118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						cpsz = sizeof(struct sockaddr_in);
29128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
29138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
29158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case AF_INET6:
29168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						cpsz = sizeof(struct sockaddr_in6);
29178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
29188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
291975cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
292075cd23222c96d5ebe5a9082c57a263f917f1462btuexen					case AF_CONN:
292175cd23222c96d5ebe5a9082c57a263f917f1462btuexen						cpsz = sizeof(struct sockaddr_conn);
292275cd23222c96d5ebe5a9082c57a263f917f1462btuexen						break;
292375cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
29248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					default:
29258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						cpsz = 0;
29268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
29278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
29288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (cpsz == 0) {
29308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
29318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (left < cpsz) {
29338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* not enough room. */
29348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
29358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(INET) && defined(INET6)
29378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
29388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
29398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Must map the address */
29408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
29418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    (struct sockaddr_in6 *)sas);
29428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
29438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					memcpy(sas, &net->ro._l_addr, cpsz);
29458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(INET) && defined(INET6)
29468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				((struct sockaddr_in *)sas)->sin_port = stcb->rport;
29498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
29518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				left -= cpsz;
29528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*optsize += cpsz;
29538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
29548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
29558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
29568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
29578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT;
29588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
29608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_LOCAL_ADDRESSES:
29628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
29638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t limit, actual;
29648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_storage *sas;
29658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_getaddresses *saddr;
29668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
29688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
29698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sas = (struct sockaddr_storage *)&saddr->addr[0];
29718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		limit = *optsize - sizeof(sctp_assoc_t);
29728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
29738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
29748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
29758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(struct sockaddr_storage) + actual;
29778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
29788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEER_ADDR_PARAMS:
29808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
29818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paddrparams *paddrp;
29828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
29838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
29858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
29868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
29888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
29898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
29908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
29918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
29928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
29938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
29948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
29958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
29968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
29978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
29988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
29998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
30008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb && (net == NULL)) {
30028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr *sa;
30038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sa = (struct sockaddr *)&paddrp->spp_address;
30058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
30068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET) {
30078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in *sin;
30088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin = (struct sockaddr_in *)sa;
30108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin->sin_addr.s_addr) {
30118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
30128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
30138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
30148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
30158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
30178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
30188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
30198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET6) {
30208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in6 *sin6;
30218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6 = (struct sockaddr_in6 *)sa;
30238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
30248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
30258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
30268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
30278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
30288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
30308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
303175cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
303275cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
303375cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
303475cd23222c96d5ebe5a9082c57a263f917f1462btuexen
303575cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
303675cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
303775cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
303875cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
303975cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
304075cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
304175cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
304275cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
304375cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
30448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			{
30458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EAFNOSUPPORT;
30468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
30478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
30488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
30498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
30508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
30538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Applies to the specific association */
30548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddrp->spp_flags = 0;
30558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net) {
30568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				int ovh;
30578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
30588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ovh = SCTP_MED_OVERHEAD;
30598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
30608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ovh = SCTP_MED_V4_OVERHEAD;
30618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_hbinterval = net->heart_beat_delay;
30648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmaxrxt = net->failure_threshold;
30658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmtu = net->mtu - ovh;
30668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get flags for HB */
30678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dest_state & SCTP_ADDR_NOHB) {
30688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_DISABLE;
30698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
30708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_ENABLE;
30718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get flags for PMTU */
30738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
30748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
30758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
30768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
30778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dscp & 0x01) {
30798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_dscp = net->dscp & 0xfc;
30808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_DSCP;
30818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
30838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
30848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (net->flowlabel & 0x80000000)) {
30858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
30868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
30878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
30898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
30908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
30918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * No destination so return default
30928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * value
30938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
30948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
30958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
30968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb->asoc.default_dscp & 0x01) {
30978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
30988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_DSCP;
30998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
31018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb->asoc.default_flowlabel & 0x80000000) {
31028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
31038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
31048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
31068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* default settings should be these */
31078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
31088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_DISABLE;
31098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
31108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_ENABLE;
31118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
31138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
31148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
31158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
31168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
31188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddrp->spp_assoc_id = sctp_get_associd(stcb);
31208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
31218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
31228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
31238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
31248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
31258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Use endpoint defaults */
31268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
31278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
31288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
31298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
31308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get inp's default */
31318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (inp->sctp_ep.default_dscp & 0x01) {
31328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
31338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_DSCP;
31348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
31368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
31378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (inp->sctp_ep.default_flowlabel & 0x80000000)) {
31388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
31398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
31408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
31428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* can't return this */
31438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmtu = 0;
31448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
31468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_ENABLE;
31478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
31488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_DISABLE;
31498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
31518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
31528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
31538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
31548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
31568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
31578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
31588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
31598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
31618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
31628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_paddrparams);
31638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
31648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
31658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
31668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_PEER_ADDR_INFO:
31678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
31688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paddrinfo *paddri;
31698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
31708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
31728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
31738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
31758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
31768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
31778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
31788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
31798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
31808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
31818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
31828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
31838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
31848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
31858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
31868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
31888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb) && (net)) {
31908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
31918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* It's unconfirmed */
31928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddri->spinfo_state = SCTP_UNCONFIRMED;
31938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
31948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* It's active */
31958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddri->spinfo_state = SCTP_ACTIVE;
31968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
31978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* It's inactive */
31988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddri->spinfo_state = SCTP_INACTIVE;
31998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddri->spinfo_cwnd = net->cwnd;
32018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
32028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddri->spinfo_rto = net->RTO;
32038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddri->spinfo_assoc_id = sctp_get_associd(stcb);
32048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddri->spinfo_mtu = net->mtu;
32058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
32068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_paddrinfo);
32078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
32088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
32098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
32108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
32128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT;
32138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
32158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PCB_STATUS:
32178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
32188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_pcbinfo *spcb;
32198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
32218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_fill_pcbinfo(spcb);
32228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(struct sctp_pcbinfo);
32238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
32248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_STATUS:
32268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
32278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
32288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_status *sstat;
32298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
32318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
32328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
32348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
32358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
32368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
32378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
32398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * I think passing the state is fine since
32408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * sctp_constants.h will be available to the user
32418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * land.
32428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
32438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_state = stcb->asoc.state;
32448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_assoc_id = sctp_get_associd(stcb);
32458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
32468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
32478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
32488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * We can't include chunks that have been passed to
32498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the socket layer. Only things in queue.
32508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
32518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
32528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 stcb->asoc.cnt_on_all_streams);
32538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_instrms = stcb->asoc.streamincnt;
32568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
32578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
3258f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
32598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(&sstat->sstat_primary.spinfo_address,
32608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       &stcb->asoc.primary_destination->ro._l_addr,
32618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
32628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
32638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET) {
32648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(&sstat->sstat_primary.spinfo_address,
32658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       &stcb->asoc.primary_destination->ro._l_addr,
32668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       sizeof(struct sockaddr_in));
32678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
32688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(&sstat->sstat_primary.spinfo_address,
32698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       &stcb->asoc.primary_destination->ro._l_addr,
32708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       sizeof(struct sockaddr_in6));
32718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
32738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = stcb->asoc.primary_destination;
32748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
32758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
32768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Again the user can get info from sctp_constants.h
32778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * for what the state of the network is.
32788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
32798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
32808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* It's unconfirmed */
32818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
32828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
32838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* It's active */
32848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
32858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
32868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* It's inactive */
32878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
32888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_primary.spinfo_cwnd = net->cwnd;
32908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
32918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_primary.spinfo_rto = net->RTO;
32928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_primary.spinfo_mtu = net->mtu;
32938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
32948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
32958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(struct sctp_status);
32968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
32978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RTOINFO:
32998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
33008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_rtoinfo *srto;
33018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
33038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
33048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
33068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			srto->srto_initial = stcb->asoc.initial_rto;
33078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			srto->srto_max = stcb->asoc.maxrto;
33088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			srto->srto_min = stcb->asoc.minrto;
33098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
33108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
33118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
33128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
33138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
33148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
33158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				srto->srto_initial = inp->sctp_ep.initial_rto;
33168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				srto->srto_max = inp->sctp_ep.sctp_maxrto;
33178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				srto->srto_min = inp->sctp_ep.sctp_minrto;
33188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
33198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
33208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
33218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
33228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
33238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
33258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_rtoinfo);
33268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
33288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMEOUTS:
33308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
33318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_timeouts *stimo;
33328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
33348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
33358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
33378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_init= stcb->asoc.timoinit;
33388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_data= stcb->asoc.timodata;
33398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_sack= stcb->asoc.timosack;
33408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_shutdown= stcb->asoc.timoshutdown;
33418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_heartbeat= stcb->asoc.timoheartbeat;
33428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_cookie= stcb->asoc.timocookie;
33438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_shutdownack= stcb->asoc.timoshutdownack;
33448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
33458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_timeouts);
33468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
33478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
33488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
33498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
33518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ASSOCINFO:
33538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
33548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assocparams *sasoc;
33558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
33578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
33588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
33608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
33618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
33628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
33638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
33648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
33658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
33668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
33678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
33688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
33698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
33708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
33718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
33728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
33738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_number_peer_destinations = 0;
33748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_peer_rwnd = 0;
33758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
33768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
33778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
33788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
33798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
33808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
33818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
33838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assocparams);
33848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
33868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_SEND_PARAM:
33888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
33898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sndrcvinfo *s_info;
33908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
33928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
33938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
33958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
33968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
33978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
33988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
33998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
34008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
34018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
34028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
34038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
34048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
34058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
34068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
3407000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			}
34088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
34108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_sndrcvinfo);
34118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
34138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_INITMSG:
34158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
34168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_initmsg *sinit;
34178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
34198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
34208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
34218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
34228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
34238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
34248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
34258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(struct sctp_initmsg);
34268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
34278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PRIMARY_ADDR:
34298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we allow a "get" operation on this */
34308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
34318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_setprim *ssp;
34328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
34348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
34358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
34378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* simply copy out the sockaddr_storage... */
343818818c8dd0d4cafdb259fa73f01f7825948faadct			size_t len;
34398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			len = *optsize;
3441f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
34428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len)
34438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len;
34448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
34458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET &&
34468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    len > sizeof(struct sockaddr_in))
34478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				len = sizeof(struct sockaddr_in);
34488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else if (
34498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET6 &&
34508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    len > sizeof(struct sockaddr_in6))
34518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				len = sizeof(struct sockaddr_in6);
34528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
34538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(&ssp->ssp_addr,
34558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       &stcb->asoc.primary_destination->ro._l_addr,
34568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       len);
34578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
34588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_setprim);
34598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
34608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
34618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
34628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
34648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_HMAC_IDENT:
34668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
34678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_hmacalgo *shmac;
34688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmaclist_t *hmaclist;
34698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t size;
34708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int i;
34718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
34738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
34758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hmaclist = inp->sctp_ep.local_hmacs;
34768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hmaclist == NULL) {
34778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no HMACs to return */
34788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(*shmac);
34798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
34808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
34818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* is there room for all of the hmac ids? */
34838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size = sizeof(*shmac) + (hmaclist->num_algo *
34848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 sizeof(shmac->shmac_idents[0]));
34858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((size_t)(*optsize) < size) {
34868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
34878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
34888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
34898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
34908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* copy in the list */
34928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		shmac->shmac_number_of_idents = hmaclist->num_algo;
34938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < hmaclist->num_algo; i++) {
34948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			shmac->shmac_idents[i] = hmaclist->hmac[i];
34958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
34978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = size;
34988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
34998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_ACTIVE_KEY:
35018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
35028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authkeyid *scact;
35038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
35058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
35068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
35088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* get the active key on the assoc */
35098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
35108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
35118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
35128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
35138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
35148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
35158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get the endpoint active key */
35168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
35178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				scact->scact_keynumber = inp->sctp_ep.default_keyid;
35188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
35198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
35208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
35218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
35228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
35238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
35258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_authkeyid);
35268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
35288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_LOCAL_AUTH_CHUNKS:
35308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
35318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authchunks *sac;
35328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auth_chklist_t *chklist = NULL;
35338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t size = 0;
35348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
35368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
35378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
35398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* get off the assoc */
35408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chklist = stcb->asoc.local_auth_chunks;
35418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* is there enough space? */
35428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			size = sctp_auth_get_chklist_size(chklist);
35438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
35448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
35458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
35468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
35478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* copy in the chunks */
35488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
35491a2e446bdbc52cc6178a3f80092943a84706ece9tuexen				sac->gauth_number_of_chunks = (uint32_t)size;
35508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*optsize = sizeof(struct sctp_authchunks) + size;
35518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
35528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
35538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
35548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
35558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
35568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
35578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get off the endpoint */
35588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
35598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				chklist = inp->sctp_ep.local_auth_chunks;
35608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* is there enough space? */
35618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				size = sctp_auth_get_chklist_size(chklist);
35628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
35638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
35648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
35658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
35668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* copy in the chunks */
35678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
35681a2e446bdbc52cc6178a3f80092943a84706ece9tuexen					sac->gauth_number_of_chunks = (uint32_t)size;
35698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*optsize = sizeof(struct sctp_authchunks) + size;
35708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
35718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
35728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
35738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
35748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
35758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
35768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
35788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEER_AUTH_CHUNKS:
35808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
35818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authchunks *sac;
35828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auth_chklist_t *chklist = NULL;
35838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t size = 0;
35848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
35868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
35878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
35898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* get off the assoc */
35908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chklist = stcb->asoc.peer_auth_chunks;
35918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* is there enough space? */
35928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			size = sctp_auth_get_chklist_size(chklist);
35938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
35948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
35958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
35968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
35978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* copy in the chunks */
35988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
35991a2e446bdbc52cc6178a3f80092943a84706ece9tuexen				sac->gauth_number_of_chunks = (uint32_t)size;
36008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*optsize = sizeof(struct sctp_authchunks) + size;
36018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
36028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
36038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
36048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
36058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT;
36068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
36088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
36108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEELOFF:
36118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
36128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_peeloff_opt *peeloff;
36138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(peeloff, optval, struct sctp_peeloff_opt, *optsize);
36158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* do the peeloff */
36168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_peeloff_option(p, peeloff);
36178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
36188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_peeloff_opt);
36198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	break;
36228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* HAVE_SCTP_PEELOFF_SOCKOPT */
36238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EVENT:
36248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
36258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_event *event;
36268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t event_type;
36278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
36298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
36308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (event->se_type) {
36328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ASSOC_CHANGE:
36338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
3634000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_PEER_ADDR_CHANGE:
36368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
3637000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_REMOTE_ERROR:
36398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVPEERERR;
3640000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SEND_FAILED:
36428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
3643000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SHUTDOWN_EVENT:
36458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
3646000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ADAPTATION_INDICATION:
36488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
3649000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_PARTIAL_DELIVERY_EVENT:
36518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
3652000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTHENTICATION_EVENT:
36548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_AUTHEVNT;
3655000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_STREAM_RESET_EVENT:
36578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
3658000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SENDER_DRY_EVENT:
36608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_DRYEVNT;
3661000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_NOTIFICATIONS_STOPPED_EVENT:
36638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = 0;
36648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
36658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOTSUP;
36668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
3667298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen		case SCTP_ASSOC_RESET_EVENT:
3668298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
3669298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			break;
3670298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen		case SCTP_STREAM_CHANGE_EVENT:
3671298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
3672298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			break;
36735741e159bdf238ef4b61085d6fbfea2947386238tuexen		case SCTP_SEND_FAILED_EVENT:
36745741e159bdf238ef4b61085d6fbfea2947386238tuexen			event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
36755741e159bdf238ef4b61085d6fbfea2947386238tuexen			break;
36768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
36778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = 0;
36788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
36798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
36808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
36818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (event_type > 0) {
36838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
36848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
36858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
36868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
36878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
36888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
36898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
36908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RLOCK(inp);
36918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					event->se_on = sctp_is_feature_on(inp, event_type);
36928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RUNLOCK(inp);
36938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
36948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
36958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
36968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
36978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
36988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
37008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_event);
37018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
37048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RECVRCVINFO:
37058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
37068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int onoff;
37078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*optsize < sizeof(int)) {
37098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
37108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
37118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
37126f63c1f0e9307e260e6d8724b12d0153cedb4a9atuexen			SCTP_INP_RLOCK(inp);
37138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
37148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
37158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
37178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* return the option value */
37188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*(int *)optval = onoff;
37198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(int);
37208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
37238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RECVNXTINFO:
37248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
37258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int onoff;
37268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*optsize < sizeof(int)) {
37288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
37298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
37308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
37316f63c1f0e9307e260e6d8724b12d0153cedb4a9atuexen			SCTP_INP_RLOCK(inp);
37328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
37338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
37348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
37368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* return the option value */
37378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*(int *)optval = onoff;
37388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(int);
37398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
37428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_SNDINFO:
37438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
37448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sndinfo *info;
37458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
37478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
37488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
37508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->snd_sid = stcb->asoc.def_send.sinfo_stream;
37518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->snd_flags = stcb->asoc.def_send.sinfo_flags;
37528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->snd_flags &= 0xfff0;
37538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
37548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->snd_context = stcb->asoc.def_send.sinfo_context;
37558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
37568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
37578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
37588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
37598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
37608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
37618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->snd_sid = inp->def_send.sinfo_stream;
37628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->snd_flags = inp->def_send.sinfo_flags;
37638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->snd_flags &= 0xfff0;
37648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->snd_ppid = inp->def_send.sinfo_ppid;
37658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->snd_context = inp->def_send.sinfo_context;
37668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
37678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
37688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
37698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
37708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
37718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
37738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_sndinfo);
37748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
37778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_PRINFO:
37788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
37798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_default_prinfo *info;
37808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
37828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
37838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
37858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
37868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
37878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
37888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
37898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
37908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
37918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
37928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
37938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
37948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->pr_value = inp->def_send.sinfo_timetolive;
37958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
37968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
37978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
37988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
37998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
38008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
38028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_default_prinfo);
38038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
38068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEER_ADDR_THLDS:
38078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
38088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paddrthlds *thlds;
38098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
38108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
38128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
38138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
38158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
38168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
38178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
38188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
38198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
38208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
38218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
38228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
38238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
38248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
38258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
38268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
38278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3828b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (stcb && (net == NULL)) {
38298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr *sa;
38308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sa = (struct sockaddr *)&thlds->spt_address;
38328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
38338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET) {
38348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in *sin;
38358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin = (struct sockaddr_in *)sa;
38378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin->sin_addr.s_addr) {
38388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
38398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
38408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
38418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
38428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
38438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
38448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
38458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
38468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET6) {
38478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in6 *sin6;
38488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6 = (struct sockaddr_in6 *)sa;
38508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
38518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
38528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
38538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
38548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
38558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
38568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
38578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
385875cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
385975cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
386075cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
386175cd23222c96d5ebe5a9082c57a263f917f1462btuexen
386275cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
386375cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
386475cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
386575cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
386675cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
386775cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
386875cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
386975cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
387075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
38718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			{
38728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EAFNOSUPPORT;
38738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
38748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
38758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
38768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
38778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
38808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net) {
38818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				thlds->spt_pathmaxrxt = net->failure_threshold;
38828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				thlds->spt_pathpfthld = net->pf_threshold;
38838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
38848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
38858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
38868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
38878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			thlds->spt_assoc_id = sctp_get_associd(stcb);
38888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
38898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
38908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
38918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
38928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
38938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Use endpoint defaults */
38948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
38958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
3896000a5bac556b28e74e4e98c540f66b1743e9312dtuexen				thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
38978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
38988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
38998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
39008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
39018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
39028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
39038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
39048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_paddrthlds);
39058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
39068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
39078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3908153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	case SCTP_REMOTE_UDP_ENCAPS_PORT:
3909153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	{
3910153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		struct sctp_udpencaps *encaps;
3911153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		struct sctp_nets *net;
3912000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
3913153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
3914153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
3915153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
3916153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (stcb) {
3917153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
3918153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		} else {
3919153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			/* We increment here since sctp_findassociation_ep_addr() wil
3920153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 * do a decrement if it finds the stcb as long as the locked
3921153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
3922153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 */
3923153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			net = NULL;
3924153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			SCTP_INP_INCR_REF(inp);
3925153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
3926153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (stcb == NULL) {
3927153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_DECR_REF(inp);
3928153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
3929153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
3930153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (stcb && (net == NULL)) {
3931153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			struct sockaddr *sa;
3932000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
3933153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			sa = (struct sockaddr *)&encaps->sue_address;
3934153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#ifdef INET
3935153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (sa->sa_family == AF_INET) {
3936153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				struct sockaddr_in *sin;
3937153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
3938153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				sin = (struct sockaddr_in *)sa;
3939153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				if (sin->sin_addr.s_addr) {
3940153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					error = EINVAL;
3941153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_TCB_UNLOCK(stcb);
3942153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3943153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					break;
3944153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				}
3945153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else
3946153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#endif
3947153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#ifdef INET6
3948153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (sa->sa_family == AF_INET6) {
3949153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				struct sockaddr_in6 *sin6;
3950153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
3951153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				sin6 = (struct sockaddr_in6 *)sa;
3952153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3953153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					error = EINVAL;
3954153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_TCB_UNLOCK(stcb);
3955153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3956153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					break;
3957153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				}
3958153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else
3959153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#endif
396075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
396175cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
396275cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
396375cd23222c96d5ebe5a9082c57a263f917f1462btuexen
396475cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
396575cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
396675cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
396775cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
396875cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
396975cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
397075cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
397175cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
397275cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
3973153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			{
3974153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				error = EAFNOSUPPORT;
3975153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_TCB_UNLOCK(stcb);
3976153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3977153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				break;
3978153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
3979153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
3980153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
3981153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (stcb) {
3982153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (net) {
3983153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				encaps->sue_port = net->port;
3984153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else {
3985153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				encaps->sue_port = stcb->asoc.port;
3986153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
3987153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			SCTP_TCB_UNLOCK(stcb);
3988153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		} else {
3989153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3990153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3991153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
3992153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_RLOCK(inp);
3993153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				encaps->sue_port = inp->sctp_ep.port;
3994153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_RUNLOCK(inp);
3995153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else {
3996153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3997153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				error = EINVAL;
3998153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
3999153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
4000153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (error == 0) {
4001443f94da739e8e8968e5eb93c2f82f73287cfd5dt			*optsize = sizeof(struct sctp_udpencaps);
4002153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
4003153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		break;
4004153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	}
4005aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t	case SCTP_ECN_SUPPORTED:
4006aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t	{
4007aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		struct sctp_assoc_value *av;
4008aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t
4009aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4010aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4011aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t
4012aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		if (stcb) {
4013aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			av->assoc_value = stcb->asoc.ecn_supported;
4014aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			SCTP_TCB_UNLOCK(stcb);
4015aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		} else {
4016aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4017aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4018aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4019aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				SCTP_INP_RLOCK(inp);
4020aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				av->assoc_value = inp->ecn_supported;
4021aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				SCTP_INP_RUNLOCK(inp);
4022aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			} else {
4023aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4024aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				error = EINVAL;
4025aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			}
4026aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		}
4027aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		if (error == 0) {
4028aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			*optsize = sizeof(struct sctp_assoc_value);
4029aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		}
4030aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		break;
4031aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t	}
4032a8657c4fc04fb9cc82100f648810d51ec6ab155at	case SCTP_PR_SUPPORTED:
4033a8657c4fc04fb9cc82100f648810d51ec6ab155at	{
4034a8657c4fc04fb9cc82100f648810d51ec6ab155at		struct sctp_assoc_value *av;
4035a8657c4fc04fb9cc82100f648810d51ec6ab155at
4036a8657c4fc04fb9cc82100f648810d51ec6ab155at		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4037a8657c4fc04fb9cc82100f648810d51ec6ab155at		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4038a8657c4fc04fb9cc82100f648810d51ec6ab155at
4039a8657c4fc04fb9cc82100f648810d51ec6ab155at		if (stcb) {
4040a8657c4fc04fb9cc82100f648810d51ec6ab155at			av->assoc_value = stcb->asoc.prsctp_supported;
4041a8657c4fc04fb9cc82100f648810d51ec6ab155at			SCTP_TCB_UNLOCK(stcb);
4042a8657c4fc04fb9cc82100f648810d51ec6ab155at		} else {
4043a8657c4fc04fb9cc82100f648810d51ec6ab155at			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4044a8657c4fc04fb9cc82100f648810d51ec6ab155at			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4045a8657c4fc04fb9cc82100f648810d51ec6ab155at			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4046a8657c4fc04fb9cc82100f648810d51ec6ab155at				SCTP_INP_RLOCK(inp);
4047a8657c4fc04fb9cc82100f648810d51ec6ab155at				av->assoc_value = inp->prsctp_supported;
4048a8657c4fc04fb9cc82100f648810d51ec6ab155at				SCTP_INP_RUNLOCK(inp);
4049a8657c4fc04fb9cc82100f648810d51ec6ab155at			} else {
4050a8657c4fc04fb9cc82100f648810d51ec6ab155at				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4051a8657c4fc04fb9cc82100f648810d51ec6ab155at				error = EINVAL;
4052a8657c4fc04fb9cc82100f648810d51ec6ab155at			}
4053a8657c4fc04fb9cc82100f648810d51ec6ab155at		}
4054a8657c4fc04fb9cc82100f648810d51ec6ab155at		if (error == 0) {
4055a8657c4fc04fb9cc82100f648810d51ec6ab155at			*optsize = sizeof(struct sctp_assoc_value);
4056a8657c4fc04fb9cc82100f648810d51ec6ab155at		}
4057a8657c4fc04fb9cc82100f648810d51ec6ab155at		break;
4058a8657c4fc04fb9cc82100f648810d51ec6ab155at	}
4059fb3816eaffe5878bb1286adb120fd160da178a05t	case SCTP_AUTH_SUPPORTED:
4060fb3816eaffe5878bb1286adb120fd160da178a05t	{
4061fb3816eaffe5878bb1286adb120fd160da178a05t		struct sctp_assoc_value *av;
4062fb3816eaffe5878bb1286adb120fd160da178a05t
4063fb3816eaffe5878bb1286adb120fd160da178a05t		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4064fb3816eaffe5878bb1286adb120fd160da178a05t		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4065fb3816eaffe5878bb1286adb120fd160da178a05t
4066fb3816eaffe5878bb1286adb120fd160da178a05t		if (stcb) {
4067fb3816eaffe5878bb1286adb120fd160da178a05t			av->assoc_value = stcb->asoc.auth_supported;
4068fb3816eaffe5878bb1286adb120fd160da178a05t			SCTP_TCB_UNLOCK(stcb);
4069fb3816eaffe5878bb1286adb120fd160da178a05t		} else {
4070fb3816eaffe5878bb1286adb120fd160da178a05t			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4071fb3816eaffe5878bb1286adb120fd160da178a05t			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4072fb3816eaffe5878bb1286adb120fd160da178a05t			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4073fb3816eaffe5878bb1286adb120fd160da178a05t				SCTP_INP_RLOCK(inp);
4074fb3816eaffe5878bb1286adb120fd160da178a05t				av->assoc_value = inp->auth_supported;
4075fb3816eaffe5878bb1286adb120fd160da178a05t				SCTP_INP_RUNLOCK(inp);
4076fb3816eaffe5878bb1286adb120fd160da178a05t			} else {
4077fb3816eaffe5878bb1286adb120fd160da178a05t				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4078fb3816eaffe5878bb1286adb120fd160da178a05t				error = EINVAL;
4079fb3816eaffe5878bb1286adb120fd160da178a05t			}
4080fb3816eaffe5878bb1286adb120fd160da178a05t		}
4081fb3816eaffe5878bb1286adb120fd160da178a05t		if (error == 0) {
4082fb3816eaffe5878bb1286adb120fd160da178a05t			*optsize = sizeof(struct sctp_assoc_value);
4083fb3816eaffe5878bb1286adb120fd160da178a05t		}
4084fb3816eaffe5878bb1286adb120fd160da178a05t		break;
4085fb3816eaffe5878bb1286adb120fd160da178a05t	}
4086fb3816eaffe5878bb1286adb120fd160da178a05t	case SCTP_ASCONF_SUPPORTED:
4087fb3816eaffe5878bb1286adb120fd160da178a05t	{
4088fb3816eaffe5878bb1286adb120fd160da178a05t		struct sctp_assoc_value *av;
4089fb3816eaffe5878bb1286adb120fd160da178a05t
4090fb3816eaffe5878bb1286adb120fd160da178a05t		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4091fb3816eaffe5878bb1286adb120fd160da178a05t		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4092fb3816eaffe5878bb1286adb120fd160da178a05t
4093fb3816eaffe5878bb1286adb120fd160da178a05t		if (stcb) {
4094fb3816eaffe5878bb1286adb120fd160da178a05t			av->assoc_value = stcb->asoc.asconf_supported;
4095fb3816eaffe5878bb1286adb120fd160da178a05t			SCTP_TCB_UNLOCK(stcb);
4096fb3816eaffe5878bb1286adb120fd160da178a05t		} else {
4097fb3816eaffe5878bb1286adb120fd160da178a05t			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4098fb3816eaffe5878bb1286adb120fd160da178a05t			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4099fb3816eaffe5878bb1286adb120fd160da178a05t			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4100fb3816eaffe5878bb1286adb120fd160da178a05t				SCTP_INP_RLOCK(inp);
4101fb3816eaffe5878bb1286adb120fd160da178a05t				av->assoc_value = inp->asconf_supported;
4102fb3816eaffe5878bb1286adb120fd160da178a05t				SCTP_INP_RUNLOCK(inp);
4103fb3816eaffe5878bb1286adb120fd160da178a05t			} else {
4104fb3816eaffe5878bb1286adb120fd160da178a05t				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4105fb3816eaffe5878bb1286adb120fd160da178a05t				error = EINVAL;
4106fb3816eaffe5878bb1286adb120fd160da178a05t			}
4107fb3816eaffe5878bb1286adb120fd160da178a05t		}
4108fb3816eaffe5878bb1286adb120fd160da178a05t		if (error == 0) {
4109fb3816eaffe5878bb1286adb120fd160da178a05t			*optsize = sizeof(struct sctp_assoc_value);
4110fb3816eaffe5878bb1286adb120fd160da178a05t		}
4111fb3816eaffe5878bb1286adb120fd160da178a05t		break;
4112fb3816eaffe5878bb1286adb120fd160da178a05t	}
41132344bfccffeb80545fca6a86e8cda3d56a6f50bft	case SCTP_RECONFIG_SUPPORTED:
41142344bfccffeb80545fca6a86e8cda3d56a6f50bft	{
41152344bfccffeb80545fca6a86e8cda3d56a6f50bft		struct sctp_assoc_value *av;
41162344bfccffeb80545fca6a86e8cda3d56a6f50bft
41172344bfccffeb80545fca6a86e8cda3d56a6f50bft		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
41182344bfccffeb80545fca6a86e8cda3d56a6f50bft		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
41192344bfccffeb80545fca6a86e8cda3d56a6f50bft
41202344bfccffeb80545fca6a86e8cda3d56a6f50bft		if (stcb) {
41212344bfccffeb80545fca6a86e8cda3d56a6f50bft			av->assoc_value = stcb->asoc.reconfig_supported;
41222344bfccffeb80545fca6a86e8cda3d56a6f50bft			SCTP_TCB_UNLOCK(stcb);
41232344bfccffeb80545fca6a86e8cda3d56a6f50bft		} else {
41242344bfccffeb80545fca6a86e8cda3d56a6f50bft			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
41252344bfccffeb80545fca6a86e8cda3d56a6f50bft			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
41262344bfccffeb80545fca6a86e8cda3d56a6f50bft			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
41272344bfccffeb80545fca6a86e8cda3d56a6f50bft				SCTP_INP_RLOCK(inp);
41282344bfccffeb80545fca6a86e8cda3d56a6f50bft				av->assoc_value = inp->reconfig_supported;
41292344bfccffeb80545fca6a86e8cda3d56a6f50bft				SCTP_INP_RUNLOCK(inp);
41302344bfccffeb80545fca6a86e8cda3d56a6f50bft			} else {
41312344bfccffeb80545fca6a86e8cda3d56a6f50bft				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
41322344bfccffeb80545fca6a86e8cda3d56a6f50bft				error = EINVAL;
41332344bfccffeb80545fca6a86e8cda3d56a6f50bft			}
41342344bfccffeb80545fca6a86e8cda3d56a6f50bft		}
41352344bfccffeb80545fca6a86e8cda3d56a6f50bft		if (error == 0) {
41362344bfccffeb80545fca6a86e8cda3d56a6f50bft			*optsize = sizeof(struct sctp_assoc_value);
41372344bfccffeb80545fca6a86e8cda3d56a6f50bft		}
41382344bfccffeb80545fca6a86e8cda3d56a6f50bft		break;
41392344bfccffeb80545fca6a86e8cda3d56a6f50bft	}
414044318e900a771ba1a5bafb510c38f33fd5cd8a39t	case SCTP_NRSACK_SUPPORTED:
414144318e900a771ba1a5bafb510c38f33fd5cd8a39t	{
414244318e900a771ba1a5bafb510c38f33fd5cd8a39t		struct sctp_assoc_value *av;
414344318e900a771ba1a5bafb510c38f33fd5cd8a39t
414444318e900a771ba1a5bafb510c38f33fd5cd8a39t		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
414544318e900a771ba1a5bafb510c38f33fd5cd8a39t		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
414644318e900a771ba1a5bafb510c38f33fd5cd8a39t
414744318e900a771ba1a5bafb510c38f33fd5cd8a39t		if (stcb) {
414844318e900a771ba1a5bafb510c38f33fd5cd8a39t			av->assoc_value = stcb->asoc.nrsack_supported;
414944318e900a771ba1a5bafb510c38f33fd5cd8a39t			SCTP_TCB_UNLOCK(stcb);
415044318e900a771ba1a5bafb510c38f33fd5cd8a39t		} else {
415144318e900a771ba1a5bafb510c38f33fd5cd8a39t			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
415244318e900a771ba1a5bafb510c38f33fd5cd8a39t			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
415344318e900a771ba1a5bafb510c38f33fd5cd8a39t			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
415444318e900a771ba1a5bafb510c38f33fd5cd8a39t				SCTP_INP_RLOCK(inp);
415544318e900a771ba1a5bafb510c38f33fd5cd8a39t				av->assoc_value = inp->nrsack_supported;
415644318e900a771ba1a5bafb510c38f33fd5cd8a39t				SCTP_INP_RUNLOCK(inp);
415744318e900a771ba1a5bafb510c38f33fd5cd8a39t			} else {
415844318e900a771ba1a5bafb510c38f33fd5cd8a39t				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
415944318e900a771ba1a5bafb510c38f33fd5cd8a39t				error = EINVAL;
416044318e900a771ba1a5bafb510c38f33fd5cd8a39t			}
416144318e900a771ba1a5bafb510c38f33fd5cd8a39t		}
416244318e900a771ba1a5bafb510c38f33fd5cd8a39t		if (error == 0) {
416344318e900a771ba1a5bafb510c38f33fd5cd8a39t			*optsize = sizeof(struct sctp_assoc_value);
416444318e900a771ba1a5bafb510c38f33fd5cd8a39t		}
416544318e900a771ba1a5bafb510c38f33fd5cd8a39t		break;
416644318e900a771ba1a5bafb510c38f33fd5cd8a39t	}
4167669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t	case SCTP_PKTDROP_SUPPORTED:
4168669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t	{
4169669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		struct sctp_assoc_value *av;
4170669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t
4171669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4172669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4173669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t
4174669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		if (stcb) {
4175669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			av->assoc_value = stcb->asoc.pktdrop_supported;
4176669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			SCTP_TCB_UNLOCK(stcb);
4177669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		} else {
4178669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4179669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4180669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4181669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				SCTP_INP_RLOCK(inp);
4182669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				av->assoc_value = inp->pktdrop_supported;
4183669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				SCTP_INP_RUNLOCK(inp);
4184669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			} else {
4185669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4186669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				error = EINVAL;
4187669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			}
4188669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		}
4189669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		if (error == 0) {
4190669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			*optsize = sizeof(struct sctp_assoc_value);
4191669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		}
4192669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		break;
4193669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t	}
41942d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen	case SCTP_ENABLE_STREAM_RESET:
41952d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen	{
41962d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		struct sctp_assoc_value *av;
41972d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen
41982d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
41992d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
42002d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen
42012d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		if (stcb) {
42022d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			av->assoc_value = (uint32_t)stcb->asoc.local_strreset_support;
42032d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			SCTP_TCB_UNLOCK(stcb);
42042d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		} else {
42052d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
42062d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
42072d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
42082d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				SCTP_INP_RLOCK(inp);
42092d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				av->assoc_value = (uint32_t)inp->local_strreset_support;
42102d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				SCTP_INP_RUNLOCK(inp);
42112d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			} else {
42122d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
42132d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				error = EINVAL;
42142d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			}
42152d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		}
42162d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		if (error == 0) {
42172d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			*optsize = sizeof(struct sctp_assoc_value);
42182d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		}
42192d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		break;
42202d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen	}
422120d5d287bff2075897105f85287230d55bdfa420t	case SCTP_PR_STREAM_STATUS:
422220d5d287bff2075897105f85287230d55bdfa420t	{
422320d5d287bff2075897105f85287230d55bdfa420t		struct sctp_prstatus *sprstat;
422420d5d287bff2075897105f85287230d55bdfa420t		uint16_t sid;
422520d5d287bff2075897105f85287230d55bdfa420t		uint16_t policy;
422620d5d287bff2075897105f85287230d55bdfa420t
422720d5d287bff2075897105f85287230d55bdfa420t		SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
422820d5d287bff2075897105f85287230d55bdfa420t		SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
422920d5d287bff2075897105f85287230d55bdfa420t
423020d5d287bff2075897105f85287230d55bdfa420t		sid = sprstat->sprstat_sid;
423120d5d287bff2075897105f85287230d55bdfa420t		policy = sprstat->sprstat_policy;
423220d5d287bff2075897105f85287230d55bdfa420t#if defined(SCTP_DETAILED_STR_STATS)
423320d5d287bff2075897105f85287230d55bdfa420t		if ((stcb != NULL) &&
423420d5d287bff2075897105f85287230d55bdfa420t		    (policy != SCTP_PR_SCTP_NONE) &&
423520d5d287bff2075897105f85287230d55bdfa420t		    (sid < stcb->asoc.streamoutcnt) &&
423620d5d287bff2075897105f85287230d55bdfa420t		    ((policy == SCTP_PR_SCTP_ALL) ||
423720d5d287bff2075897105f85287230d55bdfa420t		     (PR_SCTP_VALID_POLICY(policy)))) {
423820d5d287bff2075897105f85287230d55bdfa420t#else
423920d5d287bff2075897105f85287230d55bdfa420t		if ((stcb != NULL) &&
424020d5d287bff2075897105f85287230d55bdfa420t		    (policy != SCTP_PR_SCTP_NONE) &&
424120d5d287bff2075897105f85287230d55bdfa420t		    (sid < stcb->asoc.streamoutcnt) &&
424220d5d287bff2075897105f85287230d55bdfa420t		    (policy == SCTP_PR_SCTP_ALL)) {
424320d5d287bff2075897105f85287230d55bdfa420t#endif
424420d5d287bff2075897105f85287230d55bdfa420t			if (policy == SCTP_PR_SCTP_ALL) {
424520d5d287bff2075897105f85287230d55bdfa420t				sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
424620d5d287bff2075897105f85287230d55bdfa420t				sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
424720d5d287bff2075897105f85287230d55bdfa420t			} else {
424820d5d287bff2075897105f85287230d55bdfa420t				sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy];
424920d5d287bff2075897105f85287230d55bdfa420t				sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy];
425020d5d287bff2075897105f85287230d55bdfa420t			}
425120d5d287bff2075897105f85287230d55bdfa420t			SCTP_TCB_UNLOCK(stcb);
425220d5d287bff2075897105f85287230d55bdfa420t			*optsize = sizeof(struct sctp_prstatus);
425320d5d287bff2075897105f85287230d55bdfa420t		} else {
425420d5d287bff2075897105f85287230d55bdfa420t			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
425520d5d287bff2075897105f85287230d55bdfa420t			error = EINVAL;
425620d5d287bff2075897105f85287230d55bdfa420t		}
425720d5d287bff2075897105f85287230d55bdfa420t		break;
425820d5d287bff2075897105f85287230d55bdfa420t	}
425920d5d287bff2075897105f85287230d55bdfa420t	case SCTP_PR_ASSOC_STATUS:
426020d5d287bff2075897105f85287230d55bdfa420t	{
426120d5d287bff2075897105f85287230d55bdfa420t		struct sctp_prstatus *sprstat;
426220d5d287bff2075897105f85287230d55bdfa420t		uint16_t policy;
426320d5d287bff2075897105f85287230d55bdfa420t
426420d5d287bff2075897105f85287230d55bdfa420t		SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
426520d5d287bff2075897105f85287230d55bdfa420t		SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
426620d5d287bff2075897105f85287230d55bdfa420t
426720d5d287bff2075897105f85287230d55bdfa420t		policy = sprstat->sprstat_policy;
426820d5d287bff2075897105f85287230d55bdfa420t		if ((stcb != NULL) &&
426920d5d287bff2075897105f85287230d55bdfa420t		    (policy != SCTP_PR_SCTP_NONE) &&
427020d5d287bff2075897105f85287230d55bdfa420t		    ((policy == SCTP_PR_SCTP_ALL) ||
427120d5d287bff2075897105f85287230d55bdfa420t		     (PR_SCTP_VALID_POLICY(policy)))) {
427220d5d287bff2075897105f85287230d55bdfa420t			if (policy == SCTP_PR_SCTP_ALL) {
427320d5d287bff2075897105f85287230d55bdfa420t				sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0];
427420d5d287bff2075897105f85287230d55bdfa420t				sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0];
427520d5d287bff2075897105f85287230d55bdfa420t			} else {
427620d5d287bff2075897105f85287230d55bdfa420t				sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy];
427720d5d287bff2075897105f85287230d55bdfa420t				sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy];
427820d5d287bff2075897105f85287230d55bdfa420t			}
427920d5d287bff2075897105f85287230d55bdfa420t			SCTP_TCB_UNLOCK(stcb);
428020d5d287bff2075897105f85287230d55bdfa420t			*optsize = sizeof(struct sctp_prstatus);
428120d5d287bff2075897105f85287230d55bdfa420t		} else {
428220d5d287bff2075897105f85287230d55bdfa420t			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
428320d5d287bff2075897105f85287230d55bdfa420t			error = EINVAL;
428420d5d287bff2075897105f85287230d55bdfa420t		}
428520d5d287bff2075897105f85287230d55bdfa420t		break;
428620d5d287bff2075897105f85287230d55bdfa420t	}
42878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
42888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
42898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = ENOPROTOOPT;
42908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
42918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end switch (sopt->sopt_name) */
42928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error) {
42938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = 0;
42948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
42958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
42968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
42978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
42988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__) || defined(__Userspace__)
42998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
43008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
43018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
43028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
43038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
43048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    void *p)
43058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
43068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error, set_opt;
43078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t *mopt;
43088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb = NULL;
4309b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	struct sctp_inpcb *inp = NULL;
43108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
43118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (optval == NULL) {
43138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("optval is NULL\n");
43148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
43158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EINVAL);
43168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
43178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
43182fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
43198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("inp is NULL?\n");
43208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4321b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
43228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
43238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf_id = inp->def_vrf_id;
43248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = 0;
43268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (optname) {
43278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NODELAY:
43288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTOCLOSE:
43298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTO_ASCONF:
43308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EXPLICIT_EOR:
43318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DISABLE_FRAGMENTS:
43328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_USE_EXT_RCVINFO:
43338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_I_WANT_MAPPED_V4_ADDR:
43348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* copy in the option value */
43358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
43368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		set_opt = 0;
43378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error)
43388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
43398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (optname) {
43408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_DISABLE_FRAGMENTS:
43418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
43428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
43438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTO_ASCONF:
43448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
43458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * NOTE: we don't really support this flag
43468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
43478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
43488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* only valid for bound all sockets */
43498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
43508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (*mopt != 0)) {
43518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* forbidden by admin */
43528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
43538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (EPERM);
43548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
43558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
43568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
43578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
43588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EINVAL);
43598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
43608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
43618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_EXPLICIT_EOR:
43628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
43638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
43648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_USE_EXT_RCVINFO:
43658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
43668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
43678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_I_WANT_MAPPED_V4_ADDR:
43688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
43698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
43708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
43718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
43728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EINVAL);
43738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
43748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
43758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_NODELAY:
43768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			set_opt = SCTP_PCB_FLAGS_NODELAY;
43778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
43788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTOCLOSE:
43798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
43808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
43818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
43828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EINVAL);
43838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
43848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
43858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
43868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * The value is in ticks. Note this does not effect
43878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * old associations, only new ones.
43888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
43898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
43908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
43918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
43938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*mopt != 0) {
43948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, set_opt);
43958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
43968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, set_opt);
43978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
43998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
44008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_REUSE_PORT:
44018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
44028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
44038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND)  == 0) {
44048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't set it after we are bound */
44058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
44068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
44078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
44098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't do this for a 1-m socket */
44108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
44118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
44128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (optval)
44148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
44158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
44168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
44178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
44188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PARTIAL_DELIVERY_POINT:
44208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
44218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
44228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
44248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*value > SCTP_SB_LIMIT_RCV(so)) {
44258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
44268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
44278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
44288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->partial_delivery_point = *value;
44308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
44318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_FRAGMENT_INTERLEAVE:
44338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* not yet until we re-write sctp_recvmsg() */
44348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
44358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *level;
44368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
44388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*level == SCTP_FRAG_LEVEL_2) {
44398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
44408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
44418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (*level == SCTP_FRAG_LEVEL_1) {
44428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
44438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
44448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (*level == SCTP_FRAG_LEVEL_0) {
44458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
44468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
44478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
44498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
44508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
44518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
44538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CMT_ON_OFF:
44558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
44568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_assoc_value *av;
44578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
44598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (av->assoc_value > SCTP_CMT_MAX) {
44608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
44618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
44628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
4463000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			}
44648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
44658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
44668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.sctp_cmt_on_off = av->assoc_value;
44678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
44688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
44698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
44708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
44718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
44728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (av->assoc_id == SCTP_ALL_ASSOC)) {
44738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_WLOCK(inp);
44748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_cmt_on_off = av->assoc_value;
44758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_WUNLOCK(inp);
44768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
44778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
44788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (av->assoc_id == SCTP_ALL_ASSOC)) {
44798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RLOCK(inp);
44808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
44818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_TCB_LOCK(stcb);
44828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.sctp_cmt_on_off = av->assoc_value;
44838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_TCB_UNLOCK(stcb);
44848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
44858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RUNLOCK(inp);
44868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
44878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
44888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
44898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
44908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOPROTOOPT;
44918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
44938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PLUGGABLE_CC:
44948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
44958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
44968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
44978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
44998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((av->assoc_value != SCTP_CC_RFC2581) &&
45008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_CC_HSTCP) &&
45018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_CC_HTCP) &&
45028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_CC_RTCC)) {
45038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
45048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
45058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
45068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
45088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
45098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
45108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.congestion_control_module = av->assoc_value;
45118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
45128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
45138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
45148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
45158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
45178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
45188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
45198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
45208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
45218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
45228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
45238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
45248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
45258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
45278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
45288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
45298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
45308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
45318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
45328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.congestion_control_module = av->assoc_value;
45338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
45348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
45358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
45368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
45378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
45388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
45398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
45408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
45418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
45448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CC_OPTION:
45468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
45478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_cc_option *cc_opt;
45488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
45498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
45508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
45518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
45528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
45538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
45548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
45558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
45568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
45578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						(*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1, cc_opt);
45588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
45598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
45608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
45618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
45628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
45638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
45648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
45668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
45678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = ENOTSUP;
45688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
4569000a5bac556b28e74e4e98c540f66b1743e9312dtuexen				error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1,
45708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   cc_opt);
45718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
45738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
45758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PLUGGABLE_SS:
45778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
45788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
45798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
45808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
45818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((av->assoc_value != SCTP_SS_DEFAULT) &&
45828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
45838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
45848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_SS_PRIORITY) &&
45858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
45868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_SS_FIRST_COME)) {
45878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
45888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
45898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
45908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
45928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
45938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
45948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
45958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.stream_scheduling_module = av->assoc_value;
45968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
45978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
45988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
45998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
46008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
46018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
46028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
46038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
46048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
46058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
46068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
46088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
46098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
46108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
46118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
46128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
46138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
46148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.stream_scheduling_module = av->assoc_value;
46158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
46168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
46178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
46198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
46228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SS_VALUE:
46248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
46258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_stream_value *av;
46268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
46288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
46298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
46308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
46318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                                              av->stream_value) < 0) {
46328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
46338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
46348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
46368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
46378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (av->assoc_id == SCTP_CURRENT_ASSOC) {
46388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
46398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
46408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
46418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
46428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                                          &stcb->asoc,
46438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                                          &stcb->asoc.strmout[av->stream_id],
46448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                                          av->stream_value);
46458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
46468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
4648000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
46498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
46508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Can't set stream value without association */
46518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
46528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
46538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
46568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CLR_STAT_LOG:
46588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
46598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EOPNOTSUPP;
46608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
46618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CONTEXT:
46628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
46638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
46648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
46668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
46678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
46698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.context = av->assoc_value;
46708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
46718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
46728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
46738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
46748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
46758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
46768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
46778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_context = av->assoc_value;
46788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
46798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
46818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
46828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
46838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
46848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
46858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.context = av->assoc_value;
46868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
46878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
46898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
46928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_VRF_ID:
46948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
46958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *default_vrfid;
46968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
46978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int i;
46988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
46998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
47008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*default_vrfid > SCTP_MAX_VRF_ID) {
47018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
47038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
47048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
47068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < inp->num_vrfs; i++) {
47078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* The VRF must be in the VRF list */
47088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (*default_vrfid == inp->m_vrf_ids[i]) {
47098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
4710e2828360ea9cf8951730d46f5c14626c9425cb30t				inp->def_vrf_id = *default_vrfid;
47118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
47128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto sctp_done;
47138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
47178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
47188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->def_vrf_id = *default_vrfid;
47198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
47208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
47218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_done:
47228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
47238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
47248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
47258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEL_VRF_ID:
47268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
47278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
47288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *del_vrfid;
47298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int i, fnd = 0;
47308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
47318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(del_vrfid, optval, uint32_t, optsize);
47328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*del_vrfid > SCTP_MAX_VRF_ID) {
47338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
47358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
47368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->num_vrfs == 1) {
47388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't delete last one */
47398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
47418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
47428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
47448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't add more once you are bound */
47458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
47478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
47488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
47508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < inp->num_vrfs; i++) {
47518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (*del_vrfid == inp->m_vrf_ids[i]) {
47528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				fnd = 1;
47538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
47548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!fnd) {
47578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
47598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
47608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (i != (inp->num_vrfs - 1)) {
47628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Take bottom one and move to this slot */
47638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->m_vrf_ids[i] = inp->m_vrf_ids[(inp->num_vrfs-1)];
47648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*del_vrfid == inp->def_vrf_id) {
47668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Take the first one as the new default */
47678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->def_vrf_id = inp->m_vrf_ids[0];
47688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Drop the number by one killing last one */
47708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->num_vrfs--;
47718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
47728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
47738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EOPNOTSUPP;
47748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
47758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
47768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
47778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ADD_VRF_ID:
47788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
47798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
47808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *add_vrfid;
47818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int i;
47828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
47838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(add_vrfid, optval, uint32_t, optsize);
47848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*add_vrfid > SCTP_MAX_VRF_ID) {
47858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
47878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
47888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
47908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't add more once you are bound */
47918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
47938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
47948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
47968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Verify its not already here */
47978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < inp->num_vrfs; i++) {
47988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (*add_vrfid == inp->m_vrf_ids[i]) {
47998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
48008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EALREADY;
48018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
48028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
48038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->num_vrfs + 1) > inp->vrf_size) {
48068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* need to grow array */
48078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint32_t *tarray;
48088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_MALLOC(tarray, uint32_t *,
48098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (sizeof(uint32_t) * (inp->vrf_size + SCTP_DEFAULT_VRF_SIZE)),
48108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_M_MVRF);
48118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tarray == NULL) {
48128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
48138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = ENOMEM;
48148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
48158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
48168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(tarray, inp->m_vrf_ids, (sizeof(uint32_t) * inp->vrf_size));
48188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF);
48198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->m_vrf_ids = tarray;
48208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->vrf_size += SCTP_DEFAULT_VRF_SIZE;
48218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->m_vrf_ids[inp->num_vrfs] = *add_vrfid;
48238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->num_vrfs++;
48248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
48258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
48268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
48278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EOPNOTSUPP;
48288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4829e2828360ea9cf8951730d46f5c14626c9425cb30t		break;
48308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DELAYED_SACK:
48328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
48338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sack_info *sack;
48348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
48368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
48378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sack->sack_delay) {
48388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
48398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sack->sack_delay = SCTP_MAX_SACK_DELAY;
48408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
48418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sack->sack_delay = TICKS_TO_MSEC(1);
48428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
48458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sack->sack_delay) {
48468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.delayed_ack = sack->sack_delay;
48478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sack->sack_freq) {
48498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.sack_freq = sack->sack_freq;
48508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
48528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
48538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
48548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
48558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
48568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
48578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
48588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sack->sack_delay) {
48598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
48608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
48618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sack->sack_freq) {
48628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
48638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
48648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
48658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
48678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
48688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
48698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
48708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
48718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sack->sack_delay) {
48728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.delayed_ack = sack->sack_delay;
48738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
48748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sack->sack_freq) {
48758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.sack_freq = sack->sack_freq;
48768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
48778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
48788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
48798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
48808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
48838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_CHUNK:
48858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
48868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authchunk *sauth;
48878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
48898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
48918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
48928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
48938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
48948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
48968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
48978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_KEY:
48998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
49008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authkey *sca;
49018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_keyhead *shared_keys;
49028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_sharedkey_t *shared_key;
49038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_key_t *key = NULL;
49048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t size;
49058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
49068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
49078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sca->sca_keylength == 0) {
49088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			size = optsize - sizeof(struct sctp_authkey);
49098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
49108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
49118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				size = sca->sca_keylength;
49128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
49138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
49148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
49158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
49168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
49198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
49208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
49218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			shared_keys = &stcb->asoc.shared_keys;
49228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* clear the cached keys for this key id */
49238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
49248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
49258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * create the new shared key and
49268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * insert/replace it
49278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
49288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (size > 0) {
49298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				key = sctp_set_key(sca->sca_key, (uint32_t) size);
49308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (key == NULL) {
49318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
49328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = ENOMEM;
49338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
49348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
49358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
49368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			shared_key = sctp_alloc_sharedkey();
49388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (shared_key == NULL) {
49398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_key(key);
49408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
49418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = ENOMEM;
49428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
49438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
49448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			shared_key->key = key;
49468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			shared_key->keyid = sca->sca_keynumber;
49478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = sctp_insert_sharedkey(shared_keys, shared_key);
49488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
49498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
49508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
49518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
49528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
49538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
49548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
49558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				shared_keys = &inp->sctp_ep.shared_keys;
49568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
49578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * clear the cached keys on all assocs for
49588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * this key id
49598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
49608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
49618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
49628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * create the new shared key and
49638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * insert/replace it
49648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
49658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (size > 0) {
49668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					key = sctp_set_key(sca->sca_key, (uint32_t) size);
49678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (key == NULL) {
49688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
49698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						error = ENOMEM;
49708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_INP_WUNLOCK(inp);
49718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
49728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
49738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
49748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				shared_key = sctp_alloc_sharedkey();
49758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (shared_key == NULL) {
49768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_free_key(key);
49778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
49788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = ENOMEM;
49798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_WUNLOCK(inp);
49808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
49818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
49828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				shared_key->key = key;
49838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				shared_key->keyid = sca->sca_keynumber;
49848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = sctp_insert_sharedkey(shared_keys, shared_key);
49858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
49868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
49888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
49898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
49908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
49918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
49928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					shared_keys = &stcb->asoc.shared_keys;
49938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* clear the cached keys for this key id */
49948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
49958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
49968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * create the new shared key and
49978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * insert/replace it
49988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
49998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (size > 0) {
50008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						key = sctp_set_key(sca->sca_key, (uint32_t) size);
50018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (key == NULL) {
50028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							SCTP_TCB_UNLOCK(stcb);
50038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
50048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
50058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
50068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					shared_key = sctp_alloc_sharedkey();
50078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (shared_key == NULL) {
50088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_free_key(key);
50098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_TCB_UNLOCK(stcb);
50108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
50118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
50128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					shared_key->key = key;
50138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					shared_key->keyid = sca->sca_keynumber;
50148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = sctp_insert_sharedkey(shared_keys, shared_key);
50158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
50168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
50178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
50188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
50198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
50208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
50218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
50228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_HMAC_IDENT:
50238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
50248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_hmacalgo *shmac;
50258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmaclist_t *hmaclist;
50268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint16_t hmacid;
50278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t i;
50288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
50308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
50318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
50328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
50338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
50348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5035000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
50368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
50378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hmaclist == NULL) {
50388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
50398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOMEM;
50408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
50418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
50428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < shmac->shmac_number_of_idents; i++) {
50438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hmacid = shmac->shmac_idents[i];
50448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
50458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* invalid HMACs were found */;
50468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
50478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
50488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_hmaclist(hmaclist);
50498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto sctp_set_hmac_done;
50508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
50518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
50528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < hmaclist->num_algo; i++) {
50538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
50548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* already in list */
505517fca683d16802e8836f92ca2d9761a4798ada4bt				break;
50568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
50578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
505817fca683d16802e8836f92ca2d9761a4798ada4bt		if (i == hmaclist->num_algo) {
505917fca683d16802e8836f92ca2d9761a4798ada4bt			/* not found in list */
50608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_hmaclist(hmaclist);
50618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
50628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
50638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
50648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
50658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* set it on the endpoint */
50668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
50678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_ep.local_hmacs)
50688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
50698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->sctp_ep.local_hmacs = hmaclist;
50708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
50718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_set_hmac_done:
50728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
50738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
50748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_ACTIVE_KEY:
50758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
50768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authkeyid *scact;
50778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
50798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
50808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* set the active key on the right place */
50828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
50838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* set the active key on the assoc */
50848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_auth_setactivekey(stcb,
50858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						   scact->scact_keynumber)) {
50868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
50878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    SCTP_FROM_SCTP_USRREQ,
50888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    EINVAL);
50898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
50908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
50918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
50928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
50938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
50948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
50958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
50968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
50978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
50988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
50998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
51008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
51018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
51028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
51038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
51058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
51068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
51078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
51088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
51098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_auth_setactivekey(stcb, scact->scact_keynumber);
51108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
51118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
51128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
51138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
51168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_DELETE_KEY:
51188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
51198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authkeyid *scdel;
51208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
51228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
51238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* delete the key from the right place */
51258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
51268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
51278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
51288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
51298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
51318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
51328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
51338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
51348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
51358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
51368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
51378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
51388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
51398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
51408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
51418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
51428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
51448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
51458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
51468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
51478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
51488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
51498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
51508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
51518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
51528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
51558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_DEACTIVATE_KEY:
51578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
51588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authkeyid *keyid;
51598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
51618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
51628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* deactivate the key from the right place */
51648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
51658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
51668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
51678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
51688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
51708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
51718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
51728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
51738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
51748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
51758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
51768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
51778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
51788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
51798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
51808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
51818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
51838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
51848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
51858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
51868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
51878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
51888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
51898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
51908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
51918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
51948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5195c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	case SCTP_ENABLE_STREAM_RESET:
5196c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	{
5197c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		struct sctp_assoc_value *av;
51982d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen
5199c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5200c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
5201c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5202c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EINVAL;
5203c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5204c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5205c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5206c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stcb) {
52072d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
5208c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_TCB_UNLOCK(stcb);
5209c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		} else {
5210c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5211c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5212c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
5213c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
5214c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_INP_WLOCK(inp);
52152d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				inp->local_strreset_support = (uint8_t)av->assoc_value;
5216c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_INP_WUNLOCK(inp);
5217c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			}
5218c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
5219c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
5220c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_INP_RLOCK(inp);
5221c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5222c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen					SCTP_TCB_LOCK(stcb);
52232d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen					stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
5224c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen					SCTP_TCB_UNLOCK(stcb);
5225c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				}
5226c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_INP_RUNLOCK(inp);
5227c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			}
52288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5229c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5230c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		break;
5231c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	}
52328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RESET_STREAMS:
52338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
5234000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		struct sctp_reset_streams *strrst;
52351de509107029a81699453f86fcced3c7b7fb534btuexen		int i, send_out = 0;
52361de509107029a81699453f86fcced3c7b7fb534btuexen		int send_in = 0;
52378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5238c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
5239c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
52408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
52418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
52428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT;
52438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
52448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52452344bfccffeb80545fca6a86e8cda3d56a6f50bft		if (stcb->asoc.reconfig_supported == 0) {
52468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
5247c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			 * Peer does not support the chunk type.
52488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
5249c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5250c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EOPNOTSUPP;
5251c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_TCB_UNLOCK(stcb);
5252c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5253c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
52548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.stream_reset_outstanding) {
52558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
52568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EALREADY;
52578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
52588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
52598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5260c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
52618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			send_in = 1;
5262c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5263c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
52648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			send_out = 1;
5265c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5266c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if ((send_in == 0) && (send_out == 0)) {
5267c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5268c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EINVAL;
5269c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_TCB_UNLOCK(stcb);
5270c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5271c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5272c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		for (i = 0; i < strrst->srs_number_streams; i++) {
5273c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if ((send_in) &&
5274c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
5275c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
52768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
5277c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				break;
52788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5279c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if ((send_out) &&
5280c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
5281c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5282c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				error = EINVAL;
5283c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				break;
52848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5285c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5286c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (error) {
5287c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_TCB_UNLOCK(stcb);
5288c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5289c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5290c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
5291c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen						strrst->srs_stream_list,
5292c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen						send_out, send_in, 0, 0, 0, 0, 0);
5293c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen
5294c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5295c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_TCB_UNLOCK(stcb);
5296c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		break;
5297c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	}
5298c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	case SCTP_ADD_STREAMS:
5299c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	{
5300c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		struct sctp_add_streams *stradd;
53011de509107029a81699453f86fcced3c7b7fb534btuexen		uint8_t addstream = 0;
53021de509107029a81699453f86fcced3c7b7fb534btuexen		uint16_t add_o_strmcnt = 0;
53031de509107029a81699453f86fcced3c7b7fb534btuexen		uint16_t add_i_strmcnt = 0;
5304c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen
5305c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
5306c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
5307c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stcb == NULL) {
5308c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5309c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = ENOENT;
5310c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5311c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
53122344bfccffeb80545fca6a86e8cda3d56a6f50bft		if (stcb->asoc.reconfig_supported == 0) {
53131de509107029a81699453f86fcced3c7b7fb534btuexen			/*
53141de509107029a81699453f86fcced3c7b7fb534btuexen			 * Peer does not support the chunk type.
53151de509107029a81699453f86fcced3c7b7fb534btuexen			 */
53161de509107029a81699453f86fcced3c7b7fb534btuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
53171de509107029a81699453f86fcced3c7b7fb534btuexen			error = EOPNOTSUPP;
53181de509107029a81699453f86fcced3c7b7fb534btuexen			SCTP_TCB_UNLOCK(stcb);
53191de509107029a81699453f86fcced3c7b7fb534btuexen			break;
53201de509107029a81699453f86fcced3c7b7fb534btuexen		}
53211de509107029a81699453f86fcced3c7b7fb534btuexen		if (stcb->asoc.stream_reset_outstanding) {
53221de509107029a81699453f86fcced3c7b7fb534btuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
53231de509107029a81699453f86fcced3c7b7fb534btuexen			error = EALREADY;
53241de509107029a81699453f86fcced3c7b7fb534btuexen			SCTP_TCB_UNLOCK(stcb);
53251de509107029a81699453f86fcced3c7b7fb534btuexen			break;
53261de509107029a81699453f86fcced3c7b7fb534btuexen		}
5327c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if ((stradd->sas_outstrms == 0) &&
5328c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		    (stradd->sas_instrms == 0)) {
5329c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EINVAL;
5330c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			goto skip_stuff;
5331c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5332c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stradd->sas_outstrms) {
53338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			addstream = 1;
53348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We allocate here */
5335c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			add_o_strmcnt = stradd->sas_outstrms;
5336c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
53378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* You can't have more than 64k */
53388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
53398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto skip_stuff;
53408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5342c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stradd->sas_instrms) {
5343c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			int cnt;
53448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5345c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			addstream |= 2;
5346c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			/* We allocate inside sctp_send_str_reset_req() */
5347c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			add_i_strmcnt = stradd->sas_instrms;
5348c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			cnt = add_i_strmcnt;
5349c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			cnt += stcb->asoc.streamincnt;
5350c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if (cnt > 0x0000ffff) {
5351c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				/* You can't have more than 64k */
53528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
5353c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				goto skip_stuff;
53548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5355c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if (cnt > (int)stcb->asoc.max_inbound_streams) {
5356c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				/* More than you are allowed */
53578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
5358c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				goto skip_stuff;
53598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5361c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
5362c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
53638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skip_stuff:
5364c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_TCB_UNLOCK(stcb);
5365c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		break;
5366c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	}
5367c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	case SCTP_RESET_ASSOC:
5368c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	{
5369c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		uint32_t *value;
5370c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen
5371c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
5372c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
5373c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stcb == NULL) {
5374c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5375c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = ENOENT;
5376c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5377c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
53782344bfccffeb80545fca6a86e8cda3d56a6f50bft		if (stcb->asoc.reconfig_supported == 0) {
5379c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			/*
5380c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			 * Peer does not support the chunk type.
5381c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			 */
5382c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5383c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EOPNOTSUPP;
53848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
53858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
53868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5387c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stcb->asoc.stream_reset_outstanding) {
5388c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5389c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EALREADY;
5390c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_TCB_UNLOCK(stcb);
5391c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5392c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5393c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
53948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
53958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
53968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
53978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
53988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CONNECT_X:
53998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
54008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
54018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
54028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
54038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
54048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
54058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
54068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CONNECT_X_DELAYED:
54078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
54088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
54098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
54108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
54118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
54128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
54138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
54148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CONNECT_X_COMPLETE:
54158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
54168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr *sa;
54178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
54188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* FIXME MT: check correct? */
54208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
54218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* find tcb */
54238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
54248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RLOCK(inp);
54258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = LIST_FIRST(&inp->sctp_asoc_list);
54268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
54278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_LOCK(stcb);
54288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net = sctp_findnet(stcb, sa);
54298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
54318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
54328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
54338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
54348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
54358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
54368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
54378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
54388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
54398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
54408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
54428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
54448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
54458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT;
54468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
54478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
54488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.delayed_connection == 1) {
54498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.delayed_connection = 0;
54508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
54518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
54528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.primary_destination,
54538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_FROM_SCTP_USRREQ+SCTP_LOC_9);
54548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
54558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
54568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
54578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * already expired or did not use delayed
54588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * connectx
54598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
54608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
54618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EALREADY;
54628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
54638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
54648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
54658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
54668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_MAX_BURST:
54678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
54688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 900000
54698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint8_t *burst;
54708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(burst, optval, uint8_t, optsize);
54728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
54748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->sctp_ep.max_burst = *burst;
54758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
54768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
54778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
54788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
54808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
54818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
54838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.max_burst = av->assoc_value;
54848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
54858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
54868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
54878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
54888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
54898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
54908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
54918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.max_burst = av->assoc_value;
54928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
54938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
54958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
54968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
54978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
54988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
54998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.max_burst = av->assoc_value;
55008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
55018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
55028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
55038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
55048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
55068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
55078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
55088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_MAXSEG:
55098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
55108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
55118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int ovh;
55128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
55148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
55158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
55178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ovh = SCTP_MED_OVERHEAD;
55188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ovh = SCTP_MED_V4_OVERHEAD;
55208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
55228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (av->assoc_value) {
55238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
55248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
55258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
55268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
55278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
55288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
55308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
55318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
55328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
55338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* FIXME MT: I think this is not in tune with the API ID */
55348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (av->assoc_value) {
55358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_frag_point = (av->assoc_value + ovh);
55368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
55378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
55388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
55398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
55408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
55418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
55428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
55438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
55448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
55468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
55478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EVENTS:
55488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
55498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_event_subscribe *events;
55508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
55528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
55548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_data_io_event) {
55558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
55568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
55588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_association_event) {
55618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
55628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
55648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_address_event) {
55678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
55688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
55708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_send_failure_event) {
55738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
55748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
55768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_peer_error_event) {
55798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
55808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
55828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_shutdown_event) {
55858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
55868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
55888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_partial_delivery_event) {
55918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
55928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
55948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_adaptation_layer_event) {
55978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
55988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
56008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
56018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_authentication_event) {
56038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
56048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
56058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
56068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
56078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_sender_dry_event) {
56098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
56108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
56118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
56128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
56138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_stream_reset_event) {
56158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
56168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
56178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
56188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
56198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
56208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
56228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
56238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(stcb);
56248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_association_event) {
56258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
56268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
56288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_address_event) {
56308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
56318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
56338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_send_failure_event) {
56358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
56368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
56388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_peer_error_event) {
56408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
56418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
56438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_shutdown_event) {
56458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
56468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
56488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_partial_delivery_event) {
56508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
56518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
56538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_adaptation_layer_event) {
56558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
56568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
56588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_authentication_event) {
56608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
56618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
56638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_sender_dry_event) {
56658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
56668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
56688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_stream_reset_event) {
56708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
56718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
56738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
56758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
56768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Send up the sender dry event only for 1-to-1 style sockets. */
56778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_sender_dry_event) {
56788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
56798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
56808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb = LIST_FIRST(&inp->sctp_asoc_list);
56818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb) {
56828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
56838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
56848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
56858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (stcb->asoc.stream_queue_cnt == 0)) {
56868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
56878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
56888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
56898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
56908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
56918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
56928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
56938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
56948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
56958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ADAPTATION_LAYER:
56968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
56978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_setadaptation *adap_bits;
56988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
57008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
57018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
57029a8642036bc992ec39f872443a35f8c545cc28c4t		inp->sctp_ep.adaptation_layer_indicator_provided = 1;
57038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
57048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
57058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
57068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG
57078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SET_INITIAL_DBG_SEQ:
57088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
57098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *vvv;
57108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
57118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
57128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
57138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->sctp_ep.initial_sequence_debug = *vvv;
57148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
57158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
57168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
57178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_SEND_PARAM:
57198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
57208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sndrcvinfo *s_info;
57218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
57228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
57238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
57248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
57258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
57268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
57278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
57288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
57298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
57308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
57318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
57328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
57338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
57348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
57358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
57368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
57378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
57388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
57398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
57408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
57418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
57428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
57438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
57448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
57458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
57468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
57478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
57488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
57498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
57508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
57518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
57528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
57538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
57548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
57558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
57568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
57578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEER_ADDR_PARAMS:
57588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
57598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paddrparams *paddrp;
57608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
57618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
57628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
57638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
57648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
57658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
57668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
57678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
57688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
57698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
57708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
57718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
57728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
57738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp,
57748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    (struct sockaddr *)&paddrp->spp_address,
57758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    &net, NULL, NULL);
57768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
57778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
57788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
57798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5780b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (stcb && (net == NULL)) {
57818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr *sa;
57828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
57838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sa = (struct sockaddr *)&paddrp->spp_address;
57848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
57858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET) {
57868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
57878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in *sin;
57888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin = (struct sockaddr_in *)sa;
57898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin->sin_addr.s_addr) {
57908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
57918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
57928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
57938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
57948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
57958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
57968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
57988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET6) {
57998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in6 *sin6;
58008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6 = (struct sockaddr_in6 *)sa;
58028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
58038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
58048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
58058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
58068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
58078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
58098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
581075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
581175cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
581275cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
581375cd23222c96d5ebe5a9082c57a263f917f1462btuexen
581475cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
581575cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
581675cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
581775cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
581875cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
581975cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
582075cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
582175cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
582275cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
58238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			{
58248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EAFNOSUPPORT;
58258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
58268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
58278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
58288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
58298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
58308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* sanity checks */
58318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
58328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb)
58338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
58348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
58358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
58368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
58378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
58398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb)
58408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
58418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
58428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
58438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
58448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
58468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/************************TCB SPECIFIC SET ******************/
58478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
58488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do we change the timer for HB, we run
58498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * only one?
58508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
5851b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			int ovh = 0;
58528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
58548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				ovh = SCTP_MED_OVERHEAD;
58558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
58568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				ovh = SCTP_MED_V4_OVERHEAD;
58578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
58588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* network sets ? */
58608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net) {
58618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/************************NET SPECIFIC SET ******************/
58628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_DISABLE) {
58638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
58648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    !(net->dest_state & SCTP_ADDR_NOHB)) {
58658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
58668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
58678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
58688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state |= SCTP_ADDR_NOHB;
58698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_ENABLE) {
58718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (paddrp->spp_hbinterval) {
58728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->heart_beat_delay = paddrp->spp_hbinterval;
58738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
58748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->heart_beat_delay = 0;
58758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
58768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
58778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
58788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
58798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state &= ~SCTP_ADDR_NOHB;
58808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_DEMAND) {
58828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* on demand HB */
58838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5884a4ffbccf5bed12adde7673f02ca4b0ca3214262ctuexen					sctp_chunk_output(inp, stcb,  SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
58858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
58868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
58888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
58898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
58908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
58918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
58928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state |= SCTP_ADDR_NO_PMTUD;
5893b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t					net->mtu = paddrp->spp_pathmtu + ovh;
5894b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t					if (net->mtu < stcb->asoc.smallest_mtu) {
5895b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t						sctp_pathmtu_adjustment(stcb, net->mtu);
58968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
58978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
58998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
59008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
59018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
59028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
59038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
59048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_pathmaxrxt) {
59058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->dest_state & SCTP_ADDR_PF) {
59068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->error_count > paddrp->spp_pathmaxrxt) {
59078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state &= ~SCTP_ADDR_PF;
59088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
59098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
59108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
59118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (net->error_count > net->pf_threshold)) {
59128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state |= SCTP_ADDR_PF;
59138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
59148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
59158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
59168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
59178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
59188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->dest_state & SCTP_ADDR_REACHABLE) {
59198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->error_count > paddrp->spp_pathmaxrxt) {
5920e2828360ea9cf8951730d46f5c14626c9425cb30t							net->dest_state &= ~SCTP_ADDR_REACHABLE;
592147674b651417d493ff4e0318113fd7beeef119dbtuexen							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
59228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
59238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
59248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->error_count <= paddrp->spp_pathmaxrxt) {
59258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state |= SCTP_ADDR_REACHABLE;
592647674b651417d493ff4e0318113fd7beeef119dbtuexen							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
59278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
59288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
59298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->failure_threshold = paddrp->spp_pathmaxrxt;
59308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
59318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_DSCP) {
59328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dscp = paddrp->spp_dscp & 0xfc;
59338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dscp |= 0x01;
59348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
59358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
59368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
59378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->ro._l_addr.sa.sa_family == AF_INET6) {
59388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
59398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->flowlabel |= 0x80000000;
59408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
59418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
59428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
59438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
59448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
59458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_pathmaxrxt) {
59468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
59478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
59488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->dest_state & SCTP_ADDR_PF) {
59498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (net->error_count > paddrp->spp_pathmaxrxt) {
59508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								net->dest_state &= ~SCTP_ADDR_PF;
59518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
59528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else {
59538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
59548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    (net->error_count > net->pf_threshold)) {
59558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								net->dest_state |= SCTP_ADDR_PF;
59568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
59578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
59588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
59598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
59608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
59618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->dest_state & SCTP_ADDR_REACHABLE) {
59628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (net->error_count > paddrp->spp_pathmaxrxt) {
5963e2828360ea9cf8951730d46f5c14626c9425cb30t								net->dest_state &= ~SCTP_ADDR_REACHABLE;
596447674b651417d493ff4e0318113fd7beeef119dbtuexen								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
59658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
59668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else {
59678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (net->error_count <= paddrp->spp_pathmaxrxt) {
59688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								net->dest_state |= SCTP_ADDR_REACHABLE;
596947674b651417d493ff4e0318113fd7beeef119dbtuexen								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
59708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
59718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
59728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->failure_threshold = paddrp->spp_pathmaxrxt;
59738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
59748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
59758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
59768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_ENABLE) {
59778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (paddrp->spp_hbinterval) {
59788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
59798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
59808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.heart_beat_delay = 0;
59818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
59828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Turn back on the timer */
59838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
59848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (paddrp->spp_hbinterval) {
59858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->heart_beat_delay = paddrp->spp_hbinterval;
59868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
59878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->heart_beat_delay = 0;
59888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
59898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->dest_state & SCTP_ADDR_NOHB) {
59908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state &= ~SCTP_ADDR_NOHB;
59918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
59928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
59938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
59948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
59958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
59968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
59978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
59988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_DISABLE) {
59998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
60008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (!(net->dest_state & SCTP_ADDR_NOHB)) {
60018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state |= SCTP_ADDR_NOHB;
60028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
60038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
60048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
60058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
60068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
60078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
60088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
60108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
60118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
60128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
60138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
60148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
60158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dest_state |= SCTP_ADDR_NO_PMTUD;
6016b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t						net->mtu = paddrp->spp_pathmtu + ovh;
6017b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t						if (net->mtu < stcb->asoc.smallest_mtu) {
6018b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t							sctp_pathmtu_adjustment(stcb, net->mtu);
60198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
60208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
60218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
60228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
60248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
60258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
60268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
60278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
60288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
60298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
60308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
60318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_DSCP) {
60338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
60348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dscp = paddrp->spp_dscp & 0xfc;
60358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dscp |= 0x01;
60368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
60378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
60388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.default_dscp |= 0x01;
60398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
60418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
60428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
60438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->ro._l_addr.sa.sa_family == AF_INET6) {
60448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
60458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->flowlabel |= 0x80000000;
60468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
60478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
60488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
60498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.default_flowlabel |= 0x80000000;
60508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
60528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
60538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
60548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
60558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/************************NO TCB, SET TO default stuff ******************/
60568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
60578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
60588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
60598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
60608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
60618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * For the TOS/FLOWLABEL stuff you set it
60628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * with the options on the socket
60638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
60648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_pathmaxrxt) {
60658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
60668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
60688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
60698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
60708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else if (paddrp->spp_hbinterval) {
60718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
60728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						paddrp->spp_hbinterval= SCTP_MAX_HB_INTERVAL;
60738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
60748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
60768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_ENABLE) {
60778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
60788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
60798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else if (paddrp->spp_hbinterval) {
60808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
60818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
60828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
60838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
60848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
60858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
60878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
60888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
60898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
60908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_DSCP) {
60928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
60938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.default_dscp |= 0x01;
60948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
60968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
60978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
60988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
60998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						inp->sctp_ep.default_flowlabel |= 0x80000000;
61008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
61018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
61028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
61038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
61048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
61058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
61068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
61078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
61098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
61108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
61118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RTOINFO:
61128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
61138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_rtoinfo *srto;
61148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t new_init, new_min, new_max;
61158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
61168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
61178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
61188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
61198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
61208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (srto->srto_initial)
61218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_init = srto->srto_initial;
61228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
61238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_init = stcb->asoc.initial_rto;
61248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (srto->srto_max)
61258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_max = srto->srto_max;
61268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
61278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_max = stcb->asoc.maxrto;
61288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (srto->srto_min)
61298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_min = srto->srto_min;
61308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
61318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_min = stcb->asoc.minrto;
61328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((new_min <= new_init) && (new_init <= new_max)) {
61338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.initial_rto = new_init;
61348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.maxrto = new_max;
61358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.minrto = new_min;
61368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
61378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
61388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
61398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
61418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
61428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
61438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
61448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
61458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
61468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (srto->srto_initial)
61478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_init = srto->srto_initial;
61488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
61498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_init = inp->sctp_ep.initial_rto;
61508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (srto->srto_max)
61518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_max = srto->srto_max;
61528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
61538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_max = inp->sctp_ep.sctp_maxrto;
61548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (srto->srto_min)
61558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_min = srto->srto_min;
61568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
61578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_min = inp->sctp_ep.sctp_minrto;
61588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((new_min <= new_init) && (new_init <= new_max)) {
61598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.initial_rto = new_init;
61608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_maxrto = new_max;
61618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_minrto = new_min;
61628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
61638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
61648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
61658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
61668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
61678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
61688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
61698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
6170000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			}
61718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
61728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
61738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
61748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ASSOCINFO:
61758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
61768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assocparams *sasoc;
61778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
61788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
61798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
61808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sasoc->sasoc_cookie_life) {
61818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* boundary check the cookie life */
61828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sasoc->sasoc_cookie_life < 1000)
61838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_cookie_life = 1000;
61848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
61858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
61868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
61888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
61898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sasoc->sasoc_asocmaxrxt)
61908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
61918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sasoc->sasoc_cookie_life) {
61928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
61938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
61958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
61968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
61978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
61988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
61998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
62008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sasoc->sasoc_asocmaxrxt)
62018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
62028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sasoc->sasoc_cookie_life) {
62038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
62048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
62058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
62068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
62078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
62088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
6209000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			}
62108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
62118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
62128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
62138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_INITMSG:
62148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
62158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_initmsg *sinit;
62168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
62178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
62188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
62198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sinit->sinit_num_ostreams)
62208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
62218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
62228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sinit->sinit_max_instreams)
62238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
62248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
62258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sinit->sinit_max_attempts)
62268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
62278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
62288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sinit->sinit_max_init_timeo)
62298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
62308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
62318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
62328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
62338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PRIMARY_ADDR:
62348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
62358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_setprim *spa;
62368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
62378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
62388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
62398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
62408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
62418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
62428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
62438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
62448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
62458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
62468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
62478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
62488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
62498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
62508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp,
62518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    (struct sockaddr *)&spa->ssp_addr,
62528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    &net, NULL, NULL);
62538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
62548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
62558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
62568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
62578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
62588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb) && (net)) {
62598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((net != stcb->asoc.primary_destination) &&
62608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
62618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Ok we need to set it */
62628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
6263000a5bac556b28e74e4e98c540f66b1743e9312dtuexen					if ((stcb->asoc.alternate) &&
62648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (!(net->dest_state & SCTP_ADDR_PF)) &&
62658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (net->dest_state & SCTP_ADDR_REACHABLE)) {
62668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_free_remote_addr(stcb->asoc.alternate);
62678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.alternate = NULL;
62688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
62698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
62708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
62718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
62728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
62738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
62748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
62758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
62768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
62778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
62788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
62798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
62808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SET_DYNAMIC_PRIMARY:
62818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
62828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		union sctp_sockstore *ss;
62838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
6284b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		int i, fnd = 0;
62858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__Windows__) && !defined(__Userspace__)
62878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
62888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct proc *proc;
62898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__
62918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version > 602000
62928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = priv_check(curthread,
62938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				   PRIV_NETINET_RESERVEDPORT);
62948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif __FreeBSD_version >= 500000
62958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = suser((struct thread *)p);
62968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
62978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = suser(p);
62988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__APPLE__)
63008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		proc = (struct proc *)p;
63018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (p) {
63028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = suser(proc->p_ucred, &proc->p_acflag);
63038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
63048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
63058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
63068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
63078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = suser(p, 0);
63088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
63098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
63108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error)
63118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
63128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
63138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
63148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* SUPER USER CHECK? */
63158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
63168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < inp->num_vrfs; i++) {
63178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (vrf_id == inp->m_vrf_ids[i]) {
63188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				fnd = 1;
63198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
63208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
63218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
63228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!fnd) {
63238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
63248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
63258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
63268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
63278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
63288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
63298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
63308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
63318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SET_PEER_PRIMARY_ADDR:
63328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
63338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_setpeerprim *sspp;
63348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
63358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
63368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
63378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb != NULL) {
63388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_ifa *ifa;
63398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
63408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
63418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (ifa == NULL) {
63428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
63438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
63448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto out_of_it;
63458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
63468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
63478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Must validate the ifa found is in our ep */
63488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_laddr *laddr;
6349b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				int found = 0;
63508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
63518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (laddr->ifa == NULL) {
63528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
63538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							__FUNCTION__);
63548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
63558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
63568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (laddr->ifa == ifa) {
63578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						found = 1;
63588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
63598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
63608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
63618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!found) {
63628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
63638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
63648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto out_of_it;
63658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
6366998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
6367998635733088fde643e6d807fa76679c4ceeaa00t			} else {
6368998635733088fde643e6d807fa76679c4ceeaa00t				switch (sspp->sspp_addr.ss_family) {
6369998635733088fde643e6d807fa76679c4ceeaa00t#ifdef INET
6370998635733088fde643e6d807fa76679c4ceeaa00t				case AF_INET:
6371998635733088fde643e6d807fa76679c4ceeaa00t				{
6372998635733088fde643e6d807fa76679c4ceeaa00t					struct sockaddr_in *sin;
6373998635733088fde643e6d807fa76679c4ceeaa00t
6374998635733088fde643e6d807fa76679c4ceeaa00t					sin = (struct sockaddr_in *)&sspp->sspp_addr;
6375998635733088fde643e6d807fa76679c4ceeaa00t					if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
6376998635733088fde643e6d807fa76679c4ceeaa00t					                     &sin->sin_addr) != 0) {
6377998635733088fde643e6d807fa76679c4ceeaa00t						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6378998635733088fde643e6d807fa76679c4ceeaa00t						error = EINVAL;
6379998635733088fde643e6d807fa76679c4ceeaa00t						goto out_of_it;
6380998635733088fde643e6d807fa76679c4ceeaa00t					}
6381998635733088fde643e6d807fa76679c4ceeaa00t					break;
6382998635733088fde643e6d807fa76679c4ceeaa00t				}
6383998635733088fde643e6d807fa76679c4ceeaa00t#endif
6384998635733088fde643e6d807fa76679c4ceeaa00t#ifdef INET6
6385998635733088fde643e6d807fa76679c4ceeaa00t				case AF_INET6:
6386998635733088fde643e6d807fa76679c4ceeaa00t				{
6387998635733088fde643e6d807fa76679c4ceeaa00t					struct sockaddr_in6 *sin6;
6388998635733088fde643e6d807fa76679c4ceeaa00t
6389998635733088fde643e6d807fa76679c4ceeaa00t					sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
6390998635733088fde643e6d807fa76679c4ceeaa00t					if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
6391998635733088fde643e6d807fa76679c4ceeaa00t					                     &sin6->sin6_addr) != 0) {
6392998635733088fde643e6d807fa76679c4ceeaa00t						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6393998635733088fde643e6d807fa76679c4ceeaa00t						error = EINVAL;
6394998635733088fde643e6d807fa76679c4ceeaa00t						goto out_of_it;
6395998635733088fde643e6d807fa76679c4ceeaa00t					}
6396998635733088fde643e6d807fa76679c4ceeaa00t					break;
6397998635733088fde643e6d807fa76679c4ceeaa00t				}
6398998635733088fde643e6d807fa76679c4ceeaa00t#endif
6399998635733088fde643e6d807fa76679c4ceeaa00t				default:
6400998635733088fde643e6d807fa76679c4ceeaa00t					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6401998635733088fde643e6d807fa76679c4ceeaa00t					error = EINVAL;
6402998635733088fde643e6d807fa76679c4ceeaa00t					goto out_of_it;
6403998635733088fde643e6d807fa76679c4ceeaa00t				}
6404998635733088fde643e6d807fa76679c4ceeaa00t#endif
64058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_set_primary_ip_address_sa(stcb,
64078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							   (struct sockaddr *)&sspp->sspp_addr) != 0) {
64088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
64098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
64108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		out_of_it:
64128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
64138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
64148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
64158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
64168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
64178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
64188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
64198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_BINDX_ADD_ADDR:
64208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
64218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_getaddresses *addrs;
64228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
64238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct thread *td;
64248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
64258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		td = (struct thread *)p;
64268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
64288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    optsize);
64298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
64308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addrs->addr->sa_family == AF_INET) {
6431c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
64328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
64338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
64348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
64358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
64378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
64388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
64398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
64408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else
64438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
64458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addrs->addr->sa_family == AF_INET6) {
6446c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
64478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
64488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
64498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
64508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
64528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
64538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
64548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
64558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  break;
64568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else
64598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
64618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       error = EAFNOSUPPORT;
6462e2828360ea9cf8951730d46f5c14626c9425cb30t		       break;
64638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
64648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_bindx_add_address(so, inp, addrs->addr,
64658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       addrs->sget_assoc_id, vrf_id,
64668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       &error, p);
64678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
64688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
64698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_BINDX_REM_ADDR:
64708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
64718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_getaddresses *addrs;
64728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
64738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct thread *td;
64748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		td = (struct thread *)p;
64758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
64768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
64788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
64798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addrs->addr->sa_family == AF_INET) {
6480c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
64818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
64828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
64838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
64848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
64868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
64878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
64888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
64898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else
64928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
64948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addrs->addr->sa_family == AF_INET6) {
6495c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
64968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
64978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
64988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
64998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
65008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
65018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (td != NULL &&
65028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (error = prison_local_ip6(td->td_ucred,
65038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                              &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
65048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                              (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
65058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
65068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
65078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
65088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
65098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else
65108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
65118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
65128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EAFNOSUPPORT;
65138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
65148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65150ac02f34d6041cd0018437596a5a9a94685e6919tuexen		sctp_bindx_delete_address(inp, addrs->addr,
65168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  addrs->sget_assoc_id, vrf_id,
65178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  &error);
65188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
65198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
65208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __APPLE__
65218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_LISTEN_FIX:
65228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* only applies to one-to-many sockets */
65238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
65248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* make sure the ACCEPTCONN flag is OFF */
65258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			so->so_options &= ~SO_ACCEPTCONN;
65268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
65278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* otherwise, not allowed */
65288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
65298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
65308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
65328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* __APPLE__ */
65338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EVENT:
65348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
65358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_event *event;
65368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t event_type;
65378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
65388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
65398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
65408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (event->se_type) {
65418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ASSOC_CHANGE:
65428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
6543000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
65448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_PEER_ADDR_CHANGE:
65458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
6546000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
65478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_REMOTE_ERROR:
65488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVPEERERR;
6549000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
65508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SEND_FAILED:
65518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
6552000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
65538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SHUTDOWN_EVENT:
65548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
6555000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
65568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ADAPTATION_INDICATION:
65578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
6558000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
65598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_PARTIAL_DELIVERY_EVENT:
65608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
6561000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
65628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTHENTICATION_EVENT:
65638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_AUTHEVNT;
6564000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
65658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_STREAM_RESET_EVENT:
65668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
6567000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
65688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SENDER_DRY_EVENT:
65698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_DRYEVNT;
6570000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
65718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_NOTIFICATIONS_STOPPED_EVENT:
65728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = 0;
65738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
65748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOTSUP;
65758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
6576298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen		case SCTP_ASSOC_RESET_EVENT:
6577298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
6578298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			break;
6579298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen		case SCTP_STREAM_CHANGE_EVENT:
6580298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
6581298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			break;
65825741e159bdf238ef4b61085d6fbfea2947386238tuexen		case SCTP_SEND_FAILED_EVENT:
65835741e159bdf238ef4b61085d6fbfea2947386238tuexen			event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
65845741e159bdf238ef4b61085d6fbfea2947386238tuexen			break;
65858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
65868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = 0;
65878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
65888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
65898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
65908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (event_type > 0) {
65928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
65938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (event->se_on) {
65948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_on(inp, stcb, event_type);
65958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
65968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
65978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
65988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (stcb->asoc.stream_queue_cnt == 0)) {
65998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
66008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
66018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
66028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
66038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_off(inp, stcb, event_type);
66048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
66058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
66068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
66078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
66088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * We don't want to send up a storm of events,
66098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * so return an error for sender dry events
66108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
66118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
66128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
66138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
6614000a5bac556b28e74e4e98c540f66b1743e9312dtuexen				    ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
66158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
66168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
66178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = ENOTSUP;
66188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
66198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
66208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
66218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
66228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
66238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
66248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_WLOCK(inp);
66258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (event->se_on) {
66268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_feature_on(inp, event_type);
66278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
66288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_feature_off(inp, event_type);
66298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
66308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_WUNLOCK(inp);
66318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
66328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
66338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
66348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RLOCK(inp);
66358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
66368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_TCB_LOCK(stcb);
66378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (event->se_on) {
66388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_stcb_feature_on(inp, stcb, event_type);
66398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else {
66408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_stcb_feature_off(inp, stcb, event_type);
66418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
66428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_TCB_UNLOCK(stcb);
66438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
66448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RUNLOCK(inp);
66458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
66468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
66478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
66488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
66498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
66508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RECVRCVINFO:
66518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
66528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int *onoff;
66538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
66548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
66558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
66568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*onoff != 0) {
66578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
66588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
66598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
66608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
66618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
66628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
66638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
66648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RECVNXTINFO:
66658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
66668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int *onoff;
66678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
66688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
66698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
66708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*onoff != 0) {
66718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
66728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
66738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
66748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
66758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
66768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
66778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
66788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_SNDINFO:
66798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
66808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sndinfo *info;
66818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint16_t policy;
66828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
66838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
66848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
66858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
66868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
66878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (info->snd_sid < stcb->asoc.streamoutcnt) {
66888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_send.sinfo_stream = info->snd_sid;
66898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
66908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_send.sinfo_flags = info->snd_flags;
66918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_send.sinfo_flags |= policy;
66928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
66938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_send.sinfo_context = info->snd_context;
66948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
66958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
66968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
66978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
66988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
66998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
67008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
67018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
67028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
67038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
67048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
67058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_stream = info->snd_sid;
67068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
67078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_flags = info->snd_flags;
67088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_flags |= policy;
67098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_ppid = info->snd_ppid;
67108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_context = info->snd_context;
67118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
67128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
67138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
67148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
67158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
67168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
67178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
67188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (info->snd_sid < stcb->asoc.streamoutcnt) {
67198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.def_send.sinfo_stream = info->snd_sid;
67208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
67218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.def_send.sinfo_flags = info->snd_flags;
67228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.def_send.sinfo_flags |= policy;
67238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
67248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.def_send.sinfo_context = info->snd_context;
67258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
67268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
67278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
67288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
67298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
67308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
67318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
67328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_PRINFO:
67348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
67358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_default_prinfo *info;
67368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
67378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
67388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
67398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
67408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
67418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
67428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
67438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
67448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
67458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
67468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.def_send.sinfo_flags &= 0xfff0;
67478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
67488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
67498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
67508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
67518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
67528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
67538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
67548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
67558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
67568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_flags &= 0xfff0;
67578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_flags |= info->pr_policy;
67588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_timetolive = info->pr_value;
67598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
67608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
67618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
67628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
67638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
67648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
67658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
67668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.def_send.sinfo_flags &= 0xfff0;
67678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
67688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
67698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
67708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
67718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
67728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
67738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
67748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
67758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEER_ADDR_THLDS:
67778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Applies to the specific association */
67788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
67798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paddrthlds *thlds;
67808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
67818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
67828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
67838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
67848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
67858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
678649659836bb1e9e5d1ab58f3804c47e509933c2c4t			net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
67878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
67888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
67898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
67908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
67918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
67928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
67938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp,
679449659836bb1e9e5d1ab58f3804c47e509933c2c4t							    (struct sockaddr *)&thlds->spt_address,
67958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    &net, NULL, NULL);
67968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
67978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
67988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
67998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6800b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (stcb && (net == NULL)) {
68018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr *sa;
68028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
680349659836bb1e9e5d1ab58f3804c47e509933c2c4t			sa = (struct sockaddr *)&thlds->spt_address;
68048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
68058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET) {
68068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in *sin;
68088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin = (struct sockaddr_in *)sa;
68098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin->sin_addr.s_addr) {
68108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
68118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
68128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
68138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
68148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
68158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
68168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
68188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET6) {
68198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in6 *sin6;
68208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6 = (struct sockaddr_in6 *)sa;
68228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
68238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
68248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
68258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
68268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
68278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
68288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
68298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
683075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
683175cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
683275cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
683375cd23222c96d5ebe5a9082c57a263f917f1462btuexen
683475cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
683575cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
683675cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
683775cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
683875cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
683975cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
684075cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
684175cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
684275cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
68438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			{
68448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EAFNOSUPPORT;
68458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
68468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
68478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
68488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
68498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
68508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
68518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net) {
68528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dest_state & SCTP_ADDR_PF) {
68538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
68548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (net->failure_threshold <= thlds->spt_pathpfthld)) {
68558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dest_state &= ~SCTP_ADDR_PF;
68568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
68578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
68588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((net->failure_threshold > thlds->spt_pathpfthld) &&
68598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
6860e2828360ea9cf8951730d46f5c14626c9425cb30t						net->dest_state |= SCTP_ADDR_PF;
68618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
68628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
68638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
68648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
68658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
68668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dest_state & SCTP_ADDR_REACHABLE) {
68678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->failure_threshold > thlds->spt_pathmaxrxt) {
68688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dest_state &= ~SCTP_ADDR_REACHABLE;
686947674b651417d493ff4e0318113fd7beeef119dbtuexen						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
68708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
68718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
68728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
68738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dest_state |= SCTP_ADDR_REACHABLE;
687447674b651417d493ff4e0318113fd7beeef119dbtuexen						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
68758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
68768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
68778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->failure_threshold = thlds->spt_pathmaxrxt;
68788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->pf_threshold = thlds->spt_pathpfthld;
68798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
68808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
68818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->dest_state & SCTP_ADDR_PF) {
68828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
68838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (net->failure_threshold <= thlds->spt_pathpfthld)) {
68848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state &= ~SCTP_ADDR_PF;
68858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
68868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
68878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((net->failure_threshold > thlds->spt_pathpfthld) &&
68888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
6889e2828360ea9cf8951730d46f5c14626c9425cb30t							net->dest_state |= SCTP_ADDR_PF;
68908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
68918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
68928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
68938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
68948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
68958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->dest_state & SCTP_ADDR_REACHABLE) {
68968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->failure_threshold > thlds->spt_pathmaxrxt) {
68978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state &= ~SCTP_ADDR_REACHABLE;
689847674b651417d493ff4e0318113fd7beeef119dbtuexen							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
68998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
69008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
69018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
69028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state |= SCTP_ADDR_REACHABLE;
690347674b651417d493ff4e0318113fd7beeef119dbtuexen							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
69048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
69058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
69068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->failure_threshold = thlds->spt_pathmaxrxt;
69078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->pf_threshold = thlds->spt_pathpfthld;
69088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
69098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
69108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
69118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
69128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
69138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
69148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
69158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
69168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
69178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
69188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
69198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
69208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
69218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
69228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
69238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
69248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
69258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
69268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6927153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	case SCTP_REMOTE_UDP_ENCAPS_PORT:
6928153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	{
6929153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		struct sctp_udpencaps *encaps;
6930153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		struct sctp_nets *net;
693181616c6a3e184f46276632dd15aa489cd06d94dftuexen
6932153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
6933153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
6934153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (stcb) {
6935153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
6936153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		} else {
6937153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			/* We increment here since sctp_findassociation_ep_addr() wil
6938153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 * do a decrement if it finds the stcb as long as the locked
6939153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
6940153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 */
6941153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			net = NULL;
6942153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			SCTP_INP_INCR_REF(inp);
6943153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
6944153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (stcb == NULL) {
6945153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_DECR_REF(inp);
6946153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
6947153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
6948b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (stcb && (net == NULL)) {
6949153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			struct sockaddr *sa;
6950000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
6951153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			sa = (struct sockaddr *)&encaps->sue_address;
6952153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#ifdef INET
6953153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (sa->sa_family == AF_INET) {
6954153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
6955153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				struct sockaddr_in *sin;
6956153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				sin = (struct sockaddr_in *)sa;
6957153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				if (sin->sin_addr.s_addr) {
6958153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6959153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_TCB_UNLOCK(stcb);
6960153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					error = EINVAL;
6961153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					break;
6962153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				}
6963153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else
6964153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#endif
6965153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#ifdef INET6
6966153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (sa->sa_family == AF_INET6) {
6967153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				struct sockaddr_in6 *sin6;
6968153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
6969153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				sin6 = (struct sockaddr_in6 *)sa;
6970153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6971153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6972153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_TCB_UNLOCK(stcb);
6973153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					error = EINVAL;
6974153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					break;
6975153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				}
6976153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else
6977153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#endif
697875cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
697975cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
698075cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
698175cd23222c96d5ebe5a9082c57a263f917f1462btuexen
698275cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
698375cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
698475cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
698575cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
698675cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
698775cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
698875cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
698975cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
699075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
6991153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			{
6992153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					error = EAFNOSUPPORT;
6993153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_TCB_UNLOCK(stcb);
6994153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6995153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					break;
6996153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				}
6997153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
6998153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
6999153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (stcb) {
7000153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (net) {
7001153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				net->port = encaps->sue_port;
7002153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else {
7003153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				stcb->asoc.port = encaps->sue_port;
7004153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
7005153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			SCTP_TCB_UNLOCK(stcb);
7006153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		} else {
7007153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7008153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7009153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
7010153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_WLOCK(inp);
7011153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				inp->sctp_ep.port = encaps->sue_port;
7012153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_WUNLOCK(inp);
7013153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else {
7014153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7015153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				error = EINVAL;
7016153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
7017153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
7018153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		break;
7019153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	}
7020aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t	case SCTP_ECN_SUPPORTED:
7021aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t	{
7022aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		struct sctp_assoc_value *av;
7023aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t
7024aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7025aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7026aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t
7027aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		if (stcb) {
7028aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7029aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			error = EINVAL;
7030aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			SCTP_TCB_UNLOCK(stcb);
7031aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		} else {
7032aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7033aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7034aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
7035aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				SCTP_INP_WLOCK(inp);
7036aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				if (av->assoc_value == 0) {
7037aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t					inp->ecn_supported = 0;
7038aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				} else {
7039a8657c4fc04fb9cc82100f648810d51ec6ab155at					inp->ecn_supported = 1;
7040a8657c4fc04fb9cc82100f648810d51ec6ab155at				}
7041a8657c4fc04fb9cc82100f648810d51ec6ab155at				SCTP_INP_WUNLOCK(inp);
7042a8657c4fc04fb9cc82100f648810d51ec6ab155at			} else {
7043a8657c4fc04fb9cc82100f648810d51ec6ab155at				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7044a8657c4fc04fb9cc82100f648810d51ec6ab155at				error = EINVAL;
7045a8657c4fc04fb9cc82100f648810d51ec6ab155at			}
7046a8657c4fc04fb9cc82100f648810d51ec6ab155at		}
7047a8657c4fc04fb9cc82100f648810d51ec6ab155at		break;
7048a8657c4fc04fb9cc82100f648810d51ec6ab155at	}
7049a8657c4fc04fb9cc82100f648810d51ec6ab155at	case SCTP_PR_SUPPORTED:
7050a8657c4fc04fb9cc82100f648810d51ec6ab155at	{
7051a8657c4fc04fb9cc82100f648810d51ec6ab155at		struct sctp_assoc_value *av;
7052a8657c4fc04fb9cc82100f648810d51ec6ab155at
7053a8657c4fc04fb9cc82100f648810d51ec6ab155at		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7054a8657c4fc04fb9cc82100f648810d51ec6ab155at		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7055a8657c4fc04fb9cc82100f648810d51ec6ab155at
7056a8657c4fc04fb9cc82100f648810d51ec6ab155at		if (stcb) {
7057a8657c4fc04fb9cc82100f648810d51ec6ab155at			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7058a8657c4fc04fb9cc82100f648810d51ec6ab155at			error = EINVAL;
7059a8657c4fc04fb9cc82100f648810d51ec6ab155at			SCTP_TCB_UNLOCK(stcb);
7060a8657c4fc04fb9cc82100f648810d51ec6ab155at		} else {
7061a8657c4fc04fb9cc82100f648810d51ec6ab155at			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7062a8657c4fc04fb9cc82100f648810d51ec6ab155at			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7063a8657c4fc04fb9cc82100f648810d51ec6ab155at			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
7064a8657c4fc04fb9cc82100f648810d51ec6ab155at				SCTP_INP_WLOCK(inp);
7065a8657c4fc04fb9cc82100f648810d51ec6ab155at				if (av->assoc_value == 0) {
7066a8657c4fc04fb9cc82100f648810d51ec6ab155at					inp->prsctp_supported = 0;
7067a8657c4fc04fb9cc82100f648810d51ec6ab155at				} else {
7068a8657c4fc04fb9cc82100f648810d51ec6ab155at					inp->prsctp_supported = 1;
7069aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				}
7070aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				SCTP_INP_WUNLOCK(inp);
7071aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			} else {
7072aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7073aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t				error = EINVAL;
7074aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t			}
7075aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		}
7076aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t		break;
7077aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t	}
7078fb3816eaffe5878bb1286adb120fd160da178a05t	case SCTP_AUTH_SUPPORTED:
7079fb3816eaffe5878bb1286adb120fd160da178a05t	{
7080fb3816eaffe5878bb1286adb120fd160da178a05t		struct sctp_assoc_value *av;
7081fb3816eaffe5878bb1286adb120fd160da178a05t
7082fb3816eaffe5878bb1286adb120fd160da178a05t		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7083fb3816eaffe5878bb1286adb120fd160da178a05t		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7084fb3816eaffe5878bb1286adb120fd160da178a05t
7085fb3816eaffe5878bb1286adb120fd160da178a05t		if (stcb) {
7086fb3816eaffe5878bb1286adb120fd160da178a05t			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7087fb3816eaffe5878bb1286adb120fd160da178a05t			error = EINVAL;
7088fb3816eaffe5878bb1286adb120fd160da178a05t			SCTP_TCB_UNLOCK(stcb);
7089fb3816eaffe5878bb1286adb120fd160da178a05t		} else {
7090fb3816eaffe5878bb1286adb120fd160da178a05t			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7091fb3816eaffe5878bb1286adb120fd160da178a05t			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7092fb3816eaffe5878bb1286adb120fd160da178a05t			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
7093fb3816eaffe5878bb1286adb120fd160da178a05t				if ((av->assoc_value == 0) &&
7094fb3816eaffe5878bb1286adb120fd160da178a05t				    (inp->asconf_supported == 1)) {
7095fb3816eaffe5878bb1286adb120fd160da178a05t				    	/* AUTH is required for ASCONF */
7096fb3816eaffe5878bb1286adb120fd160da178a05t					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7097fb3816eaffe5878bb1286adb120fd160da178a05t					error = EINVAL;
7098fb3816eaffe5878bb1286adb120fd160da178a05t				} else {
7099fb3816eaffe5878bb1286adb120fd160da178a05t					SCTP_INP_WLOCK(inp);
7100fb3816eaffe5878bb1286adb120fd160da178a05t					if (av->assoc_value == 0) {
7101fb3816eaffe5878bb1286adb120fd160da178a05t						inp->auth_supported = 0;
7102fb3816eaffe5878bb1286adb120fd160da178a05t					} else {
7103fb3816eaffe5878bb1286adb120fd160da178a05t						inp->auth_supported = 1;
7104fb3816eaffe5878bb1286adb120fd160da178a05t					}
7105fb3816eaffe5878bb1286adb120fd160da178a05t					SCTP_INP_WUNLOCK(inp);
7106fb3816eaffe5878bb1286adb120fd160da178a05t				}
7107fb3816eaffe5878bb1286adb120fd160da178a05t			} else {
7108fb3816eaffe5878bb1286adb120fd160da178a05t				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7109fb3816eaffe5878bb1286adb120fd160da178a05t				error = EINVAL;
7110fb3816eaffe5878bb1286adb120fd160da178a05t			}
7111fb3816eaffe5878bb1286adb120fd160da178a05t		}
7112fb3816eaffe5878bb1286adb120fd160da178a05t		break;
7113fb3816eaffe5878bb1286adb120fd160da178a05t	}
7114fb3816eaffe5878bb1286adb120fd160da178a05t	case SCTP_ASCONF_SUPPORTED:
7115fb3816eaffe5878bb1286adb120fd160da178a05t	{
7116fb3816eaffe5878bb1286adb120fd160da178a05t		struct sctp_assoc_value *av;
7117fb3816eaffe5878bb1286adb120fd160da178a05t
7118fb3816eaffe5878bb1286adb120fd160da178a05t		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7119fb3816eaffe5878bb1286adb120fd160da178a05t		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7120fb3816eaffe5878bb1286adb120fd160da178a05t
7121fb3816eaffe5878bb1286adb120fd160da178a05t		if (stcb) {
7122fb3816eaffe5878bb1286adb120fd160da178a05t			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7123fb3816eaffe5878bb1286adb120fd160da178a05t			error = EINVAL;
7124fb3816eaffe5878bb1286adb120fd160da178a05t			SCTP_TCB_UNLOCK(stcb);
7125fb3816eaffe5878bb1286adb120fd160da178a05t		} else {
7126fb3816eaffe5878bb1286adb120fd160da178a05t			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7127fb3816eaffe5878bb1286adb120fd160da178a05t			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7128fb3816eaffe5878bb1286adb120fd160da178a05t			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
7129fb3816eaffe5878bb1286adb120fd160da178a05t				if ((av->assoc_value != 0) &&
7130fb3816eaffe5878bb1286adb120fd160da178a05t				    (inp->auth_supported == 0)) {
7131fb3816eaffe5878bb1286adb120fd160da178a05t				    	/* AUTH is required for ASCONF */
7132fb3816eaffe5878bb1286adb120fd160da178a05t					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7133fb3816eaffe5878bb1286adb120fd160da178a05t					error = EINVAL;
7134fb3816eaffe5878bb1286adb120fd160da178a05t				} else {
7135fb3816eaffe5878bb1286adb120fd160da178a05t					SCTP_INP_WLOCK(inp);
7136fb3816eaffe5878bb1286adb120fd160da178a05t					if (av->assoc_value == 0) {
7137fb3816eaffe5878bb1286adb120fd160da178a05t						inp->asconf_supported = 0;
7138fb3816eaffe5878bb1286adb120fd160da178a05t						sctp_auth_delete_chunk(SCTP_ASCONF,
7139fb3816eaffe5878bb1286adb120fd160da178a05t						                       inp->sctp_ep.local_auth_chunks);
7140fb3816eaffe5878bb1286adb120fd160da178a05t						sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
7141fb3816eaffe5878bb1286adb120fd160da178a05t						                       inp->sctp_ep.local_auth_chunks);
7142fb3816eaffe5878bb1286adb120fd160da178a05t					} else {
7143fb3816eaffe5878bb1286adb120fd160da178a05t						inp->asconf_supported = 1;
7144fb3816eaffe5878bb1286adb120fd160da178a05t						sctp_auth_add_chunk(SCTP_ASCONF,
7145fb3816eaffe5878bb1286adb120fd160da178a05t						                    inp->sctp_ep.local_auth_chunks);
7146fb3816eaffe5878bb1286adb120fd160da178a05t						sctp_auth_add_chunk(SCTP_ASCONF_ACK,
7147fb3816eaffe5878bb1286adb120fd160da178a05t						                    inp->sctp_ep.local_auth_chunks);
7148fb3816eaffe5878bb1286adb120fd160da178a05t					}
7149fb3816eaffe5878bb1286adb120fd160da178a05t					SCTP_INP_WUNLOCK(inp);
7150fb3816eaffe5878bb1286adb120fd160da178a05t				}
7151fb3816eaffe5878bb1286adb120fd160da178a05t			} else {
7152fb3816eaffe5878bb1286adb120fd160da178a05t				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7153fb3816eaffe5878bb1286adb120fd160da178a05t				error = EINVAL;
7154fb3816eaffe5878bb1286adb120fd160da178a05t			}
7155fb3816eaffe5878bb1286adb120fd160da178a05t		}
7156fb3816eaffe5878bb1286adb120fd160da178a05t		break;
7157fb3816eaffe5878bb1286adb120fd160da178a05t	}
71582344bfccffeb80545fca6a86e8cda3d56a6f50bft	case SCTP_RECONFIG_SUPPORTED:
71592344bfccffeb80545fca6a86e8cda3d56a6f50bft	{
71602344bfccffeb80545fca6a86e8cda3d56a6f50bft		struct sctp_assoc_value *av;
71612344bfccffeb80545fca6a86e8cda3d56a6f50bft
71622344bfccffeb80545fca6a86e8cda3d56a6f50bft		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
71632344bfccffeb80545fca6a86e8cda3d56a6f50bft		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
71642344bfccffeb80545fca6a86e8cda3d56a6f50bft
71652344bfccffeb80545fca6a86e8cda3d56a6f50bft		if (stcb) {
71662344bfccffeb80545fca6a86e8cda3d56a6f50bft			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
71672344bfccffeb80545fca6a86e8cda3d56a6f50bft			error = EINVAL;
71682344bfccffeb80545fca6a86e8cda3d56a6f50bft			SCTP_TCB_UNLOCK(stcb);
71692344bfccffeb80545fca6a86e8cda3d56a6f50bft		} else {
71702344bfccffeb80545fca6a86e8cda3d56a6f50bft			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
71712344bfccffeb80545fca6a86e8cda3d56a6f50bft			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
71722344bfccffeb80545fca6a86e8cda3d56a6f50bft			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
71732344bfccffeb80545fca6a86e8cda3d56a6f50bft				SCTP_INP_WLOCK(inp);
71742344bfccffeb80545fca6a86e8cda3d56a6f50bft				if (av->assoc_value == 0) {
71752344bfccffeb80545fca6a86e8cda3d56a6f50bft					inp->reconfig_supported = 0;
71762344bfccffeb80545fca6a86e8cda3d56a6f50bft				} else {
71772344bfccffeb80545fca6a86e8cda3d56a6f50bft					inp->reconfig_supported = 1;
71782344bfccffeb80545fca6a86e8cda3d56a6f50bft				}
71792344bfccffeb80545fca6a86e8cda3d56a6f50bft				SCTP_INP_WUNLOCK(inp);
71802344bfccffeb80545fca6a86e8cda3d56a6f50bft			} else {
71812344bfccffeb80545fca6a86e8cda3d56a6f50bft				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
71822344bfccffeb80545fca6a86e8cda3d56a6f50bft				error = EINVAL;
71832344bfccffeb80545fca6a86e8cda3d56a6f50bft			}
71842344bfccffeb80545fca6a86e8cda3d56a6f50bft		}
71852344bfccffeb80545fca6a86e8cda3d56a6f50bft		break;
71862344bfccffeb80545fca6a86e8cda3d56a6f50bft	}
718744318e900a771ba1a5bafb510c38f33fd5cd8a39t	case SCTP_NRSACK_SUPPORTED:
718844318e900a771ba1a5bafb510c38f33fd5cd8a39t	{
718944318e900a771ba1a5bafb510c38f33fd5cd8a39t		struct sctp_assoc_value *av;
719044318e900a771ba1a5bafb510c38f33fd5cd8a39t
719144318e900a771ba1a5bafb510c38f33fd5cd8a39t		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
719244318e900a771ba1a5bafb510c38f33fd5cd8a39t		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
719344318e900a771ba1a5bafb510c38f33fd5cd8a39t
719444318e900a771ba1a5bafb510c38f33fd5cd8a39t		if (stcb) {
719544318e900a771ba1a5bafb510c38f33fd5cd8a39t			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
719644318e900a771ba1a5bafb510c38f33fd5cd8a39t			error = EINVAL;
719744318e900a771ba1a5bafb510c38f33fd5cd8a39t			SCTP_TCB_UNLOCK(stcb);
719844318e900a771ba1a5bafb510c38f33fd5cd8a39t		} else {
719944318e900a771ba1a5bafb510c38f33fd5cd8a39t			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
720044318e900a771ba1a5bafb510c38f33fd5cd8a39t			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
720144318e900a771ba1a5bafb510c38f33fd5cd8a39t			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
720244318e900a771ba1a5bafb510c38f33fd5cd8a39t				SCTP_INP_WLOCK(inp);
720344318e900a771ba1a5bafb510c38f33fd5cd8a39t				if (av->assoc_value == 0) {
720444318e900a771ba1a5bafb510c38f33fd5cd8a39t					inp->nrsack_supported = 0;
720544318e900a771ba1a5bafb510c38f33fd5cd8a39t				} else {
720644318e900a771ba1a5bafb510c38f33fd5cd8a39t					inp->nrsack_supported = 1;
720744318e900a771ba1a5bafb510c38f33fd5cd8a39t				}
720844318e900a771ba1a5bafb510c38f33fd5cd8a39t				SCTP_INP_WUNLOCK(inp);
720944318e900a771ba1a5bafb510c38f33fd5cd8a39t			} else {
721044318e900a771ba1a5bafb510c38f33fd5cd8a39t				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
721144318e900a771ba1a5bafb510c38f33fd5cd8a39t				error = EINVAL;
721244318e900a771ba1a5bafb510c38f33fd5cd8a39t			}
721344318e900a771ba1a5bafb510c38f33fd5cd8a39t		}
721444318e900a771ba1a5bafb510c38f33fd5cd8a39t		break;
721544318e900a771ba1a5bafb510c38f33fd5cd8a39t	}
7216669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t	case SCTP_PKTDROP_SUPPORTED:
7217669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t	{
7218669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		struct sctp_assoc_value *av;
7219669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t
7220669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7221669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7222669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t
7223669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		if (stcb) {
7224669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7225669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			error = EINVAL;
7226669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			SCTP_TCB_UNLOCK(stcb);
7227669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		} else {
7228669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7229669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7230669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
7231669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				SCTP_INP_WLOCK(inp);
7232669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				if (av->assoc_value == 0) {
7233669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t					inp->pktdrop_supported = 0;
7234669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				} else {
7235669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t					inp->pktdrop_supported = 1;
7236669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				}
7237669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				SCTP_INP_WUNLOCK(inp);
7238669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			} else {
7239669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7240669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t				error = EINVAL;
7241669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t			}
7242669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		}
7243669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t		break;
7244669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t	}
72458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
72468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
72478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = ENOPROTOOPT;
72488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
72498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end switch (opt) */
72508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
72518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
72528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
72538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
72548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
72558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_ctloutput(struct socket *so, struct sockopt *sopt)
72568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
72578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	void *optval = NULL;
72588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	size_t optsize = 0;
72598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	void *p;
72608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error = 0;
72618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
72628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sopt->sopt_level != IPPROTO_SCTP) {
72638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* wrong proto level... send back up to IP */
72648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
72658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (INP_CHECK_SOCKAF(so, AF_INET6))
72668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ip6_ctloutput(so, sopt);
72678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* INET6 */
72680612043f643c9b26245564c05defca64d472060etuexen#if defined(INET) && defined(INET6)
72698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
72708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
72728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ip_ctloutput(so, sopt);
72738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (error);
72758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
72768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	optsize = sopt->sopt_valsize;
72778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (optsize) {
72788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
72798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (optval == NULL) {
72808a29867a84996e7ee31a638ab89256ca7d2dc9b0tuexen			SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
72818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (ENOBUFS);
72828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
72838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sooptcopyin(sopt, optval, optsize, optsize);
72848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
72858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE(optval, SCTP_M_SOCKOPT);
72868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out;
72878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
72888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
72898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__Windows__)
72908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	p = (void *)sopt->sopt_td;
72918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
72928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	p = (void *)sopt->sopt_p;
72938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sopt->sopt_dir == SOPT_SET) {
72958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
72968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (sopt->sopt_dir == SOPT_GET) {
72978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
72988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
72998a29867a84996e7ee31a638ab89256ca7d2dc9b0tuexen		SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
73008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
73018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((error == 0) && (optval != NULL)) {
73038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sooptcopyout(sopt, optval, optsize);
73048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(optval, SCTP_M_SOCKOPT);
73058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (optval != NULL) {
73068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(optval, SCTP_M_SOCKOPT);
73078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenout:
73098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
73108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
73118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
73148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
73158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
73168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
73178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
73188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
73198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__)
73208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
73218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
73228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
73238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__) || defined(__Userspace__)
73248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
73258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connect(struct socket *so, struct sockaddr *addr)
73268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
73278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	void *p = NULL;
73288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__)
73298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
73308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
73318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
73328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
73338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
73348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connect(struct socket *so, struct mbuf *nam, struct proc *p)
73358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
73368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *addr = mtod(nam, struct sockaddr *);
73378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
7341b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int i, fnd = 0;
73428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error = 0;
73448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int create_lock_on = 0;
73458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
73468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
7347b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	struct sctp_tcb *stcb = NULL;
73488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
73502fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
73518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* I made the same as TCP since we are not setup? */
73528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
73538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ECONNRESET);
73548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (addr == NULL) {
73568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
73578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return EINVAL;
73588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
73618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        /* TODO __Userspace__ falls into this code for IPv6 stuff at the moment... */
73628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
736323273859c39742f09cc5ec7c9bf32ff225661e82tuexen#if !defined(__Windows__) && !defined(__Userspace_os_Linux) && !defined(__Userspace_os_Windows)
73648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (addr->sa_family) {
73658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
73668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
73678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
73688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
73698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6p;
73708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
73738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
73748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
73758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
73778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6p = (struct sockaddr_in6 *)addr;
73788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
73798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
73808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (error);
73818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
73848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
73878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
73888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
73898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
73908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sinp;
73918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73930612043f643c9b26245564c05defca64d472060etuexen#if !defined(__Userspace_os_Windows)
73948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr->sa_len != sizeof(struct sockaddr_in)) {
73958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
73968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
73978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
739881616c6a3e184f46276632dd15aa489cd06d94dftuexen#endif
73998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
74008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinp = (struct sockaddr_in *)addr;
74018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
74028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
74038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (error);
74048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
74078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
74108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7411e2828360ea9cf8951730d46f5c14626c9425cb30t		return (EAFNOSUPPORT);
74128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_INCR_REF(inp);
74158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_ASOC_CREATE_LOCK(inp);
74168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	create_lock_on = 1;
74178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
74188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
74198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
74208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
74218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Should I really unlock ? */
74228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
74238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	        error = EFAULT;
74248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
74258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
74278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
74288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (addr->sa_family == AF_INET6)) {
74298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
74308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
74318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
74328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74337988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
74347988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
74357988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) &&
74367988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	    (addr->sa_family != AF_CONN)) {
74377988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
74387988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		error = EINVAL;
74397988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		goto out_now;
74407988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	}
74417988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
74428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
74438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_PCB_FLAGS_UNBOUND) {
74448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Bind a ephemeral port */
74458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_inpcb_bind(so, NULL, NULL, p);
74468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
74478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_now;
74488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now do we connect? */
74518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
74528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
74538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
74548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
74558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
74568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
74588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
74598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We are already connected AND the TCP model */
74608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
74618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EADDRINUSE;
74628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
74638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
74658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
74668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = LIST_FIRST(&inp->sctp_asoc_list);
74678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
74688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
74698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We increment here since sctp_findassociation_ep_addr() will
74708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * do a decrement if it finds the stcb as long as the locked
74718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * tcb (last argument) is NOT a TCB.. aka NULL.
74728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
74738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_INCR_REF(inp);
74748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
74758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
74768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_DECR_REF(inp);
74778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
74788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
74798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb != NULL) {
74828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Already have or am bring up an association */
74838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
74848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EALREADY;
74858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
74868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
74888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf_id = inp->def_vrf_id;
74898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
74908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < inp->num_vrfs; i++) {
74918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (vrf_id == inp->m_vrf_ids[i]) {
74928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			fnd = 1;
74938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
74948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!fnd) {
74978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
74988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
74998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
75008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
75018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
75028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* We are GOOD to go */
75038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
75048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
75058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Gak! no memory */
75068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
75078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
75088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
75098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
75108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Set the connected flag so we can queue data */
75118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		soisconnecting(so);
75128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
75138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
75148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
75158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
75168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* initialize authentication parameters for the assoc */
75178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_initialize_auth_params(inp, stcb);
75188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
75198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
75208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
75218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out_now:
75228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (create_lock_on) {
75238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_ASOC_CREATE_UNLOCK(inp);
75248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
75258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
75268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_DECR_REF(inp);
7527b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (error);
75288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
75298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
75308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
75317a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#if defined(__Userspace__)
75327a9f1edd34bf82c194a2f9d0c64394f431175138tuexenint
75337a9f1edd34bf82c194a2f9d0c64394f431175138tuexensctpconn_connect(struct socket *so, struct sockaddr *addr)
75347a9f1edd34bf82c194a2f9d0c64394f431175138tuexen{
75357a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#ifdef SCTP_MVRF
75367a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	int i, fnd = 0;
75377a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
75387a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	void *p = NULL;
75397a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	int error = 0;
75407a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	int create_lock_on = 0;
75417a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	uint32_t vrf_id;
75427a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	struct sctp_inpcb *inp;
75437a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	struct sctp_tcb *stcb = NULL;
75447a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
75457a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
75467a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (inp == NULL) {
75477a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* I made the same as TCP since we are not setup? */
75487a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
75497a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		return (ECONNRESET);
75507a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
75517a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (addr == NULL) {
75527a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
75537a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		return EINVAL;
75547a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
75557a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	switch (addr->sa_family) {
7556f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef INET
7557f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t	case AF_INET:
7558f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
7559f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t		if (addr->sa_len != sizeof(struct sockaddr_in)) {
75607a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
75617a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			return (EINVAL);
75627a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
7563f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#endif
75647a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		break;
75657a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
7566f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef INET6
7567f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t	case AF_INET6:
7568f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
7569f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
75707a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
75717a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			return (EINVAL);
75727a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
7573f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#endif
75747a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		break;
75757a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
75767a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	case AF_CONN:
7577f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
75787a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		if (addr->sa_len != sizeof(struct sockaddr_conn)) {
75797a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
75807a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			return (EINVAL);
75817a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
7582f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#endif
75837a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		break;
75847a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	default:
75857a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
7586e2828360ea9cf8951730d46f5c14626c9425cb30t		return (EAFNOSUPPORT);
75877a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
75887a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	SCTP_INP_INCR_REF(inp);
75897a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	SCTP_ASOC_CREATE_LOCK(inp);
75907a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	create_lock_on = 1;
75917a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
75927a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
75937a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
75947a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
75957a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* Should I really unlock ? */
75967a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
75977a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	        error = EFAULT;
75987a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
75997a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76007a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#ifdef INET6
76017a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
76027a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	    (addr->sa_family == AF_INET6)) {
76037a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
76047a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = EINVAL;
76057a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
76067a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76077a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
76087a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == SCTP_PCB_FLAGS_UNBOUND) {
76097a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* Bind a ephemeral port */
76107a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = sctp_inpcb_bind(so, NULL, NULL, p);
76117a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		if (error) {
76127a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			goto out_now;
76137a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
76147a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76157a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	/* Now do we connect? */
76167a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
76177a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
76187a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
76197a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = EINVAL;
76207a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
76217a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76227a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
76237a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
76247a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* We are already connected AND the TCP model */
76257a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
76267a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = EADDRINUSE;
76277a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
76287a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76297a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
76307a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_INP_RLOCK(inp);
76317a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		stcb = LIST_FIRST(&inp->sctp_asoc_list);
76327a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_INP_RUNLOCK(inp);
76337a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	} else {
76347a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* We increment here since sctp_findassociation_ep_addr() will
76357a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		 * do a decrement if it finds the stcb as long as the locked
76367a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		 * tcb (last argument) is NOT a TCB.. aka NULL.
76377a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		 */
76387a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_INP_INCR_REF(inp);
76397a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
76407a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		if (stcb == NULL) {
76417a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			SCTP_INP_DECR_REF(inp);
76427a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		} else {
76437a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			SCTP_TCB_UNLOCK(stcb);
76447a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
76457a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76467a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (stcb != NULL) {
76477a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* Already have or am bring up an association */
76487a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
76497a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = EALREADY;
76507a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
76517a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76527a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
76537a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	vrf_id = inp->def_vrf_id;
76547a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#ifdef SCTP_MVRF
76557a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	for (i = 0; i < inp->num_vrfs; i++) {
76567a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		if (vrf_id == inp->m_vrf_ids[i]) {
76577a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			fnd = 1;
76587a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			break;
76597a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
76607a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76617a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (!fnd) {
76627a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
76637a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = EINVAL;
76647a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
76657a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76667a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
76677a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	/* We are GOOD to go */
76687a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
76697a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (stcb == NULL) {
76707a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* Gak! no memory */
76717a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
76727a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76737a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
76747a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
76757a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* Set the connected flag so we can queue data */
76767a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		soisconnecting(so);
76777a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76787a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
76797a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
76807a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
76817a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	/* initialize authentication parameters for the assoc */
76827a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	sctp_initialize_auth_params(inp, stcb);
76837a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
76847a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
76857a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	SCTP_TCB_UNLOCK(stcb);
76867a9f1edd34bf82c194a2f9d0c64394f431175138tuexen out_now:
76877a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (create_lock_on) {
76887a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_ASOC_CREATE_UNLOCK(inp);
76897a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
76907a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
76917a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	SCTP_INP_DECR_REF(inp);
76927a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	return (error);
76937a9f1edd34bf82c194a2f9d0c64394f431175138tuexen}
76947a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
76958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
76968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
76978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version >= 700000
76988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_listen(struct socket *so, int backlog, struct thread *p)
76998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
77008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_listen(struct socket *so, struct thread *p)
77018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__)
77038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_listen(struct socket *so, int backlog, PKTHREAD p)
77048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Userspace__)
77058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_listen(struct socket *so, int backlog, struct proc *p)
77068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
77078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_listen(struct socket *so, struct proc *p)
77088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
77108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
77118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Note this module depends on the protocol processing being called
77128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * AFTER any socket level flags and backlog are applied to the
77138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * socket. The traditional way that the socket flags are applied is
77148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * AFTER protocol processing. We have made a change to the
77158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
77168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * place if the socket API for SCTP is to work properly.
77178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
77188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error = 0;
77208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
7721000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
77228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
77232fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
77248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* I made the same as TCP since we are not setup? */
77258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
77268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ECONNRESET);
77278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
77288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
77298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* See if we have a listener */
77308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_inpcb *tinp;
7731828732282b383285a904f1cdcdaa2e633b2eb38at		union sctp_sockstore store;
77328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
77348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* not bound all */
77358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_laddr *laddr;
77368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
77388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				memcpy(&store, &laddr->ifa->address, sizeof(store));
7739828732282b383285a904f1cdcdaa2e633b2eb38at				switch (store.sa.sa_family) {
77408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
77418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET:
7742828732282b383285a904f1cdcdaa2e633b2eb38at					store.sin.sin_port = inp->sctp_lport;
77438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
77448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
77468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET6:
7747828732282b383285a904f1cdcdaa2e633b2eb38at					store.sin6.sin6_port = inp->sctp_lport;
77488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
77498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
775075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
775175cd23222c96d5ebe5a9082c57a263f917f1462btuexen				case AF_CONN:
7752828732282b383285a904f1cdcdaa2e633b2eb38at					store.sconn.sconn_port = inp->sctp_lport;
775375cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
775475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
77558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				default:
77568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
77578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
7758828732282b383285a904f1cdcdaa2e633b2eb38at				tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
77598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tinp && (tinp != inp) &&
77608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
77618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
77628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (tinp->sctp_socket->so_qlimit)) {
77638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* we have a listener already and its not this inp. */
77648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_DECR_REF(tinp);
77658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (EADDRINUSE);
77668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if (tinp) {
77678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_DECR_REF(tinp);
77688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
77698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
77708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
77718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Setup a local addr bound all */
77728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memset(&store, 0, sizeof(store));
77738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
77748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
77758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				store.sa.sa_family = AF_INET6;
7776f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
77778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				store.sa.sa_len = sizeof(struct sockaddr_in6);
77788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
77808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7781828732282b383285a904f1cdcdaa2e633b2eb38at#if defined(__Userspace__)
7782828732282b383285a904f1cdcdaa2e633b2eb38at			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
7783828732282b383285a904f1cdcdaa2e633b2eb38at				store.sa.sa_family = AF_CONN;
7784828732282b383285a904f1cdcdaa2e633b2eb38at#ifdef HAVE_SA_LEN
7785828732282b383285a904f1cdcdaa2e633b2eb38at				store.sa.sa_len = sizeof(struct sockaddr_conn);
7786828732282b383285a904f1cdcdaa2e633b2eb38at#endif
7787828732282b383285a904f1cdcdaa2e633b2eb38at			}
7788828732282b383285a904f1cdcdaa2e633b2eb38at#endif
77898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
7790828732282b383285a904f1cdcdaa2e633b2eb38at#if defined(__Userspace__)
7791828732282b383285a904f1cdcdaa2e633b2eb38at			if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
7792828732282b383285a904f1cdcdaa2e633b2eb38at			    ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) == 0)) {
7793828732282b383285a904f1cdcdaa2e633b2eb38at#else
77948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
7795828732282b383285a904f1cdcdaa2e633b2eb38at#endif
77968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				store.sa.sa_family = AF_INET;
7797f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
77988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				store.sa.sa_len = sizeof(struct sockaddr_in);
77998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
78008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
78018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7802828732282b383285a904f1cdcdaa2e633b2eb38at			switch (store.sa.sa_family) {
7803828732282b383285a904f1cdcdaa2e633b2eb38at#ifdef INET
7804828732282b383285a904f1cdcdaa2e633b2eb38at			case AF_INET:
7805828732282b383285a904f1cdcdaa2e633b2eb38at				store.sin.sin_port = inp->sctp_lport;
7806828732282b383285a904f1cdcdaa2e633b2eb38at				break;
7807828732282b383285a904f1cdcdaa2e633b2eb38at#endif
7808828732282b383285a904f1cdcdaa2e633b2eb38at#ifdef INET6
7809828732282b383285a904f1cdcdaa2e633b2eb38at			case AF_INET6:
7810828732282b383285a904f1cdcdaa2e633b2eb38at				store.sin6.sin6_port = inp->sctp_lport;
7811828732282b383285a904f1cdcdaa2e633b2eb38at				break;
7812828732282b383285a904f1cdcdaa2e633b2eb38at#endif
7813828732282b383285a904f1cdcdaa2e633b2eb38at#if defined(__Userspace__)
7814828732282b383285a904f1cdcdaa2e633b2eb38at			case AF_CONN:
7815828732282b383285a904f1cdcdaa2e633b2eb38at				store.sconn.sconn_port = inp->sctp_lport;
7816828732282b383285a904f1cdcdaa2e633b2eb38at				break;
7817828732282b383285a904f1cdcdaa2e633b2eb38at#endif
7818828732282b383285a904f1cdcdaa2e633b2eb38at			default:
7819828732282b383285a904f1cdcdaa2e633b2eb38at				break;
7820828732282b383285a904f1cdcdaa2e633b2eb38at			}
7821828732282b383285a904f1cdcdaa2e633b2eb38at			tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
78228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tinp && (tinp != inp) &&
78238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
78248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
78258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (tinp->sctp_socket->so_qlimit)) {
78268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* we have a listener already and its not this inp. */
78278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(tinp);
78288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EADDRINUSE);
78298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (tinp) {
78308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
78318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
78328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
78338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
78348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
78358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOCK_LOGGING
78368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
78378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
78388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
78398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
78408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCK_LOCK(so);
78418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Userspace__)
78428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = solisten_proto_check(so);
78438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error) {
78448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_UNLOCK(so);
78458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
78468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (error);
78478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
78488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
78498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
78508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
78518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* The unlucky case
78528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * - We are in the tcp pool with this guy.
78538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * - Someone else is in the main inp slot.
78548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * - We must move this guy (the listener) to the main slot
78558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * - We must then move the guy that was listener to the TCP Pool.
78568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
78578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_swap_inpcb_for_listen(inp)) {
78588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto in_use;
78598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
78608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
78618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
78628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
78638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
78648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We are already connected AND the TCP model */
78658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	in_use:
78668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
78678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_UNLOCK(so);
78688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
78698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EADDRINUSE);
78708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
78718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(inp);
78728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
78738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We must do a bind. */
78748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_UNLOCK(so);
78758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
78768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* bind error, probably perm */
78778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (error);
78788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
78798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_LOCK(so);
7880000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	}
78818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) || defined(__Userspace__)
78828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
78838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* It appears for 7.0 and on, we must always call this. */
78848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	solisten_proto(so, backlog);
78858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
78868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
78878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		solisten_proto(so);
78888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
78898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
78908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
78918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
78928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* remove the ACCEPTCONN flag for one-to-many sockets */
7893907b9e7d7c75f02c3d1f6c70016127990e8fe648t#if defined(__Userspace__)
78946435cc0024abc9f2dabba9feb634081e246d342bt		so->so_options &= ~SCTP_SO_ACCEPTCONN;
7895907b9e7d7c75f02c3d1f6c70016127990e8fe648t#else
78968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_options &= ~SO_ACCEPTCONN;
7897907b9e7d7c75f02c3d1f6c70016127990e8fe648t#endif
78988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
78998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
79018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (backlog == 0) {
79028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* turning off listen */
7903907b9e7d7c75f02c3d1f6c70016127990e8fe648t#if defined(__Userspace__)
7904907b9e7d7c75f02c3d1f6c70016127990e8fe648t		so->so_options &= ~SCTP_SO_ACCEPTCONN;
7905907b9e7d7c75f02c3d1f6c70016127990e8fe648t#else
79068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_options &= ~SO_ACCEPTCONN;
7907907b9e7d7c75f02c3d1f6c70016127990e8fe648t#endif
79088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
79098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
79108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCK_UNLOCK(so);
79118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
79128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
79138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int sctp_defered_wakeup_cnt = 0;
79158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
79178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
79188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_accept(struct socket *so, struct sockaddr **addr)
79198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
79208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
79218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_accept(struct socket *so, struct sockaddr *addr, int *namelen,
79228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    void *accept_info, int *accept_info_len)
79238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
79248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
79258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_accept(struct socket *so, struct mbuf *nam)
79268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
79278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *addr = mtod(nam, struct sockaddr *);
79288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
79298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb;
79308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
79318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	union sctp_sockstore store;
79328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
79338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
79348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error;
79358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_KAME */
79368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
79378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
79388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79392fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
79408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
79418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ECONNRESET);
79428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
79438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
79448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
79458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
79468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
79478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EOPNOTSUPP);
79488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
79498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so->so_state & SS_ISDISCONNECTED) {
79508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
79518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
79528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ECONNABORTED);
79538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
79548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = LIST_FIRST(&inp->sctp_asoc_list);
79558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
79568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
79578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
79588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ECONNRESET);
79598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
79608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_LOCK(stcb);
79618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(inp);
79628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	store = stcb->asoc.primary_destination->ro._l_addr;
79638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
79648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
79658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (store.sa.sa_family) {
79668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
79678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
79688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
79698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sin;
79708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
79728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
79738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sin == NULL)
79748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (ENOMEM);
79758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
79768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin = (struct sockaddr_in *)addr;
79778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero((caddr_t)sin, sizeof(*sin));
79788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
79798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_family = AF_INET;
79807b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
79818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_len = sizeof(*sin);
79828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
79837988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sin->sin_port = store.sin.sin_port;
79847988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sin->sin_addr = store.sin.sin_addr;
79858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
79868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*addr = (struct sockaddr *)sin;
79878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif !defined(__Panda__)
79888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_BUF_LEN(nam) = sizeof(*sin);
79898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
79908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
79928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
79938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
79948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
79958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
79968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6;
79978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
79998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
80008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sin6 == NULL)
80018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (ENOMEM);
80028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
80038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6 = (struct sockaddr_in6 *)addr;
80048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero((caddr_t)sin6, sizeof(*sin6));
80058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
80068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_family = AF_INET6;
80077b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
80088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_len = sizeof(*sin6);
80098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
80107988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sin6->sin6_port = store.sin6.sin6_port;
80117988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sin6->sin6_addr = store.sin6.sin6_addr;
80128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE)
80138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
80148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((error = sa6_recoverscope(sin6)) != 0) {
80158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE_SONAME(sin6);
80168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (error);
80178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
80188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
80198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
80208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
80218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * sin6->sin6_scope_id =
80228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * ntohs(sin6->sin6_addr.s6_addr16[1]);
80238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
80248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			in6_recoverscope(sin6, &sin6->sin6_addr, NULL);	/* skip ifp check */
80258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
80268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin6->sin6_scope_id = 0;	/* XXX */
80278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_KAME */
80288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
80290612043f643c9b26245564c05defca64d472060etuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
80308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*addr = (struct sockaddr *)sin6;
80318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif !defined(__Panda__)
80328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_BUF_LEN(nam) = sizeof(*sin6);
80338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
80348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
80358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
80368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
80377988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
80387988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	case AF_CONN:
80397988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	{
80407988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		struct sockaddr_conn *sconn;
80417988ea8f0c067cf3757e798b473b1ae4d34b6dfdt
80427988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		SCTP_MALLOC_SONAME(sconn, struct sockaddr_conn *, sizeof(struct sockaddr_conn));
80437988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		if (sconn == NULL) {
80447988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			return (ENOMEM);
80457988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		}
80467988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sconn->sconn_family = AF_CONN;
80477988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef HAVE_SCONN_LEN
80487988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sconn->sconn_len = sizeof(struct sockaddr_conn);
80497988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
80507988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sconn->sconn_port = store.sconn.sconn_port;
80517988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sconn->sconn_addr = store.sconn.sconn_addr;
80527988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		*addr = (struct sockaddr *)sconn;
80537988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		break;
80547988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	}
80557988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
80568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
80578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* TSNH */
80588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
80598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
80608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Wake any delayed sleep action */
80618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
80628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
80638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
80648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
80658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
80668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WUNLOCK(inp);
80678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
80688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sowriteable(inp->sctp_socket)) {
80698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
80708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                            /*__Userspace__ calling sowwakup_locked because of SOCKBUF_LOCK above. */
80718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
80728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
80738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sowwakeup_locked(inp->sctp_socket);
80748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
80758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
80768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* socket is locked */
80778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
80788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sowwakeup(inp->sctp_socket);
80798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
80808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
80818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
80828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
80838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WLOCK(inp);
80848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
80858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
80868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
80878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WUNLOCK(inp);
80888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
80898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (soreadable(inp->sctp_socket)) {
80908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_defered_wakeup_cnt++;
80918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
80928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                                /*__Userspace__ calling sorwakup_locked because of SOCKBUF_LOCK above */
80938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
80948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
80958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sorwakeup_locked(inp->sctp_socket);
80968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
80978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
80988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* socket is locked */
80998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
81008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sorwakeup(inp->sctp_socket);
81018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
81028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
81038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
81048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
81058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WLOCK(inp);
81068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
81078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
81088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
81098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
81108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
81118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7);
81128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
81138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
81148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
81158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
81168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
81178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
81188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
81198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_ingetaddr(struct socket *so, struct sockaddr **addr)
81208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
81218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin;
81228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
81238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_ingetaddr(struct socket *so, struct sockaddr *addr)
81248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
81258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
81268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
81278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_ingetaddr(struct socket *so, struct mbuf *nam)
81288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
81298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
81308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
81318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
81328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
81338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *sctp_ifa;
81348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
81358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
81368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Do the malloc first in case it blocks.
81378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
81388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
81398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
81408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sin == NULL)
81418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOMEM);
81428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
81438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(sin, sizeof(*sin));
81448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
81458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(nam) = sizeof(*sin);
81468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(sin, 0, sizeof(*sin));
81478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
81488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin->sin_family = AF_INET;
81497b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
81508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin->sin_len = sizeof(*sin);
81518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
81528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
81538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!inp) {
81548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
81558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE_SONAME(sin);
81568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
81578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8158b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (ECONNRESET);
81598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
81608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
81618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin->sin_port = inp->sctp_lport;
81628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
81638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
81648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_tcb *stcb;
81658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr_in *sin_a;
81668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_nets *net;
81678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int fnd;
81688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
81698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = LIST_FIRST(&inp->sctp_asoc_list);
81708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
81718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto notConn;
81728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
81738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			fnd = 0;
81748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin_a = NULL;
81758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(stcb);
81768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
81778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin_a = (struct sockaddr_in *)&net->ro._l_addr;
81788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin_a == NULL)
81798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* this will make coverity happy */
81808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
81818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
81828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin_a->sin_family == AF_INET) {
81838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					fnd = 1;
81848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
81858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
81868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
81878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((!fnd) || (sin_a == NULL)) {
81888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* punt */
81898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
81908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto notConn;
81918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
81928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
81938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			vrf_id = inp->def_vrf_id;
81948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ifa = sctp_source_address_selection(inp,
81958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								 stcb,
81968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								 (sctp_route_t *)&net->ro,
81978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								 net, 0, vrf_id);
81988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_ifa) {
81998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin->sin_addr = sctp_ifa->address.sin.sin_addr;
82008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_ifa(sctp_ifa);
82018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
82028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
82038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
82048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* For the bound all case you get back 0 */
82058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	notConn:
82068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin->sin_addr.s_addr = 0;
82078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
82088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
82098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
82108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Take the first IPv4 address in the list */
82118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_laddr *laddr;
82128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int fnd = 0;
82138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
82148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
82158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (laddr->ifa->address.sa.sa_family == AF_INET) {
82168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in *sin_a;
82178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8218bfb1bf7e665a02b48026482bf33d05c83dfad73bt				sin_a = &laddr->ifa->address.sin;
82198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin->sin_addr = sin_a->sin_addr;
82208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				fnd = 1;
82218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
82228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
82238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
82248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!fnd) {
82258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
82268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE_SONAME(sin);
82278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
82288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
82298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
8230b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			return (ENOENT);
82318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
82328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
82338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(inp);
82348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
82358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(*addr) = (struct sockaddr *)sin;
82368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
82378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
82388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
82398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
82408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
82418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
82428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_peeraddr(struct socket *so, struct sockaddr **addr)
82438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8244845436a72b5767f30403c3b77c457488703143a9tuexen	struct sockaddr_in *sin;
82458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
82468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_peeraddr(struct socket *so, struct sockaddr *addr)
82478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
82488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
82498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
82508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_peeraddr(struct socket *so, struct mbuf *nam)
82518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
82528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
82538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
82548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
82558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int fnd;
82568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin_a;
82578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
82588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb;
82598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
82608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
82618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Do the malloc first in case it blocks. */
82628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
82638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
82648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sin == NULL)
82658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOMEM);
82668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
82678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(sin, 0, sizeof(*sin));
82688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
82698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(nam) = sizeof(*sin);
82708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(sin, 0, sizeof(*sin));
82718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
82728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin->sin_family = AF_INET;
82737b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
82748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin->sin_len = sizeof(*sin);
82758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
82768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
82778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
8278b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((inp == NULL) ||
8279b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
8280b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		/* UDP type and listeners will drop out here */
82818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
82828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE_SONAME(sin);
82838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
8284b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
8285b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (ENOTCONN);
82868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
82878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
82888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = LIST_FIRST(&inp->sctp_asoc_list);
82898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
82908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
82918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
82928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(inp);
82938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
82948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
82958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE_SONAME(sin);
82968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
82978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8298b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (ECONNRESET);
82998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
83008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	fnd = 0;
83018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
83028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin_a = (struct sockaddr_in *)&net->ro._l_addr;
83038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sin_a->sin_family == AF_INET) {
83048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			fnd = 1;
83058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin->sin_port = stcb->rport;
83068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin->sin_addr = sin_a->sin_addr;
83078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
83088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
83098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
83108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
83118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!fnd) {
83128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* No IPv4 address */
83138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
83148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE_SONAME(sin);
83158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
83168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
8317b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (ENOENT);
83188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
83198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
83208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(*addr) = (struct sockaddr *)sin;
83218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
83228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
83238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
83248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
83258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
83268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct pr_usrreqs sctp_usrreqs = {
83277fbcb406549bdf370031d2ad5befb44e39b95ffft#if defined(__FreeBSD__)
83288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_abort = sctp_abort,
83298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_accept = sctp_accept,
83308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_attach = sctp_attach,
83318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_bind = sctp_bind,
83328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_connect = sctp_connect,
83338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_control = in_control,
83348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version >= 690000
83358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_close = sctp_close,
83368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_detach = sctp_close,
83378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_sopoll = sopoll_generic,
83388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_flush = sctp_flush,
83398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
83408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_detach = sctp_detach,
83418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_sopoll = sopoll,
83428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
83438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_disconnect = sctp_disconnect,
83448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_listen = sctp_listen,
83458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_peeraddr = sctp_peeraddr,
83468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_send = sctp_sendm,
83478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_shutdown = sctp_shutdown,
83488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_sockaddr = sctp_ingetaddr,
83498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_sosend = sctp_sosend,
83508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_soreceive = sctp_soreceive
83517fbcb406549bdf370031d2ad5befb44e39b95ffft#elif defined(__APPLE__)
83527fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_abort = sctp_abort,
83537fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_accept = sctp_accept,
83547fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_attach = sctp_attach,
83557fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_bind = sctp_bind,
83567fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_connect = sctp_connect,
83577fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_connect2 = pru_connect2_notsupp,
83587fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_control = in_control,
83597fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_detach = sctp_detach,
83607fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_disconnect = sctp_disconnect,
83617fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_listen = sctp_listen,
83627fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_peeraddr = sctp_peeraddr,
83637fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_rcvd = NULL,
83647fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_rcvoob = pru_rcvoob_notsupp,
83657fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_send = sctp_sendm,
83667fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sense = pru_sense_null,
83677fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_shutdown = sctp_shutdown,
83687fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sockaddr = sctp_ingetaddr,
83697fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sosend = sctp_sosend,
83707fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_soreceive = sctp_soreceive,
83717fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sopoll = sopoll
83727fbcb406549bdf370031d2ad5befb44e39b95ffft#elif defined(__Windows__)
83738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_abort,
83748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_accept,
83758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_attach,
83768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_bind,
83778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_connect,
83788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pru_connect2_notsupp,
83798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	NULL,
83808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	NULL,
83818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_disconnect,
83828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_listen,
83838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_peeraddr,
83848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	NULL,
83858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pru_rcvoob_notsupp,
83868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	NULL,
83878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pru_sense_null,
83888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_shutdown,
83898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_flush,
83908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_ingetaddr,
83918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sosend,
83928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_soreceive,
83938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sopoll_generic,
83948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	NULL,
83958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_close
83968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
83978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen};
83988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif !defined(__Panda__) && !defined(__Userspace__)
83998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
84008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_usrreq(so, req, m, nam, control)
84018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *so;
84028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int req;
84038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m, *nam, *control;
84048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
84058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct proc *p = curproc;
84068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
84078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_vrf *vrf;
84088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error;
84098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int family;
84108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp = (struct sctp_inpcb *)so->so_pcb;
84118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
84128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = 0;
84138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	family = so->so_proto->pr_domain->dom_family;
84148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (req == PRU_CONTROL) {
84158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (family) {
84168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case PF_INET:
84178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = in_control(so, (long)m, (caddr_t)nam,
8418b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			    (struct ifnet *)control);
84198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
84208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
84218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case PF_INET6:
84228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = in6_control(so, (long)m, (caddr_t)nam,
84238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct ifnet *)control, p);
84248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
84258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
84268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
84278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
84288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EAFNOSUPPORT;
84298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
84308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (error);
84318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
84328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (req) {
84338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_ATTACH:
84348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_attach(so, family, p);
84358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_DETACH:
84378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_detach(so);
84388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_BIND:
84408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (nam == NULL) {
84418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
84428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
84438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
84448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_bind(so, nam, p);
84458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_LISTEN:
84478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_listen(so, p);
84488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_CONNECT:
84508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (nam == NULL) {
84518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
84528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
84538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
84548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_connect(so, nam, p);
84558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_DISCONNECT:
84578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_disconnect(so);
84588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_ACCEPT:
84608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (nam == NULL) {
84618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
84628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
84638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
84648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_accept(so, nam);
84658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SHUTDOWN:
84678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_shutdown(so);
84688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
84708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_RCVD:
84718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
84728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * For Open and Net BSD, this is real ugly. The mbuf *nam
84738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * that is passed (by soreceive()) is the int flags c ast as
84748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * a (mbuf *) yuck!
84758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
84768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
84788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SEND:
84798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Flags are ignored */
84808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
84818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr *addr;
84828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
84838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (nam == NULL)
84848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr = NULL;
84858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
84868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr = mtod(nam, struct sockaddr *);
84878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
84888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = sctp_sendm(so, 0, m, addr, control, p);
84898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
84908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_ABORT:
84928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_abort(so);
84938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
84958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SENSE:
84968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = 0;
84978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
84988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_RCVOOB:
84998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
85008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EAFNOSUPPORT;
85018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
85028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SENDOOB:
85038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
85048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EAFNOSUPPORT;
85058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
85068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_PEERADDR:
85078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_peeraddr(so, nam);
85088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
85098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SOCKADDR:
85108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_ingetaddr(so, nam);
85118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
85128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SLOWTIMO:
85138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = 0;
85148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
85158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
85168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
85178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
85188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
85198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
85208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
85218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
85228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
852360416fb97d019e56677da96dbdac6d48048822d3tuexen
852432a191a90b5c914a02047389c5b3197e08fc9841tuexen#if defined(__Userspace__)
852560416fb97d019e56677da96dbdac6d48048822d3tuexenint
8526d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexenregister_recv_cb(struct socket *so,
8527d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen                 int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data,
8528d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen                 size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info))
852960416fb97d019e56677da96dbdac6d48048822d3tuexen{
8530d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	struct sctp_inpcb *inp;
853160416fb97d019e56677da96dbdac6d48048822d3tuexen
853260416fb97d019e56677da96dbdac6d48048822d3tuexen	inp = (struct sctp_inpcb *) so->so_pcb;
853332a191a90b5c914a02047389c5b3197e08fc9841tuexen	if (inp == NULL) {
853432a191a90b5c914a02047389c5b3197e08fc9841tuexen		return (0);
853532a191a90b5c914a02047389c5b3197e08fc9841tuexen	}
853632a191a90b5c914a02047389c5b3197e08fc9841tuexen	SCTP_INP_WLOCK(inp);
853760416fb97d019e56677da96dbdac6d48048822d3tuexen	inp->recv_callback = receive_cb;
853832a191a90b5c914a02047389c5b3197e08fc9841tuexen	SCTP_INP_WUNLOCK(inp);
8539f57cf83923be449d11806a31f62bcc17e58832d6t	return (1);
854060416fb97d019e56677da96dbdac6d48048822d3tuexen}
854160416fb97d019e56677da96dbdac6d48048822d3tuexen
854260416fb97d019e56677da96dbdac6d48048822d3tuexenint
8543d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexenregister_send_cb(struct socket *so, uint32_t sb_threshold, int (*send_cb)(struct socket *sock, uint32_t sb_free))
854460416fb97d019e56677da96dbdac6d48048822d3tuexen{
8545d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	struct sctp_inpcb *inp;
854660416fb97d019e56677da96dbdac6d48048822d3tuexen
854760416fb97d019e56677da96dbdac6d48048822d3tuexen	inp = (struct sctp_inpcb *) so->so_pcb;
854832a191a90b5c914a02047389c5b3197e08fc9841tuexen	if (inp == NULL) {
854932a191a90b5c914a02047389c5b3197e08fc9841tuexen		return (0);
855032a191a90b5c914a02047389c5b3197e08fc9841tuexen	}
855132a191a90b5c914a02047389c5b3197e08fc9841tuexen	SCTP_INP_WLOCK(inp);
855260416fb97d019e56677da96dbdac6d48048822d3tuexen	inp->send_callback = send_cb;
855360416fb97d019e56677da96dbdac6d48048822d3tuexen	inp->send_sb_threshold = sb_threshold;
855432a191a90b5c914a02047389c5b3197e08fc9841tuexen	SCTP_INP_WUNLOCK(inp);
855560416fb97d019e56677da96dbdac6d48048822d3tuexen	/* FIXME change to current amount free. This will be the full buffer
855660416fb97d019e56677da96dbdac6d48048822d3tuexen	 * the first time this is registered but it could be only a portion
855760416fb97d019e56677da96dbdac6d48048822d3tuexen	 * of the send buffer if this is called a second time e.g. if the
855860416fb97d019e56677da96dbdac6d48048822d3tuexen	 * threshold changes.
855960416fb97d019e56677da96dbdac6d48048822d3tuexen	 */
8560f57cf83923be449d11806a31f62bcc17e58832d6t	return (1);
856160416fb97d019e56677da96dbdac6d48048822d3tuexen}
8562d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen
8563d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexenint
8564d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexenregister_ulp_info (struct socket *so, void *ulp_info)
8565d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen{
8566d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	struct sctp_inpcb *inp;
8567d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen
8568d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	inp = (struct sctp_inpcb *) so->so_pcb;
8569d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	if (inp == NULL) {
8570d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen		return (0);
8571d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	}
8572d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	SCTP_INP_WLOCK(inp);
8573d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	inp->ulp_info = ulp_info;
8574d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	SCTP_INP_WUNLOCK(inp);
8575f57cf83923be449d11806a31f62bcc17e58832d6t	return (1);
8576d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen}
857760416fb97d019e56677da96dbdac6d48048822d3tuexen#endif
8578