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>
358f9e45fea288542b24a6bda01269c6fc184d991at__FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 263237 2014-03-16 12:32:16Z 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>
590612043f643c9b26245564c05defca64d472060etuexen#if !defined(__Userspace_os_Windows)
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#endif
39714ba474e7d8520db1b04d650c6a788bdc5dab9e0tuexen#endif
3988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
4008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_notify(struct sctp_inpcb *inp,
4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct ip *ip,
4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctphdr *sh,
4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sockaddr *to,
4048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_tcb *stcb,
4058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_nets *net)
4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
4070612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *so;
4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct icmp *icmph;
4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41347674b651417d493ff4e0318113fd7beeef119dbtuexen	/* protection */
4148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (sh == NULL) || (to == NULL)) {
4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb)
4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* First job is to verify the vtag matches what I would send */
4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
4228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       sizeof(struct ip)));
4288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (icmph->icmp_type != ICMP_UNREACH) {
4298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We only care about unreachable */
4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
4328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_HOST) ||
4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
4378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
44022a33a1debfe70529be4aa018a2912bfe5dcd8dat#if defined(__Panda__)
4418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_ADMIN)) {
44222a33a1debfe70529be4aa018a2912bfe5dcd8dat#elif defined(__Userspace_os_NetBSD)
44322a33a1debfe70529be4aa018a2912bfe5dcd8dat	    (icmph->icmp_code == ICMP_UNREACH_ADMIN_PROHIBIT)) {
4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
4468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
4498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Hmm reachablity problems we must examine closely. If its
4508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * not reachable, we may have lost a network. Or if there is
4518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * NO protocol at the other end named SCTP. well we consider
4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * it a OOTB abort.
4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
4548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->dest_state & SCTP_ADDR_REACHABLE) {
4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Ok that destination is NOT reachable */
4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->dest_state &= ~SCTP_ADDR_REACHABLE;
4578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->dest_state &= ~SCTP_ADDR_PF;
4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
45947674b651417d493ff4e0318113fd7beeef119dbtuexen					stcb, 0,
4608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(void *)net, SCTP_SO_NOT_LOCKED);
4618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else  if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (icmph->icmp_code == ICMP_UNREACH_PORT)) {
4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
4668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Here the peer is either playing tricks on us,
4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * including an address that belongs to someone who
4688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * does not support SCTP OR was a userland
4698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * implementation that shutdown and now is dead. In
4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * either case treat it like a OOTB abort with no
4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * TCB
4728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
47347674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
4740612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so = SCTP_INP_SO(inp);
4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
4788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_LOCK(so, 1);
4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
4818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_2);
4830612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_UNLOCK(so, 1);
4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/
4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no need to unlock here, since the TCB is gone */
4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
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
16798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (sin->sin_addr.s_addr == 0) {
16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							/*
16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * we skip unspecifed
16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * addresses
16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 */
16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
16878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((ipv4_local_scope == 0) &&
16888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
16898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
16908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
16918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
16928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
16938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
16958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							actual += sizeof(struct sockaddr_in6);
16978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else {
16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							memcpy(sas, sin, sizeof(*sin));
17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							actual += sizeof(*sin);
17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (actual >= limit) {
17078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							return (actual);
17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
17118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET6:
17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (ipv6_addr_legal) {
17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						struct sockaddr_in6 *sin6;
17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						struct sockaddr_in6 lsa6;
17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							/*
17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * we skip unspecifed
17268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * addresses
17278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 */
17288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
17318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (local_scope == 0)
17328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								continue;
17338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE)
17348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (sin6->sin6_scope_id == 0) {
17358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
17368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								if (sa6_recoverscope(sin6) != 0)
17378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									/*
17388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * bad link
17398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * local
17408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * address
17418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 */
17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									continue;
17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								lsa6 = *sin6;
17458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								if (in6_recoverscope(&lsa6,
17468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen										     &lsa6.sin6_addr,
17478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen										     NULL))
17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									/*
17498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * bad link
17508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * local
17518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * address
17528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 */
17538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								continue;
17548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sin6 = &lsa6;
17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* SCTP_KAME */
17568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
17578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
17588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((site_scope == 0) &&
17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						memcpy(sas, sin6, sizeof(*sin6));
17647988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						actual += sizeof(*sin6);
17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (actual >= limit) {
17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							return (actual);
17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
17718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
17748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17757988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
17767988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				case AF_CONN:
17777988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					if (conn_addr_legal) {
17787988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						memcpy(sas, &sctp_ifa->address.sconn, sizeof(struct sockaddr_conn));
17797988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
17807988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_conn));
17817988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						actual += sizeof(struct sockaddr_conn);
17827988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						if (actual >= limit) {
17837988ea8f0c067cf3757e798b473b1ae4d34b6dfdt							return (actual);
17847988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						}
17857988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					} else {
17867988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						continue;
17877988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					}
17887988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
17898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				default:
17908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* TSNH */
17918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
17928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
17938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
17948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
17968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_laddr *laddr;
1797f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifndef HAVE_SA_LEN
17988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t sa_len = 0;
17998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18007988ea8f0c067cf3757e798b473b1ae4d34b6dfdt
18018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
18028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
18038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
18048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
18058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
18068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
18097988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			switch (laddr->ifa->address.sa.sa_family) {
18107988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET
18117988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_INET:
18127988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
18137988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18157988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET6
18167988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_INET6:
18177988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
18187988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18197988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18207988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
18217988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_CONN:
18227988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				((struct sockaddr_conn *)sas)->sconn_port = inp->sctp_lport;
18237988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18247988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18257988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			default:
18267988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				/* TSNH */
18277988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18287988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			}
1829f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
18308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sas = (struct sockaddr_storage *)((caddr_t)sas +
18318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							  laddr->ifa->address.sa.sa_len);
18328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			actual += laddr->ifa->address.sa.sa_len;
18338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
18347988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			switch (laddr->ifa->address.sa.sa_family) {
18357988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET
18367988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_INET:
18377988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				sa_len = sizeof(struct sockaddr_in);
18387988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18397988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18407988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef INET6
18417988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_INET6:
18427988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				sa_len = sizeof(struct sockaddr_in6);
18437988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18447988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18457988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
18467988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			case AF_CONN:
18477988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				sa_len = sizeof(struct sockaddr_conn);
18487988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18497988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
18507988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			default:
18517988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				/* TSNH */
18527988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				break;
18537988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			}
18548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sas = (struct sockaddr_storage *)((caddr_t)sas + sa_len);
18558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			actual += sa_len;
18568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (actual >= limit) {
18588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (actual);
18598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (actual);
18638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
18648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic size_t
18668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_fill_up_addresses(struct sctp_inpcb *inp,
18678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                       struct sctp_tcb *stcb,
18688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                       size_t limit,
18698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                       struct sockaddr_storage *sas)
18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	size_t size = 0;
18728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
18738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t id;
18748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RLOCK();
18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FIX ME: ?? this WILL report duplicate addresses if they appear
18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * in more than one VRF.
18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill up addresses for all VRFs on the endpoint */
18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (id = 0; (id < inp->num_vrfs) && (size < limit); id++) {
18848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size += sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
18858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						   inp->m_vrf_ids[id]);
18868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sas = (struct sockaddr_storage *)((caddr_t)sas + size);
18878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
18898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill up addresses for the endpoint's default vrf */
18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
18918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  inp->def_vrf_id);
18928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RUNLOCK();
18948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (size);
18958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
18968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
18988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: assumes addr lock is held
18998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
19008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
19018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
19028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int cnt = 0;
19048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_vrf *vrf = NULL;
19058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
19078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * In both sub-set bound an bound_all cases we return the MAXIMUM
19088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * number of addresses that you COULD get. In reality the sub-set
19098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * bound may have an exclusion list for a given TCB OR in the
19108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * bound-all case a TCB may NOT include the loopback or other
19118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * addresses as well.
19128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
19138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf = sctp_find_vrf(vrf_id);
19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (vrf == NULL) {
19158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
19168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_ifn *sctp_ifn;
19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_ifa *sctp_ifa;
19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
19238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Count them if they are the right type */
19248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				switch (sctp_ifa->address.sa.sa_family) {
19258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
19268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET:
19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						cnt += sizeof(struct sockaddr_in6);
19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					else
19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						cnt += sizeof(struct sockaddr_in);
19318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
19348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET6:
19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					cnt += sizeof(struct sockaddr_in6);
19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
19378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19387988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
19397988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				case AF_CONN:
19407988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					cnt += sizeof(struct sockaddr_conn);
19417988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					break;
19427988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
19438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				default:
19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
19468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
19498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_laddr *laddr;
19508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
19528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			switch (laddr->ifa->address.sa.sa_family) {
19538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
19548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET:
19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					cnt += sizeof(struct sockaddr_in6);
19578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					cnt += sizeof(struct sockaddr_in);
19598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
19628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET6:
19638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cnt += sizeof(struct sockaddr_in6);
19648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
19658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
196675cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
196775cd23222c96d5ebe5a9082c57a263f917f1462btuexen			case AF_CONN:
196875cd23222c96d5ebe5a9082c57a263f917f1462btuexen				cnt += sizeof(struct sockaddr_conn);
196975cd23222c96d5ebe5a9082c57a263f917f1462btuexen				break;
197075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
19718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			default:
19728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
19738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (cnt);
19778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
19808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_count_max_addresses(struct sctp_inpcb *inp)
19818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int cnt = 0;
19838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
19848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int id;
19858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RLOCK();
19888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
19898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
19908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FIX ME: ?? this WILL count duplicate addresses if they appear
19918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * in more than one VRF.
19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
19938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* count addresses for all VRFs on the endpoint */
19948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (id = 0; id < inp->num_vrfs; id++) {
19958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cnt += sctp_count_max_addresses_vrf(inp, inp->m_vrf_ids[id]);
19968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* count addresses for the endpoint's default VRF */
19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RUNLOCK();
20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (cnt);
20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
20068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
20078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		  size_t optsize, void *p, int delay)
20088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
20098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error = 0;
20108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int creat_lock_on = 0;
20118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb = NULL;
20128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *sa;
20138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
2015b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int bad_addresses = 0;
20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_assoc_t *a_id;
20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We are already connected AND the TCP model */
20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EADDRINUSE);
20258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
20288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2030b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
20348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
20358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = LIST_FIRST(&inp->sctp_asoc_list);
20368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
20378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
20398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
20408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EALREADY);
20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_INCR_REF(inp);
20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_ASOC_CREATE_LOCK(inp);
20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	creat_lock_on = 1;
20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EFAULT;
20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	totaddrp = (int *)optval;
20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	totaddr = *totaddrp;
20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sa = (struct sockaddr *)(totaddrp + 1);
2054b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
2055b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((stcb != NULL) || bad_addresses) {
20568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Already have or am bring up an association */
20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_ASOC_CREATE_UNLOCK(inp);
20588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		creat_lock_on = 0;
20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb)
20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (bad_addresses == 0) {
20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
20638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EALREADY;
20648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
20668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
20688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (num_v6 > 0)) {
20708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
20718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (num_v4 > 0)) {
20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct in6pcb *inp6;
20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp6 = (struct in6pcb *)inp;
20788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_IPV6_V6ONLY(inp6)) {
20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * if IPV6_V6ONLY flag, ignore connections destined
20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * to a v4 addr or v4-mapped addr
20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
20838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_now;
20868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* INET6 */
20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
20908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_PCB_FLAGS_UNBOUND) {
20918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Bind a ephemeral port */
20928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_inpcb_bind(so, NULL, NULL, p);
20938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_now;
20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* FIX ME: do we want to pass in a vrf on the connect call? */
20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf_id = inp->def_vrf_id;
2100000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
21018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* We are GOOD to go */
21038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
21048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
21058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       (struct thread *)p
21068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__)
21078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       (PKTHREAD)p
21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       (struct proc *)p
21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		);
21128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Gak! no memory */
21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Set the connected flag so we can queue data */
21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		soisconnecting(so);
21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* move to second address */
21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (sa->sa_family) {
21248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
21258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
21268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
21278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
21298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
21308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
21318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
21348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = 0;
21398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_connectx_helper_add(stcb, sa, (totaddr-1), &error);
21408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Fill in the return id */
21418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error) {
21428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_6);
21438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
21448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	a_id = (sctp_assoc_t *)optval;
21468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*a_id = sctp_get_associd(stcb);
21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* initialize authentication parameters for the assoc */
21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_initialize_auth_params(inp, stcb);
21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (delay) {
21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* doing delayed connection */
21538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.delayed_connection = 1;
21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
21558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
21568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
21578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
21588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
21608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Set the connected flag so we can queue data */
21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		soisconnecting(so);
21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out_now:
21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (creat_lock_on) {
21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_ASOC_CREATE_UNLOCK(inp);
21688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
21698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_DECR_REF(inp);
2170b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (error);
21718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
21748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
21758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
21768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp); \
21778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = LIST_FIRST(&inp->sctp_asoc_list); \
21788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) { \
21798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(stcb); \
21808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                } \
21818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp); \
21828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (assoc_id > SCTP_ALL_ASSOC) { \
21838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) { \
21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT; \
21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break; \
21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} \
21898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else { \
21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = NULL; \
21918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        } \
21928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  }
21938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21950ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
21968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (size < sizeof(type)) { \
21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL; \
21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break; \
22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else { \
22018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		destp = (type *)srcp; \
22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} \
22038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen      }
22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__) || defined(__Userspace__)
22068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
22078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
22118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    void *p) {
22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp = NULL;
22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error, val = 0;
22148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb = NULL;
22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (optval == NULL) {
22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EINVAL);
22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
22222fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
22238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return EINVAL;
22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = 0;
22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (optname) {
22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NODELAY:
22308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTOCLOSE:
22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EXPLICIT_EOR:
22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTO_ASCONF:
22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DISABLE_FRAGMENTS:
22348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_I_WANT_MAPPED_V4_ADDR:
22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_USE_EXT_RCVINFO:
22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (optname) {
22388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_DISABLE_FRAGMENTS:
22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_I_WANT_MAPPED_V4_ADDR:
22428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
22438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTO_ASCONF:
22458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
22468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* only valid for bound all sockets */
22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
22498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
22508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
22518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto flags_out;
22528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_EXPLICIT_EOR:
22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_NODELAY:
22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_USE_EXT_RCVINFO:
22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTOCLOSE:
22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
22658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				val = 0;
22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
22718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
22728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOPROTOOPT;
22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} /* end switch (sopt->sopt_name) */
22748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*optsize < sizeof(val)) {
22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	flags_out:
22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
22808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* return the option value */
22828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*(int *)optval = val;
22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(val);
22848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        case SCTP_GET_PACKET_LOG:
22878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
22888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef  SCTP_PACKET_LOGGING
22898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint8_t *target;
22908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int ret;
22918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ret = sctp_copy_out_packet_log(target , (int)*optsize);
22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = ret;
22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EOPNOTSUPP;
22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_REUSE_PORT:
23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
23048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
23068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't do this for a 1-m socket */
23078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
23088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
23098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
23118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
23128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
23138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PARTIAL_DELIVERY_POINT:
23168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
23188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
23208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = inp->partial_delivery_point;
23218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
23228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_FRAGMENT_INTERLEAVE:
23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
23278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
23298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
23308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*value = SCTP_FRAG_LEVEL_2;
23328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
23338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*value = SCTP_FRAG_LEVEL_1;
23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
23368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*value = SCTP_FRAG_LEVEL_0;
23378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
23398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CMT_ON_OFF:
23428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
23448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
23468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
23478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
23488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = stcb->asoc.sctp_cmt_on_off;
23498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
23508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
23518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
23528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
23538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
23548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
23558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				av->assoc_value = inp->sctp_cmt_on_off;
23568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
23578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
23588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
23598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
23608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
23618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
23638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
23648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PLUGGABLE_CC:
23688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
23708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
23728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
23738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
23748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = stcb->asoc.congestion_control_module;
23758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
23768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
23778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
23788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
23798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
23808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
23818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
23828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
23838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
23848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
23858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
23868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
23878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
23898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
23908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CC_OPTION:
23948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
23958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_cc_option *cc_opt;
23968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
23988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
23998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
24008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
24018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
24028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
24038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = ENOTSUP;
24048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
24058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 0, cc_opt);
24068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*optsize = sizeof(struct sctp_cc_option);
24078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
24098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
24118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PLUGGABLE_SS:
24138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
24148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
24158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
24178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
24188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
24198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = stcb->asoc.stream_scheduling_module;
24208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
24218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
24228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
24238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
24248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
24258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
24268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
24278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
24288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
24298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
24308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
24318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
24348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
24358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
24378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SS_VALUE:
24398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
24408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_stream_value *av;
24418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
24438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
24448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
24458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
24468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                                              &av->stream_value) < 0) {
24478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
24488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
24498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
24508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*optsize = sizeof(struct sctp_stream_value);
24518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
24538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
24548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't get stream value without association */
24558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
24568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
24578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
24598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_ADDR_LEN:
24618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
24628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
24638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
24658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
24668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
24678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (av->assoc_value == AF_INET) {
24688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = sizeof(struct sockaddr_in);
24698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = 0;
24708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
24728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
24738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (av->assoc_value == AF_INET6) {
24748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = sizeof(struct sockaddr_in6);
24758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = 0;
24768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
247875cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
247975cd23222c96d5ebe5a9082c57a263f917f1462btuexen		if (av->assoc_value == AF_CONN) {
248075cd23222c96d5ebe5a9082c57a263f917f1462btuexen			av->assoc_value = sizeof(struct sockaddr_conn);
248175cd23222c96d5ebe5a9082c57a263f917f1462btuexen			error = 0;
248275cd23222c96d5ebe5a9082c57a263f917f1462btuexen		}
248375cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
24848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
24858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
24868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
24878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
24888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
24908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_ASSOC_NUMBER:
24928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
24938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value, cnt;
24948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
24968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cnt = 0;
24978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
24988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
24998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt++;
25008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
25028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = cnt;
25038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
25048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_ASSOC_ID_LIST:
25078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_ids *ids;
25098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		unsigned int at, limit;
2510000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
25118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
25128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		at = 0;
25138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		limit = (*optsize-sizeof(uint32_t))/ sizeof(sctp_assoc_t);
25148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
25158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
25168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (at < limit) {
25178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
25188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
25198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
25208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
25218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
25228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
25238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
25258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
25268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ids->gaids_number_of_ids = at;
25278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
25288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CONTEXT:
25328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
25348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
25368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
25378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
25398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = stcb->asoc.context;
25408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
25418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
25428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
25438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
25448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
25458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
25468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				av->assoc_value = inp->sctp_context;
25478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
25488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
25498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
25508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
25518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
25528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
25548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
25558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_VRF_ID:
25598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *default_vrfid;
25618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
25638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*default_vrfid = inp->def_vrf_id;
25648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
25658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_ASOC_VRF:
25688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *id;
25708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
25728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, id->assoc_id);
25738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
25748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
25758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
25768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
25778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			id->assoc_value = stcb->asoc.vrf_id;
25788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
25798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
25818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_VRF_IDS:
25838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
25848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
25858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int siz_needed;
25868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *vrf_ids;
25878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(vrf_ids, optval, uint32_t, *optsize);
25898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		siz_needed = inp->num_vrfs * sizeof(uint32_t);
25908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*optsize < siz_needed) {
25918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
25928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
25938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
25948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(vrf_ids, inp->m_vrf_ids, siz_needed);
25958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = siz_needed;
25968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
25988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
25998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EOPNOTSUPP;
26008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
26018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
26028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_NONCE_VALUES:
26048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
26058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_get_nonce_values *gnv;
26068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
26088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
26098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
26118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			gnv->gn_peers_tag = stcb->asoc.peer_vtag;
26128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			gnv->gn_local_tag = stcb->asoc.my_vtag;
26138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
26148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_get_nonce_values);
26158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
26168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
26178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOTCONN;
26188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
26208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DELAYED_SACK:
26228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
26238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sack_info *sack;
26248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
26268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
26278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
26288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sack->sack_delay = stcb->asoc.delayed_ack;
26298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sack->sack_freq = stcb->asoc.sack_freq;
26308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
26318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
26328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
26338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
26348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
26358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
26368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
26378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
26388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
26398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
26408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
26418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
26428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
26438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
26458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_sack_info);
26468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
26488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_SNDBUF_USE:
26508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
26518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sockstat *ss;
26528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
26548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
26558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
26578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
26588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
26598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 stcb->asoc.size_on_all_streams);
26608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
26618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_sockstat);
26628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
26638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
26648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOTCONN;
26658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
26678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_MAX_BURST:
26698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
26708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 900000
26718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint8_t *value;
26728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint8_t, *optsize);
26748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
26768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_ep.max_burst < 256) {
26778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*value = inp->sctp_ep.max_burst;
26788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
26798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*value = 255;
26808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
26828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint8_t);
26838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
26848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
26858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
26878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
26888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
26908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = stcb->asoc.max_burst;
26918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
26928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
26938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
26948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
26958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
26968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
26978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				av->assoc_value = inp->sctp_ep.max_burst;
26988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
26998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
27008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
27018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
27028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
27038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
27058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
27068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
27088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
27098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
27108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_MAXSEG:
27118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
27128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
27138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int ovh;
27148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
27168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
27178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
27198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
27208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
27218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
27228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
27238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
27248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
27258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
27268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
27278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ovh = SCTP_MED_OVERHEAD;
27288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
27298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ovh = SCTP_MED_V4_OVERHEAD;
27308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
27318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
27328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					av->assoc_value = 0;
27338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
27348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					av->assoc_value = inp->sctp_frag_point - ovh;
27358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
27368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
27378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
27388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
27398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
27408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
27428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assoc_value);
27438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
27458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
27468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_STAT_LOG:
27478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_fill_stat_log(optval, optsize);
27488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
27498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EVENTS:
27508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
27518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_event_subscribe *events;
27528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
27548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memset(events, 0, sizeof(struct sctp_event_subscribe));
27558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
27568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
27578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_data_io_event = 1;
27588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
27608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_association_event = 1;
27618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
27638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_address_event = 1;
27648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
27668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_send_failure_event = 1;
27678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
27698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_peer_error_event = 1;
27708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
27728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_shutdown_event = 1;
27738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
27758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_partial_delivery_event = 1;
27768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
27788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_adaptation_layer_event = 1;
27798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
27818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_authentication_event = 1;
27828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
27848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_sender_dry_event = 1;
27858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
27878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			events->sctp_stream_reset_event = 1;
27888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
27898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(struct sctp_event_subscribe);
27908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
27918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
27928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ADAPTATION_LAYER:
27938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
27948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
27958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
27978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
27998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = inp->sctp_ep.adaptation_layer_indicator;
28008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
28018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
28028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
28038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SET_INITIAL_DBG_SEQ:
28058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
28068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
28078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
28098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
28108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = inp->sctp_ep.initial_sequence_debug;
28118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
28128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
28138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
28148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_LOCAL_ADDR_SIZE:
28168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
28178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
28188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
28208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
28218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*value = sctp_count_max_addresses(inp);
28228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
28238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(uint32_t);
28248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
28258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_REMOTE_ADDR_SIZE:
28278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
28288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
28298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t size;
28308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
28318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
28338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* FIXME MT: change to sctp_assoc_value? */
28348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
28358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
28378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			size = 0;
28388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Count the sizes */
28398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
28408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
28418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					size += sizeof(struct sockaddr_in6);
28428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
28438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
28448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
28458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case AF_INET:
28468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						size += sizeof(struct sockaddr_in);
28478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
28488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
28498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
28508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case AF_INET6:
28518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						size += sizeof(struct sockaddr_in6);
28528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
28538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
285475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
285575cd23222c96d5ebe5a9082c57a263f917f1462btuexen					case AF_CONN:
285675cd23222c96d5ebe5a9082c57a263f917f1462btuexen						size += sizeof(struct sockaddr_conn);
285775cd23222c96d5ebe5a9082c57a263f917f1462btuexen						break;
285875cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
28598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					default:
28608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
28618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
28628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
28638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
28648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
28658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*value = (uint32_t) size;
28668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(uint32_t);
28678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
28688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
28698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOTCONN;
28708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
28728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_PEER_ADDRESSES:
28748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
28758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Get the address information, an array is passed in to
28768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * fill up we pack it.
28778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
28788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
28798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t cpsz, left;
28808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_storage *sas;
28818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
28828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_getaddresses *saddr;
28838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
28858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
28868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
28888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			left = (*optsize) - sizeof(struct sctp_getaddresses);
28898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_getaddresses);
28908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sas = (struct sockaddr_storage *)&saddr->addr[0];
28918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
28938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
28948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					cpsz = sizeof(struct sockaddr_in6);
28958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
28968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
28978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
28988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case AF_INET:
28998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						cpsz = sizeof(struct sockaddr_in);
29008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
29018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
29038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					case AF_INET6:
29048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						cpsz = sizeof(struct sockaddr_in6);
29058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
29068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
290775cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
290875cd23222c96d5ebe5a9082c57a263f917f1462btuexen					case AF_CONN:
290975cd23222c96d5ebe5a9082c57a263f917f1462btuexen						cpsz = sizeof(struct sockaddr_conn);
291075cd23222c96d5ebe5a9082c57a263f917f1462btuexen						break;
291175cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
29128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					default:
29138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						cpsz = 0;
29148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
29158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
29168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (cpsz == 0) {
29188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
29198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (left < cpsz) {
29218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* not enough room. */
29228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
29238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(INET) && defined(INET6)
29258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
29268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
29278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Must map the address */
29288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
29298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    (struct sockaddr_in6 *)sas);
29308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
29318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					memcpy(sas, &net->ro._l_addr, cpsz);
29338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(INET) && defined(INET6)
29348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				((struct sockaddr_in *)sas)->sin_port = stcb->rport;
29378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
29398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				left -= cpsz;
29408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*optsize += cpsz;
29418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
29428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
29438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
29448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
29458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT;
29468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
29488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_LOCAL_ADDRESSES:
29508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
29518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t limit, actual;
29528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_storage *sas;
29538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_getaddresses *saddr;
29548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
29568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
29578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sas = (struct sockaddr_storage *)&saddr->addr[0];
29598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		limit = *optsize - sizeof(sctp_assoc_t);
29608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
29618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
29628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
29638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(struct sockaddr_storage) + actual;
29658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
29668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEER_ADDR_PARAMS:
29688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
29698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paddrparams *paddrp;
29708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
29718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
29738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
29748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
29768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
29778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
29788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
29798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
29808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
29818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
29828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
29838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
29848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
29858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
29868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
29878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
29888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb && (net == NULL)) {
29908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr *sa;
29918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sa = (struct sockaddr *)&paddrp->spp_address;
29938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
29948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET) {
29958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in *sin;
29968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin = (struct sockaddr_in *)sa;
29988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin->sin_addr.s_addr) {
29998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
30008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
30018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
30028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
30038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
30058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
30068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
30078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET6) {
30088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in6 *sin6;
30098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6 = (struct sockaddr_in6 *)sa;
30118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
30128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
30138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
30148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
30158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
30168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
30188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
301975cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
302075cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
302175cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
302275cd23222c96d5ebe5a9082c57a263f917f1462btuexen
302375cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
302475cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
302575cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
302675cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
302775cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
302875cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
302975cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
303075cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
303175cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
30328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			{
30338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EAFNOSUPPORT;
30348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
30358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
30368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
30378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
30388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
30418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Applies to the specific association */
30428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddrp->spp_flags = 0;
30438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net) {
30448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				int ovh;
30458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
30468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ovh = SCTP_MED_OVERHEAD;
30478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
30488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					ovh = SCTP_MED_V4_OVERHEAD;
30498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_hbinterval = net->heart_beat_delay;
30528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmaxrxt = net->failure_threshold;
30538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmtu = net->mtu - ovh;
30548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get flags for HB */
30558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dest_state & SCTP_ADDR_NOHB) {
30568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_DISABLE;
30578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
30588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_ENABLE;
30598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get flags for PMTU */
30618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
30628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
30638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
30648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
30658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dscp & 0x01) {
30678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_dscp = net->dscp & 0xfc;
30688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_DSCP;
30698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
30718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
30728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (net->flowlabel & 0x80000000)) {
30738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
30748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
30758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
30778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
30788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
30798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * No destination so return default
30808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * value
30818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
30828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
30838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
30848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb->asoc.default_dscp & 0x01) {
30858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
30868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_DSCP;
30878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
30898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb->asoc.default_flowlabel & 0x80000000) {
30908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
30918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
30928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
30948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* default settings should be these */
30958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
30968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_DISABLE;
30978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
30988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_ENABLE;
30998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
31018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
31028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
31038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
31048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
31068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddrp->spp_assoc_id = sctp_get_associd(stcb);
31088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
31098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
31108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
31118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
31128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
31138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Use endpoint defaults */
31148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
31158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
31168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
31178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
31188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get inp's default */
31198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (inp->sctp_ep.default_dscp & 0x01) {
31208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
31218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_DSCP;
31228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
31248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
31258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (inp->sctp_ep.default_flowlabel & 0x80000000)) {
31268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
31278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
31288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
31308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* can't return this */
31318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddrp->spp_pathmtu = 0;
31328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
31348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_ENABLE;
31358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
31368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_HB_DISABLE;
31378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
31398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_ENABLE;
31408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
31418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					paddrp->spp_flags |= SPP_PMTUD_DISABLE;
31428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
31438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
31448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
31458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
31468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
31478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
31498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
31508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_paddrparams);
31518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
31528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
31538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
31548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_GET_PEER_ADDR_INFO:
31558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
31568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paddrinfo *paddri;
31578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
31588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
31608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
31618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
31638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
31648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
31658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
31668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
31678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
31688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
31698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
31708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
31718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
31728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
31738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
31748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
31768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb) && (net)) {
31788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
31798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* It's unconfirmed */
31808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddri->spinfo_state = SCTP_UNCONFIRMED;
31818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
31828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* It's active */
31838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddri->spinfo_state = SCTP_ACTIVE;
31848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
31858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* It's inactive */
31868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				paddri->spinfo_state = SCTP_INACTIVE;
31878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddri->spinfo_cwnd = net->cwnd;
31898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
31908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddri->spinfo_rto = net->RTO;
31918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddri->spinfo_assoc_id = sctp_get_associd(stcb);
31928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			paddri->spinfo_mtu = net->mtu;
31938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
31948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_paddrinfo);
31958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
31968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
31978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
31988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
32008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT;
32018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
32038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PCB_STATUS:
32058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
32068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_pcbinfo *spcb;
32078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
32098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_fill_pcbinfo(spcb);
32108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(struct sctp_pcbinfo);
32118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
32128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_STATUS:
32148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
32158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
32168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_status *sstat;
32178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
32198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
32208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
32228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
32238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
32248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
32258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
32278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * I think passing the state is fine since
32288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * sctp_constants.h will be available to the user
32298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * land.
32308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
32318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_state = stcb->asoc.state;
32328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_assoc_id = sctp_get_associd(stcb);
32338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
32348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
32358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
32368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * We can't include chunks that have been passed to
32378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the socket layer. Only things in queue.
32388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
32398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
32408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 stcb->asoc.cnt_on_all_streams);
32418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_instrms = stcb->asoc.streamincnt;
32448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
32458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
3246f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
32478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(&sstat->sstat_primary.spinfo_address,
32488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       &stcb->asoc.primary_destination->ro._l_addr,
32498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
32508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
32518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET) {
32528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(&sstat->sstat_primary.spinfo_address,
32538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       &stcb->asoc.primary_destination->ro._l_addr,
32548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       sizeof(struct sockaddr_in));
32558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
32568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(&sstat->sstat_primary.spinfo_address,
32578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       &stcb->asoc.primary_destination->ro._l_addr,
32588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       sizeof(struct sockaddr_in6));
32598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
32618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = stcb->asoc.primary_destination;
32628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
32638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
32648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Again the user can get info from sctp_constants.h
32658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * for what the state of the network is.
32668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
32678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
32688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* It's unconfirmed */
32698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
32708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (net->dest_state & SCTP_ADDR_REACHABLE) {
32718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* It's active */
32728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
32738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
32748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* It's inactive */
32758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
32768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_primary.spinfo_cwnd = net->cwnd;
32788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
32798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_primary.spinfo_rto = net->RTO;
32808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_primary.spinfo_mtu = net->mtu;
32818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
32828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
32838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(struct sctp_status);
32848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
32858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RTOINFO:
32878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
32888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_rtoinfo *srto;
32898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
32918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
32928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
32948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			srto->srto_initial = stcb->asoc.initial_rto;
32958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			srto->srto_max = stcb->asoc.maxrto;
32968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			srto->srto_min = stcb->asoc.minrto;
32978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
32988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
32998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
33008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
33018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
33028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
33038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				srto->srto_initial = inp->sctp_ep.initial_rto;
33048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				srto->srto_max = inp->sctp_ep.sctp_maxrto;
33058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				srto->srto_min = inp->sctp_ep.sctp_minrto;
33068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
33078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
33088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
33098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
33108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
33118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
33138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_rtoinfo);
33148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
33168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMEOUTS:
33188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
33198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_timeouts *stimo;
33208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
33228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
33238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
33258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_init= stcb->asoc.timoinit;
33268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_data= stcb->asoc.timodata;
33278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_sack= stcb->asoc.timosack;
33288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_shutdown= stcb->asoc.timoshutdown;
33298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_heartbeat= stcb->asoc.timoheartbeat;
33308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_cookie= stcb->asoc.timocookie;
33318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stimo->stimo_shutdownack= stcb->asoc.timoshutdownack;
33328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
33338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_timeouts);
33348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
33358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
33368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
33378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
33398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ASSOCINFO:
33418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
33428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assocparams *sasoc;
33438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
33458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
33468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
33488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
33498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
33508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
33518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
33528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
33538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
33548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
33558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
33568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
33578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
33588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
33598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
33608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
33618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_number_peer_destinations = 0;
33628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_peer_rwnd = 0;
33638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
33648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
33658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
33668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
33678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
33688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
33698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
33718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_assocparams);
33728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
33748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_SEND_PARAM:
33768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
33778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sndrcvinfo *s_info;
33788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
33808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
33818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
33838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
33848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
33858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
33868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
33878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
33888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
33898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
33908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
33918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
33928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
33938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
33948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
3395000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			}
33968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
33988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_sndrcvinfo);
33998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
34018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_INITMSG:
34038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
34048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_initmsg *sinit;
34058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
34078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
34088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
34098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
34108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
34118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
34128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
34138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = sizeof(struct sctp_initmsg);
34148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
34158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PRIMARY_ADDR:
34178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we allow a "get" operation on this */
34188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
34198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_setprim *ssp;
34208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
34228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
34238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
34258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* simply copy out the sockaddr_storage... */
342618818c8dd0d4cafdb259fa73f01f7825948faadct			size_t len;
34278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			len = *optsize;
3429f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
34308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len)
34318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len;
34328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
34338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET &&
34348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    len > sizeof(struct sockaddr_in))
34358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				len = sizeof(struct sockaddr_in);
34368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else if (
34378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    stcb->asoc.primary_destination->ro._l_addr.sa.sa_family == AF_INET6 &&
34388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    len > sizeof(struct sockaddr_in6))
34398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				len = sizeof(struct sockaddr_in6);
34408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
34418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(&ssp->ssp_addr,
34438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       &stcb->asoc.primary_destination->ro._l_addr,
34448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       len);
34458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
34468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_setprim);
34478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
34488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
34498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
34508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
34528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_HMAC_IDENT:
34548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
34558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_hmacalgo *shmac;
34568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmaclist_t *hmaclist;
34578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t size;
34588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int i;
34598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
34618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
34638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hmaclist = inp->sctp_ep.local_hmacs;
34648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hmaclist == NULL) {
34658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no HMACs to return */
34668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(*shmac);
34678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
34688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
34698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* is there room for all of the hmac ids? */
34718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size = sizeof(*shmac) + (hmaclist->num_algo *
34728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 sizeof(shmac->shmac_idents[0]));
34738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((size_t)(*optsize) < size) {
34748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
34758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
34768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
34778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
34788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* copy in the list */
34808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		shmac->shmac_number_of_idents = hmaclist->num_algo;
34818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < hmaclist->num_algo; i++) {
34828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			shmac->shmac_idents[i] = hmaclist->hmac[i];
34838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
34858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = size;
34868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
34878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_ACTIVE_KEY:
34898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
34908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authkeyid *scact;
34918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
34938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
34948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
34968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* get the active key on the assoc */
34978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
34988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
34998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
35008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
35018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
35028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
35038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get the endpoint active key */
35048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
35058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				scact->scact_keynumber = inp->sctp_ep.default_keyid;
35068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
35078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
35088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
35098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
35108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
35118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
35138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_authkeyid);
35148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
35168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_LOCAL_AUTH_CHUNKS:
35188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
35198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authchunks *sac;
35208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auth_chklist_t *chklist = NULL;
35218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t size = 0;
35228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
35248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
35258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
35278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* get off the assoc */
35288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chklist = stcb->asoc.local_auth_chunks;
35298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* is there enough space? */
35308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			size = sctp_auth_get_chklist_size(chklist);
35318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
35328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
35338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
35348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
35358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* copy in the chunks */
35368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
35371a2e446bdbc52cc6178a3f80092943a84706ece9tuexen				sac->gauth_number_of_chunks = (uint32_t)size;
35388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*optsize = sizeof(struct sctp_authchunks) + size;
35398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
35408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
35418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
35428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
35438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
35448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
35458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get off the endpoint */
35468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
35478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				chklist = inp->sctp_ep.local_auth_chunks;
35488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* is there enough space? */
35498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				size = sctp_auth_get_chklist_size(chklist);
35508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
35518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
35528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
35538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
35548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* copy in the chunks */
35558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
35561a2e446bdbc52cc6178a3f80092943a84706ece9tuexen					sac->gauth_number_of_chunks = (uint32_t)size;
35578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					*optsize = sizeof(struct sctp_authchunks) + size;
35588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
35598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
35608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
35618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
35628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
35638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
35648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
35668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEER_AUTH_CHUNKS:
35688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
35698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authchunks *sac;
35708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auth_chklist_t *chklist = NULL;
35718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t size = 0;
35728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
35748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
35758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
35778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* get off the assoc */
35788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chklist = stcb->asoc.peer_auth_chunks;
35798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* is there enough space? */
35808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			size = sctp_auth_get_chklist_size(chklist);
35818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
35828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
35838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
35848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
35858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* copy in the chunks */
35868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
35871a2e446bdbc52cc6178a3f80092943a84706ece9tuexen				sac->gauth_number_of_chunks = (uint32_t)size;
35888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*optsize = sizeof(struct sctp_authchunks) + size;
35898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
35908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
35918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
35928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
35938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT;
35948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
35968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
35988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEELOFF:
35998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
36008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_peeloff_opt *peeloff;
36018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(peeloff, optval, struct sctp_peeloff_opt, *optsize);
36038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* do the peeloff */
36048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_peeloff_option(p, peeloff);
36058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
36068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_peeloff_opt);
36078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	break;
36108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* HAVE_SCTP_PEELOFF_SOCKOPT */
36118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EVENT:
36128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
36138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_event *event;
36148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t event_type;
36158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
36178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
36188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (event->se_type) {
36208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ASSOC_CHANGE:
36218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
3622000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_PEER_ADDR_CHANGE:
36248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
3625000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_REMOTE_ERROR:
36278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVPEERERR;
3628000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SEND_FAILED:
36308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
3631000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SHUTDOWN_EVENT:
36338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
3634000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ADAPTATION_INDICATION:
36368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
3637000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_PARTIAL_DELIVERY_EVENT:
36398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
3640000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTHENTICATION_EVENT:
36428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_AUTHEVNT;
3643000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_STREAM_RESET_EVENT:
36458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
3646000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SENDER_DRY_EVENT:
36488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_DRYEVNT;
3649000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
36508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_NOTIFICATIONS_STOPPED_EVENT:
36518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = 0;
36528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
36538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOTSUP;
36548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
3655298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen		case SCTP_ASSOC_RESET_EVENT:
3656298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
3657298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			break;
3658298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen		case SCTP_STREAM_CHANGE_EVENT:
3659298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
3660298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			break;
36615741e159bdf238ef4b61085d6fbfea2947386238tuexen		case SCTP_SEND_FAILED_EVENT:
36625741e159bdf238ef4b61085d6fbfea2947386238tuexen			event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
36635741e159bdf238ef4b61085d6fbfea2947386238tuexen			break;
36648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
36658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = 0;
36668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
36678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
36688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
36698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (event_type > 0) {
36718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
36728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
36738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
36748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
36758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
36768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
36778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
36788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RLOCK(inp);
36798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					event->se_on = sctp_is_feature_on(inp, event_type);
36808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RUNLOCK(inp);
36818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
36828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
36838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
36848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
36858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
36868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
36888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_event);
36898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
36908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
36918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RECVRCVINFO:
36938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
36948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int onoff;
36958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*optsize < sizeof(int)) {
36978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
36988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
36998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
37006f63c1f0e9307e260e6d8724b12d0153cedb4a9atuexen			SCTP_INP_RLOCK(inp);
37018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
37028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
37038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
37058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* return the option value */
37068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*(int *)optval = onoff;
37078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(int);
37088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
37118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RECVNXTINFO:
37128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
37138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int onoff;
37148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*optsize < sizeof(int)) {
37168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
37178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
37188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
37196f63c1f0e9307e260e6d8724b12d0153cedb4a9atuexen			SCTP_INP_RLOCK(inp);
37208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
37218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
37228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
37248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* return the option value */
37258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*(int *)optval = onoff;
37268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(int);
37278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
37308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_SNDINFO:
37318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
37328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sndinfo *info;
37338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
37358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
37368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
37388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->snd_sid = stcb->asoc.def_send.sinfo_stream;
37398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->snd_flags = stcb->asoc.def_send.sinfo_flags;
37408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->snd_flags &= 0xfff0;
37418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
37428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->snd_context = stcb->asoc.def_send.sinfo_context;
37438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
37448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
37458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
37468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
37478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
37488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
37498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->snd_sid = inp->def_send.sinfo_stream;
37508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->snd_flags = inp->def_send.sinfo_flags;
37518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->snd_flags &= 0xfff0;
37528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->snd_ppid = inp->def_send.sinfo_ppid;
37538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->snd_context = inp->def_send.sinfo_context;
37548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
37558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
37568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
37578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
37588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
37598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
37618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_sndinfo);
37628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
37658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_PRINFO:
37668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
37678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_default_prinfo *info;
37688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
37708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
37718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
37738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
37748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
37758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
37768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
37778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
37788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
37798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
37808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
37818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
37828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				info->pr_value = inp->def_send.sinfo_timetolive;
37838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
37848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
37858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
37868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
37878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
37888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
37908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_default_prinfo);
37918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
37948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEER_ADDR_THLDS:
37958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
37968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paddrthlds *thlds;
37978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
37988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
38008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
38018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
38038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
38048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
38058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
38068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
38078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
38088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
38098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
38108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
38118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
38128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
38138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
38148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
38158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3816b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (stcb && (net == NULL)) {
38178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr *sa;
38188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sa = (struct sockaddr *)&thlds->spt_address;
38208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
38218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET) {
38228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in *sin;
38238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin = (struct sockaddr_in *)sa;
38258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin->sin_addr.s_addr) {
38268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
38278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
38288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
38298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
38308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
38318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
38328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
38338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
38348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET6) {
38358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in6 *sin6;
38368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6 = (struct sockaddr_in6 *)sa;
38388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
38398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
38408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
38418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
38428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
38438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
38448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
38458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
384675cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
384775cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
384875cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
384975cd23222c96d5ebe5a9082c57a263f917f1462btuexen
385075cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
385175cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
385275cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
385375cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
385475cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
385575cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
385675cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
385775cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
385875cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
38598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			{
38608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EAFNOSUPPORT;
38618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
38628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
38638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
38648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
38658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
38688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net) {
38698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				thlds->spt_pathmaxrxt = net->failure_threshold;
38708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				thlds->spt_pathpfthld = net->pf_threshold;
38718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
38728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
38738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
38748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
38758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			thlds->spt_assoc_id = sctp_get_associd(stcb);
38768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
38778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
38788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
38798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
38808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
38818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Use endpoint defaults */
38828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
38838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
3884000a5bac556b28e74e4e98c540f66b1743e9312dtuexen				thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
38858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
38868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
38878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
38888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
38898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
38908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error == 0) {
38928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*optsize = sizeof(struct sctp_paddrthlds);
38938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3896153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	case SCTP_REMOTE_UDP_ENCAPS_PORT:
3897153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	{
3898153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		struct sctp_udpencaps *encaps;
3899153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		struct sctp_nets *net;
3900000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
3901153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
3902153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
3903153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
3904153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (stcb) {
3905153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
3906153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		} else {
3907153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			/* We increment here since sctp_findassociation_ep_addr() wil
3908153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 * do a decrement if it finds the stcb as long as the locked
3909153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
3910153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 */
3911153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			net = NULL;
3912153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			SCTP_INP_INCR_REF(inp);
3913153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
3914153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (stcb == NULL) {
3915153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_DECR_REF(inp);
3916153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
3917153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
3918153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (stcb && (net == NULL)) {
3919153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			struct sockaddr *sa;
3920000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
3921153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			sa = (struct sockaddr *)&encaps->sue_address;
3922153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#ifdef INET
3923153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (sa->sa_family == AF_INET) {
3924153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				struct sockaddr_in *sin;
3925153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
3926153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				sin = (struct sockaddr_in *)sa;
3927153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				if (sin->sin_addr.s_addr) {
3928153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					error = EINVAL;
3929153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_TCB_UNLOCK(stcb);
3930153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3931153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					break;
3932153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				}
3933153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else
3934153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#endif
3935153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#ifdef INET6
3936153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (sa->sa_family == AF_INET6) {
3937153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				struct sockaddr_in6 *sin6;
3938153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
3939153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				sin6 = (struct sockaddr_in6 *)sa;
3940153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3941153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					error = EINVAL;
3942153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_TCB_UNLOCK(stcb);
3943153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3944153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					break;
3945153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				}
3946153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else
3947153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#endif
394875cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
394975cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
395075cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
395175cd23222c96d5ebe5a9082c57a263f917f1462btuexen
395275cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
395375cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
395475cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
395575cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
395675cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
395775cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
395875cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
395975cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
396075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
3961153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			{
3962153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				error = EAFNOSUPPORT;
3963153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_TCB_UNLOCK(stcb);
3964153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3965153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				break;
3966153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
3967153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
3968153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
3969153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (stcb) {
3970153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (net) {
3971153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				encaps->sue_port = net->port;
3972153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else {
3973153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				encaps->sue_port = stcb->asoc.port;
3974153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
3975153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			SCTP_TCB_UNLOCK(stcb);
3976153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		} else {
3977153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3978153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3979153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
3980153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_RLOCK(inp);
3981153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				encaps->sue_port = inp->sctp_ep.port;
3982153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_RUNLOCK(inp);
3983153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else {
3984153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3985153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				error = EINVAL;
3986153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
3987153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
3988153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (error == 0) {
3989443f94da739e8e8968e5eb93c2f82f73287cfd5dt			*optsize = sizeof(struct sctp_udpencaps);
3990153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
3991153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		break;
3992153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	}
39932d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen	case SCTP_ENABLE_STREAM_RESET:
39942d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen	{
39952d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		struct sctp_assoc_value *av;
39962d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen
39972d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
39982d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
39992d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen
40002d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		if (stcb) {
40012d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			av->assoc_value = (uint32_t)stcb->asoc.local_strreset_support;
40022d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			SCTP_TCB_UNLOCK(stcb);
40032d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		} else {
40042d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
40052d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
40062d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
40072d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				SCTP_INP_RLOCK(inp);
40082d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				av->assoc_value = (uint32_t)inp->local_strreset_support;
40092d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				SCTP_INP_RUNLOCK(inp);
40102d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			} else {
40112d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
40122d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				error = EINVAL;
40132d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			}
40142d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		}
40152d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		if (error == 0) {
40162d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			*optsize = sizeof(struct sctp_assoc_value);
40172d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		}
40182d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen		break;
40192d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen	}
40208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
40218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
40228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = ENOPROTOOPT;
40238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
40248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end switch (sopt->sopt_name) */
40258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error) {
40268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*optsize = 0;
40278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
40298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
40308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
40318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Panda__) || defined(__Userspace__)
40328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
40338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
40348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
40358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
40368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
40378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    void *p)
40388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
40398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error, set_opt;
40408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t *mopt;
40418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb = NULL;
4042b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	struct sctp_inpcb *inp = NULL;
40438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
40448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
40458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (optval == NULL) {
40468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("optval is NULL\n");
40478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
40488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EINVAL);
40498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
40512fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
40528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("inp is NULL?\n");
40538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4054b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
40558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf_id = inp->def_vrf_id;
40578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
40588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = 0;
40598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (optname) {
40608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NODELAY:
40618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTOCLOSE:
40628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTO_ASCONF:
40638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EXPLICIT_EOR:
40648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DISABLE_FRAGMENTS:
40658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_USE_EXT_RCVINFO:
40668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_I_WANT_MAPPED_V4_ADDR:
40678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* copy in the option value */
40688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
40698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		set_opt = 0;
40708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error)
40718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
40728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (optname) {
40738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_DISABLE_FRAGMENTS:
40748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
40758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
40768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTO_ASCONF:
40778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
40788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * NOTE: we don't really support this flag
40798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
40808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
40818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* only valid for bound all sockets */
40828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
40838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (*mopt != 0)) {
40848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* forbidden by admin */
40858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
40868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (EPERM);
40878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
40888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
40898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
40908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
40918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EINVAL);
40928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
40938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
40948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_EXPLICIT_EOR:
40958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
40968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
40978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_USE_EXT_RCVINFO:
40988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
40998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
41008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_I_WANT_MAPPED_V4_ADDR:
41018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
41028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
41038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
41048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
41058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EINVAL);
41068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
41078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
41088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_NODELAY:
41098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			set_opt = SCTP_PCB_FLAGS_NODELAY;
41108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
41118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTOCLOSE:
41128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
41138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
41148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
41158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EINVAL);
41168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
41178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
41188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
41198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * The value is in ticks. Note this does not effect
41208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * old associations, only new ones.
41218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
41228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
41238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
41248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
41268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*mopt != 0) {
41278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, set_opt);
41288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
41298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, set_opt);
41308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
41328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
41338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_REUSE_PORT:
41348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
41358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
41368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND)  == 0) {
41378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't set it after we are bound */
41388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
41398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
41408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
41428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't do this for a 1-m socket */
41438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
41448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
41458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (optval)
41478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
41488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
41498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
41508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
41518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PARTIAL_DELIVERY_POINT:
41538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
41548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *value;
41558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
41578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*value > SCTP_SB_LIMIT_RCV(so)) {
41588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
41598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
41608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
41618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->partial_delivery_point = *value;
41638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
41648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_FRAGMENT_INTERLEAVE:
41668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* not yet until we re-write sctp_recvmsg() */
41678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
41688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *level;
41698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
41718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*level == SCTP_FRAG_LEVEL_2) {
41728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
41738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
41748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (*level == SCTP_FRAG_LEVEL_1) {
41758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
41768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
41778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (*level == SCTP_FRAG_LEVEL_0) {
41788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
41798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
41808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
41828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
41838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
41848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
41868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CMT_ON_OFF:
41888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
41898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_assoc_value *av;
41908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
41928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (av->assoc_value > SCTP_CMT_MAX) {
41938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
41948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
41958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
4196000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			}
41978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FIND_STCB(inp, stcb, av->assoc_id);
41988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
41998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.sctp_cmt_on_off = av->assoc_value;
42008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
42018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
42028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
42038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
42048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
42058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (av->assoc_id == SCTP_ALL_ASSOC)) {
42068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_WLOCK(inp);
42078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_cmt_on_off = av->assoc_value;
42088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_WUNLOCK(inp);
42098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
42108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
42118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (av->assoc_id == SCTP_ALL_ASSOC)) {
42128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RLOCK(inp);
42138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
42148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_TCB_LOCK(stcb);
42158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.sctp_cmt_on_off = av->assoc_value;
42168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_TCB_UNLOCK(stcb);
42178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
42188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RUNLOCK(inp);
42198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
42208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
42218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
42228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
42238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOPROTOOPT;
42248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
42268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PLUGGABLE_CC:
42278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
42288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
42298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
42308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
42318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
42328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((av->assoc_value != SCTP_CC_RFC2581) &&
42338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_CC_HSTCP) &&
42348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_CC_HTCP) &&
42358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_CC_RTCC)) {
42368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
42378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
42388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
42398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
42418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
42428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
42438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.congestion_control_module = av->assoc_value;
42448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
42458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
42468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
42478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
42488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
42498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
42508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
42518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
42528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
42538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
42548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
42558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
42568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
42578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
42588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
42598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
42608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
42618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
42628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
42638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
42648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
42658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.congestion_control_module = av->assoc_value;
42668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
42678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
42688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
42698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
42708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
42718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
42728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
42738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
42748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
42758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
42778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
42788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CC_OPTION:
42798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
42808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_cc_option *cc_opt;
42818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
42828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
42838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
42848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
42858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
42868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
42878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
42888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
42898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
42908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						(*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1, cc_opt);
42918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
42928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
42938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
42948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
42958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
42968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
42978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
42988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
42998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
43008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = ENOTSUP;
43018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
4302000a5bac556b28e74e4e98c540f66b1743e9312dtuexen				error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1,
43038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   cc_opt);
43048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
43058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
43068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
43088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
43098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PLUGGABLE_SS:
43108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
43118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
43128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
43148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((av->assoc_value != SCTP_SS_DEFAULT) &&
43158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
43168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
43178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_SS_PRIORITY) &&
43188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
43198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (av->assoc_value != SCTP_SS_FIRST_COME)) {
43208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
43218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
43228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
43238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
43258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
43268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
43278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
43288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.stream_scheduling_module = av->assoc_value;
43298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
43308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
43318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
43328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
43338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
43348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
43358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
43368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
43378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
43388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
43398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
43408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
43418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
43428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
43438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
43448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
43458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
43468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
43478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.stream_scheduling_module = av->assoc_value;
43488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
43498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
43508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
43518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
43528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
43538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
43558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
43568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SS_VALUE:
43578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
43588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_stream_value *av;
43598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
43618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
43628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
43638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
43648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                                              av->stream_value) < 0) {
43658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
43668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
43678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
43688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
43698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
43708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (av->assoc_id == SCTP_CURRENT_ASSOC) {
43718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
43728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
43738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
43748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
43758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                                          &stcb->asoc,
43768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                                          &stcb->asoc.strmout[av->stream_id],
43778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                                          av->stream_value);
43788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
43798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
43808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
4381000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
43828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
43838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Can't set stream value without association */
43848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
43858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
43868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
43878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
43898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
43908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CLR_STAT_LOG:
43918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
43928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EOPNOTSUPP;
43938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
43948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CONTEXT:
43958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
43968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
43978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
43998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
44008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
44028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.context = av->assoc_value;
44038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
44048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
44058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
44068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
44078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
44088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
44098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
44108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_context = av->assoc_value;
44118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
44128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
44138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
44148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
44158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
44168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
44178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
44188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.context = av->assoc_value;
44198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
44208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
44218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
44228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
44238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
44258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_VRF_ID:
44278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
44288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *default_vrfid;
44298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
44308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int i;
44318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
44328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
44338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*default_vrfid > SCTP_MAX_VRF_ID) {
44348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
44358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
44368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
44378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
44398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < inp->num_vrfs; i++) {
44408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* The VRF must be in the VRF list */
44418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (*default_vrfid == inp->m_vrf_ids[i]) {
44428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
44438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 				inp->def_vrf_id = *default_vrfid;
44448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
44458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto sctp_done;
44468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
44478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
44498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
44508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
44518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->def_vrf_id = *default_vrfid;
44528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
44538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
44548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_done:
44558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
44568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
44578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEL_VRF_ID:
44598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
44608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
44618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *del_vrfid;
44628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int i, fnd = 0;
44638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(del_vrfid, optval, uint32_t, optsize);
44658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*del_vrfid > SCTP_MAX_VRF_ID) {
44668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
44678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
44688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
44698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->num_vrfs == 1) {
44718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't delete last one */
44728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
44738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
44748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
44758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
44778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't add more once you are bound */
44788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
44798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
44808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
44818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
44838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < inp->num_vrfs; i++) {
44848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (*del_vrfid == inp->m_vrf_ids[i]) {
44858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				fnd = 1;
44868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
44878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
44888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!fnd) {
44908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
44918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
44928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
44938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (i != (inp->num_vrfs - 1)) {
44958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Take bottom one and move to this slot */
44968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->m_vrf_ids[i] = inp->m_vrf_ids[(inp->num_vrfs-1)];
44978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*del_vrfid == inp->def_vrf_id) {
44998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Take the first one as the new default */
45008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->def_vrf_id = inp->m_vrf_ids[0];
45018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Drop the number by one killing last one */
45038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->num_vrfs--;
45048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
45058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
45068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EOPNOTSUPP;
45078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
45098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ADD_VRF_ID:
45118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
45128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
45138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *add_vrfid;
45148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int i;
45158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
45168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(add_vrfid, optval, uint32_t, optsize);
45178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*add_vrfid > SCTP_MAX_VRF_ID) {
45188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
45198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
45208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
45218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
45238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't add more once you are bound */
45248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
45258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
45268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
45278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
45298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Verify its not already here */
45308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < inp->num_vrfs; i++) {
45318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (*add_vrfid == inp->m_vrf_ids[i]) {
45328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
45338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EALREADY;
45348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
45358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
45368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->num_vrfs + 1) > inp->vrf_size) {
45398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* need to grow array */
45408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint32_t *tarray;
45418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_MALLOC(tarray, uint32_t *,
45428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (sizeof(uint32_t) * (inp->vrf_size + SCTP_DEFAULT_VRF_SIZE)),
45438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_M_MVRF);
45448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tarray == NULL) {
45458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
45468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = ENOMEM;
45478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
45488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
45498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(tarray, inp->m_vrf_ids, (sizeof(uint32_t) * inp->vrf_size));
45518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF);
45528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->m_vrf_ids = tarray;
45538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->vrf_size += SCTP_DEFAULT_VRF_SIZE;
45548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->m_vrf_ids[inp->num_vrfs] = *add_vrfid;
45568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->num_vrfs++;
45578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
45588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
45598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
45608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EOPNOTSUPP;
45618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 	break;
45638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DELAYED_SACK:
45658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
45668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sack_info *sack;
45678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
45688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
45698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
45708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sack->sack_delay) {
45718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
45728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sack->sack_delay = SCTP_MAX_SACK_DELAY;
45738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
45748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sack->sack_delay = TICKS_TO_MSEC(1);
45758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
45778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
45788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sack->sack_delay) {
45798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.delayed_ack = sack->sack_delay;
45808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sack->sack_freq) {
45828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.sack_freq = sack->sack_freq;
45838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
45858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
45868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
45878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
45888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
45898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
45908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
45918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sack->sack_delay) {
45928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
45938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
45948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sack->sack_freq) {
45958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
45968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
45978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
45988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
45998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
46008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
46018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
46028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
46038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
46048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sack->sack_delay) {
46058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.delayed_ack = sack->sack_delay;
46068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
46078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sack->sack_freq) {
46088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.sack_freq = sack->sack_freq;
46098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
46108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
46118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
46138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
46168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_CHUNK:
46188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
46198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authchunk *sauth;
46208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
46228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
46248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
46258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
46268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
46278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
46298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
46308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_KEY:
46328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
46338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authkey *sca;
46348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_keyhead *shared_keys;
46358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_sharedkey_t *shared_key;
46368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_key_t *key = NULL;
46378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		size_t size;
46388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
46408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sca->sca_keylength == 0) {
46418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			size = optsize - sizeof(struct sctp_authkey);
46428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
46438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
46448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				size = sca->sca_keylength;
46458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
46468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
46478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
46488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
46498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
46528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
46548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			shared_keys = &stcb->asoc.shared_keys;
46558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* clear the cached keys for this key id */
46568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
46578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
46588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * create the new shared key and
46598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * insert/replace it
46608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
46618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (size > 0) {
46628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				key = sctp_set_key(sca->sca_key, (uint32_t) size);
46638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (key == NULL) {
46648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
46658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = ENOMEM;
46668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
46678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
46688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			shared_key = sctp_alloc_sharedkey();
46718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (shared_key == NULL) {
46728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_key(key);
46738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
46748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = ENOMEM;
46758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
46768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
46778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			shared_key->key = key;
46798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			shared_key->keyid = sca->sca_keynumber;
46808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = sctp_insert_sharedkey(shared_keys, shared_key);
46818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
46828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
46838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
46848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
46858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
46868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
46878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
46888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				shared_keys = &inp->sctp_ep.shared_keys;
46898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
46908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * clear the cached keys on all assocs for
46918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * this key id
46928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
46938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
46948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
46958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * create the new shared key and
46968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * insert/replace it
46978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
46988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (size > 0) {
46998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					key = sctp_set_key(sca->sca_key, (uint32_t) size);
47008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (key == NULL) {
47018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
47028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						error = ENOMEM;
47038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_INP_WUNLOCK(inp);
47048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
47058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
47068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
47078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				shared_key = sctp_alloc_sharedkey();
47088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (shared_key == NULL) {
47098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_free_key(key);
47108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
47118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = ENOMEM;
47128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_WUNLOCK(inp);
47138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
47148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
47158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				shared_key->key = key;
47168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				shared_key->keyid = sca->sca_keynumber;
47178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = sctp_insert_sharedkey(shared_keys, shared_key);
47188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
47198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
47218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
47228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
47238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
47248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
47258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					shared_keys = &stcb->asoc.shared_keys;
47268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* clear the cached keys for this key id */
47278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
47288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
47298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * create the new shared key and
47308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * insert/replace it
47318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
47328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (size > 0) {
47338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						key = sctp_set_key(sca->sca_key, (uint32_t) size);
47348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (key == NULL) {
47358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							SCTP_TCB_UNLOCK(stcb);
47368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
47378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
47388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
47398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					shared_key = sctp_alloc_sharedkey();
47408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (shared_key == NULL) {
47418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_free_key(key);
47428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_TCB_UNLOCK(stcb);
47438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
47448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
47458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					shared_key->key = key;
47468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					shared_key->keyid = sca->sca_keynumber;
47478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = sctp_insert_sharedkey(shared_keys, shared_key);
47488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
47498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
47508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
47518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
47548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
47558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_HMAC_IDENT:
47568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
47578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_hmacalgo *shmac;
47588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_hmaclist_t *hmaclist;
47598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint16_t hmacid;
47608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t i;
47618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
47628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
47638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
47648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
47668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
47678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4768000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
47698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
47708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hmaclist == NULL) {
47718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
47728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOMEM;
47738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
47748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < shmac->shmac_number_of_idents; i++) {
47768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hmacid = shmac->shmac_idents[i];
47778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
47788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* invalid HMACs were found */;
47798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
47818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_hmaclist(hmaclist);
47828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto sctp_set_hmac_done;
47838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < hmaclist->num_algo; i++) {
47868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
47878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* already in list */
478817fca683d16802e8836f92ca2d9761a4798ada4bt				break;
47898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
479117fca683d16802e8836f92ca2d9761a4798ada4bt		if (i == hmaclist->num_algo) {
479217fca683d16802e8836f92ca2d9761a4798ada4bt			/* not found in list */
47938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_hmaclist(hmaclist);
47948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
47958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
47968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
47978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* set it on the endpoint */
47998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
48008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_ep.local_hmacs)
48018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
48028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->sctp_ep.local_hmacs = hmaclist;
48038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
48048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_set_hmac_done:
48058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
48068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_ACTIVE_KEY:
48088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
48098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authkeyid *scact;
48108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
48128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
48138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* set the active key on the right place */
48158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
48168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* set the active key on the assoc */
48178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_auth_setactivekey(stcb,
48188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						   scact->scact_keynumber)) {
48198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
48208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    SCTP_FROM_SCTP_USRREQ,
48218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    EINVAL);
48228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
48238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
48258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
48268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
48278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
48288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
48298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
48308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
48318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
48328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
48338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
48348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
48358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
48368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
48388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
48398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
48408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
48418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
48428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_auth_setactivekey(stcb, scact->scact_keynumber);
48438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
48448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
48458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
48468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
48498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_DELETE_KEY:
48518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
48528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authkeyid *scdel;
48538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
48558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
48568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* delete the key from the right place */
48588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
48598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
48608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
48618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
48628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
48648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
48658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
48668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
48678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
48688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
48698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
48708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
48718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
48728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
48738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
48748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
48758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
48778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
48788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
48798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
48808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
48818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
48828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
48838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
48848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
48858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
48888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_AUTH_DEACTIVATE_KEY:
48908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
48918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_authkeyid *keyid;
48928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
48948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
48958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* deactivate the key from the right place */
48978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
48988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
48998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
49008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
49018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
49038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
49048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
49058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
49068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
49078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
49088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
49098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
49108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
49118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
49128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
49138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
49148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
49168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
49178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
49188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
49198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
49208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
49218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
49228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
49238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
49248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
49278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4928c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	case SCTP_ENABLE_STREAM_RESET:
4929c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	{
4930c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		struct sctp_assoc_value *av;
49312d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen
4932c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4933c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
4934c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4935c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EINVAL;
4936c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
4937c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
4938c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4939c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stcb) {
49402d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen			stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
4941c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_TCB_UNLOCK(stcb);
4942c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		} else {
4943c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4944c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4945c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4946c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
4947c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_INP_WLOCK(inp);
49482d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen				inp->local_strreset_support = (uint8_t)av->assoc_value;
4949c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_INP_WUNLOCK(inp);
4950c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			}
4951c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4952c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
4953c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_INP_RLOCK(inp);
4954c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4955c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen					SCTP_TCB_LOCK(stcb);
49562d0d9bb5933907b2ca1c951b8ab47ba48437e72btuexen					stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
4957c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen					SCTP_TCB_UNLOCK(stcb);
4958c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				}
4959c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_INP_RUNLOCK(inp);
4960c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			}
49618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4962c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
4963c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		break;
4964c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	}
49658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RESET_STREAMS:
49668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
4967000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		struct sctp_reset_streams *strrst;
49681de509107029a81699453f86fcced3c7b7fb534btuexen		int i, send_out = 0;
49691de509107029a81699453f86fcced3c7b7fb534btuexen		int send_in = 0;
49708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4971c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
4972c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
49738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
49748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
49758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT;
49768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
49778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.peer_supports_strreset == 0) {
49798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
4980c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			 * Peer does not support the chunk type.
49818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
4982c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4983c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EOPNOTSUPP;
4984c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_TCB_UNLOCK(stcb);
4985c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
4986c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
49878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.stream_reset_outstanding) {
49888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
49898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EALREADY;
49908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
49918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
49928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4993c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
49948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			send_in = 1;
4995c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
4996c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
49978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			send_out = 1;
4998c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
4999c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if ((send_in == 0) && (send_out == 0)) {
5000c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5001c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EINVAL;
5002c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_TCB_UNLOCK(stcb);
5003c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5004c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5005c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		for (i = 0; i < strrst->srs_number_streams; i++) {
5006c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if ((send_in) &&
5007c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
5008c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
50098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
5010c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				break;
50118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5012c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if ((send_out) &&
5013c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			    (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
5014c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5015c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				error = EINVAL;
5016c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				break;
50178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5018c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5019c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (error) {
5020c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_TCB_UNLOCK(stcb);
5021c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5022c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5023c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
5024c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen						strrst->srs_stream_list,
5025c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen						send_out, send_in, 0, 0, 0, 0, 0);
5026c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen
5027c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5028c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_TCB_UNLOCK(stcb);
5029c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		break;
5030c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	}
5031c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	case SCTP_ADD_STREAMS:
5032c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	{
5033c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		struct sctp_add_streams *stradd;
50341de509107029a81699453f86fcced3c7b7fb534btuexen		uint8_t addstream = 0;
50351de509107029a81699453f86fcced3c7b7fb534btuexen		uint16_t add_o_strmcnt = 0;
50361de509107029a81699453f86fcced3c7b7fb534btuexen		uint16_t add_i_strmcnt = 0;
5037c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen
5038c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
5039c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
5040c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stcb == NULL) {
5041c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5042c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = ENOENT;
5043c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5044c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
50451de509107029a81699453f86fcced3c7b7fb534btuexen		if (stcb->asoc.peer_supports_strreset == 0) {
50461de509107029a81699453f86fcced3c7b7fb534btuexen			/*
50471de509107029a81699453f86fcced3c7b7fb534btuexen			 * Peer does not support the chunk type.
50481de509107029a81699453f86fcced3c7b7fb534btuexen			 */
50491de509107029a81699453f86fcced3c7b7fb534btuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
50501de509107029a81699453f86fcced3c7b7fb534btuexen			error = EOPNOTSUPP;
50511de509107029a81699453f86fcced3c7b7fb534btuexen			SCTP_TCB_UNLOCK(stcb);
50521de509107029a81699453f86fcced3c7b7fb534btuexen			break;
50531de509107029a81699453f86fcced3c7b7fb534btuexen		}
50541de509107029a81699453f86fcced3c7b7fb534btuexen		if (stcb->asoc.stream_reset_outstanding) {
50551de509107029a81699453f86fcced3c7b7fb534btuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
50561de509107029a81699453f86fcced3c7b7fb534btuexen			error = EALREADY;
50571de509107029a81699453f86fcced3c7b7fb534btuexen			SCTP_TCB_UNLOCK(stcb);
50581de509107029a81699453f86fcced3c7b7fb534btuexen			break;
50591de509107029a81699453f86fcced3c7b7fb534btuexen		}
5060c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if ((stradd->sas_outstrms == 0) &&
5061c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		    (stradd->sas_instrms == 0)) {
5062c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EINVAL;
5063c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			goto skip_stuff;
5064c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5065c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stradd->sas_outstrms) {
50668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			addstream = 1;
50678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We allocate here */
5068c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			add_o_strmcnt = stradd->sas_outstrms;
5069c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
50708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* You can't have more than 64k */
50718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
50728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto skip_stuff;
50738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
50748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5075c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stradd->sas_instrms) {
5076c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			int cnt;
50778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5078c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			addstream |= 2;
5079c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			/* We allocate inside sctp_send_str_reset_req() */
5080c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			add_i_strmcnt = stradd->sas_instrms;
5081c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			cnt = add_i_strmcnt;
5082c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			cnt += stcb->asoc.streamincnt;
5083c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if (cnt > 0x0000ffff) {
5084c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				/* You can't have more than 64k */
50858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
5086c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				goto skip_stuff;
50878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5088c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			if (cnt > (int)stcb->asoc.max_inbound_streams) {
5089c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				/* More than you are allowed */
50908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
5091c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen				goto skip_stuff;
50928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
50938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5094c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
5095c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
50968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	skip_stuff:
5097c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_TCB_UNLOCK(stcb);
5098c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		break;
5099c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	}
5100c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	case SCTP_RESET_ASSOC:
5101c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	{
5102c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		uint32_t *value;
5103c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen
5104c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
5105c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
5106c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stcb == NULL) {
5107c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5108c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = ENOENT;
5109c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5110c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5111c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stcb->asoc.peer_supports_strreset == 0) {
5112c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			/*
5113c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			 * Peer does not support the chunk type.
5114c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			 */
5115c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5116c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EOPNOTSUPP;
51178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
51188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
51198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5120c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		if (stcb->asoc.stream_reset_outstanding) {
5121c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5122c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			error = EALREADY;
5123c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			SCTP_TCB_UNLOCK(stcb);
5124c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			break;
5125c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		}
5126c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
51278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
51288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
51298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
51308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CONNECT_X:
51328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
51338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
51348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
51358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
51368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
51388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
51398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CONNECT_X_DELAYED:
51408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
51418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
51428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
51438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
51448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
51468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
51478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CONNECT_X_COMPLETE:
51488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
51498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr *sa;
51508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
51518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* FIXME MT: check correct? */
51538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
51548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* find tcb */
51568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
51578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RLOCK(inp);
51588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = LIST_FIRST(&inp->sctp_asoc_list);
51598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
51608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_LOCK(stcb);
51618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net = sctp_findnet(stcb, sa);
51628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
51648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
51658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
51668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
51678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
51688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
51698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
51708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
51718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
51728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
51738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
51748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
51778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
51788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOENT;
51798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
51808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.delayed_connection == 1) {
51828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.delayed_connection = 0;
51838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
51848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
51858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.primary_destination,
51868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_FROM_SCTP_USRREQ+SCTP_LOC_9);
51878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
51888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
51898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
51908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * already expired or did not use delayed
51918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * connectx
51928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
51938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
51948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EALREADY;
51958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
51978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
51988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_MAX_BURST:
52008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
52018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 900000
52028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint8_t *burst;
52038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(burst, optval, uint8_t, optsize);
52058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
52078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->sctp_ep.max_burst = *burst;
52088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
52098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
52108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
52118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
52138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
52148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
52168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.max_burst = av->assoc_value;
52178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
52188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
52198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
52208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
52218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC) ||
52228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
52238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
52248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.max_burst = av->assoc_value;
52258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
52268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
52288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_ALL_ASSOC)) {
52298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
52308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
52318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
52328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.max_burst = av->assoc_value;
52338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
52348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
52358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
52368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
52398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
52408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
52418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_MAXSEG:
52428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
52438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assoc_value *av;
52448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int ovh;
52458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
52478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, av->assoc_id);
52488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
52508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ovh = SCTP_MED_OVERHEAD;
52518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
52528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ovh = SCTP_MED_V4_OVERHEAD;
52538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
52558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (av->assoc_value) {
52568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
52578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
52588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
52598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
52618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
52628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
52638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
52648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (av->assoc_id == SCTP_FUTURE_ASSOC)) {
52658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
52668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* FIXME MT: I think this is not in tune with the API ID */
52678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (av->assoc_value) {
52688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_frag_point = (av->assoc_value + ovh);
52698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
52708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
52718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
52728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
52738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
52748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
52758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
52768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
52798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
52808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EVENTS:
52818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
52828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_event_subscribe *events;
52838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
52858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
52878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_data_io_event) {
52888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
52898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
52908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
52918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_association_event) {
52948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
52958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
52968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
52978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
52998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_address_event) {
53008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
53018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
53028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
53038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_send_failure_event) {
53068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
53078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
53088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
53098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_peer_error_event) {
53128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
53138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
53148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
53158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_shutdown_event) {
53188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
53198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
53208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
53218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_partial_delivery_event) {
53248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
53258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
53268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
53278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_adaptation_layer_event) {
53308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
53318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
53328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
53338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_authentication_event) {
53368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
53378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
53388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
53398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_sender_dry_event) {
53428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
53438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
53448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
53458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_stream_reset_event) {
53488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
53498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
53508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
53518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
53538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
53558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
53568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(stcb);
53578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_association_event) {
53588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
53598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
53608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
53618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_address_event) {
53638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
53648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
53658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
53668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_send_failure_event) {
53688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
53698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
53708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
53718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_peer_error_event) {
53738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
53748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
53758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
53768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_shutdown_event) {
53788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
53798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
53808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
53818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_partial_delivery_event) {
53838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
53848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
53858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
53868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_adaptation_layer_event) {
53888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
53898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
53908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
53918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_authentication_event) {
53938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
53948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
53958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
53968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_sender_dry_event) {
53988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
53998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
54008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
54018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (events->sctp_stream_reset_event) {
54038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
54048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
54058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
54068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
54088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
54098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Send up the sender dry event only for 1-to-1 style sockets. */
54108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (events->sctp_sender_dry_event) {
54118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
54128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
54138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb = LIST_FIRST(&inp->sctp_asoc_list);
54148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (stcb) {
54158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
54168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
54178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
54188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (stcb->asoc.stream_queue_cnt == 0)) {
54198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
54208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
54218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
54228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
54238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
54258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
54268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
54278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
54288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ADAPTATION_LAYER:
54298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
54308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_setadaptation *adap_bits;
54318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
54338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
54348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
54359a8642036bc992ec39f872443a35f8c545cc28c4t		inp->sctp_ep.adaptation_layer_indicator_provided = 1;
54368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
54378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
54388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
54398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG
54408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SET_INITIAL_DBG_SEQ:
54418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
54428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t *vvv;
54438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
54458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
54468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->sctp_ep.initial_sequence_debug = *vvv;
54478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
54488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
54498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
54508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
54518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_SEND_PARAM:
54528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
54538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sndrcvinfo *s_info;
54548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
54568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
54578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
54598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
54608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
54618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
54628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
54638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
54648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
54668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
54678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
54688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
54698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
54708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
54718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
54728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
54738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
54748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
54768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
54778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
54788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
54798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
54808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
54818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
54828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
54838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
54848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
54858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
54868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
54888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
54898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
54908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEER_ADDR_PARAMS:
54918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
54928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paddrparams *paddrp;
54938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
54948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
54968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
54978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
54988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
54998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
55008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
55018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
55028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
55038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
55048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
55058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
55068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp,
55078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    (struct sockaddr *)&paddrp->spp_address,
55088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    &net, NULL, NULL);
55098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
55108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
55118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
55128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5513b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (stcb && (net == NULL)) {
55148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr *sa;
55158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sa = (struct sockaddr *)&paddrp->spp_address;
55178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
55188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET) {
55198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in *sin;
55218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin = (struct sockaddr_in *)sa;
55228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin->sin_addr.s_addr) {
55238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
55248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
55258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
55268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
55278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
55288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
55298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
55308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
55318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET6) {
55328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in6 *sin6;
55338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6 = (struct sockaddr_in6 *)sa;
55358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
55368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
55378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
55388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
55398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
55408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
55418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
55428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
554375cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
554475cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
554575cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
554675cd23222c96d5ebe5a9082c57a263f917f1462btuexen
554775cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
554875cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
554975cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
555075cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
555175cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
555275cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
555375cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
555475cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
555575cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
55568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			{
55578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EAFNOSUPPORT;
55588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
55598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
55608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
55618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
55628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* sanity checks */
55648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
55658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb)
55668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
55678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
55688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
55698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
55728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb)
55738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
55748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
55758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
55768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
55798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/************************TCB SPECIFIC SET ******************/
55808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
55818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do we change the timer for HB, we run
55828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * only one?
55838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
5584b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			int ovh = 0;
55858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
55878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				ovh = SCTP_MED_OVERHEAD;
55888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
55898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				ovh = SCTP_MED_V4_OVERHEAD;
55908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
55918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* network sets ? */
55938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net) {
55948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/************************NET SPECIFIC SET ******************/
55958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_DISABLE) {
55968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
55978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    !(net->dest_state & SCTP_ADDR_NOHB)) {
55988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
55998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
56008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
56018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state |= SCTP_ADDR_NOHB;
56028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
56038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_ENABLE) {
56048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (paddrp->spp_hbinterval) {
56058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->heart_beat_delay = paddrp->spp_hbinterval;
56068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
56078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->heart_beat_delay = 0;
56088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
56098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
56108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					                SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
56118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
56128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state &= ~SCTP_ADDR_NOHB;
56138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
56148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_DEMAND) {
56158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* on demand HB */
56168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5617a4ffbccf5bed12adde7673f02ca4b0ca3214262ctuexen					sctp_chunk_output(inp, stcb,  SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
56188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
56198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
56208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
56218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
56228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
56238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
56248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
56258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state |= SCTP_ADDR_NO_PMTUD;
5626b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t					net->mtu = paddrp->spp_pathmtu + ovh;
5627b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t					if (net->mtu < stcb->asoc.smallest_mtu) {
5628b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t						sctp_pathmtu_adjustment(stcb, net->mtu);
56298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
56308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
56318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
56328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
56338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
56348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
56358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
56368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
56378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_pathmaxrxt) {
56388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->dest_state & SCTP_ADDR_PF) {
56398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->error_count > paddrp->spp_pathmaxrxt) {
56408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state &= ~SCTP_ADDR_PF;
56418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
56428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
56438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
56448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (net->error_count > net->pf_threshold)) {
56458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state |= SCTP_ADDR_PF;
56468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
56478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
56488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
56498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
56508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
56518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->dest_state & SCTP_ADDR_REACHABLE) {
56528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->error_count > paddrp->spp_pathmaxrxt) {
56538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    		net->dest_state &= ~SCTP_ADDR_REACHABLE;
565447674b651417d493ff4e0318113fd7beeef119dbtuexen							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
56558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
56568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
56578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->error_count <= paddrp->spp_pathmaxrxt) {
56588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state |= SCTP_ADDR_REACHABLE;
565947674b651417d493ff4e0318113fd7beeef119dbtuexen							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
56608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
56618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
56628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->failure_threshold = paddrp->spp_pathmaxrxt;
56638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
56648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_DSCP) {
56658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dscp = paddrp->spp_dscp & 0xfc;
56668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->dscp |= 0x01;
56678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
56688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
56698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
56708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->ro._l_addr.sa.sa_family == AF_INET6) {
56718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
56728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->flowlabel |= 0x80000000;
56738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
56748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
56758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
56768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
56778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
56788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_pathmaxrxt) {
56798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
56808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
56818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->dest_state & SCTP_ADDR_PF) {
56828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (net->error_count > paddrp->spp_pathmaxrxt) {
56838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								net->dest_state &= ~SCTP_ADDR_PF;
56848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
56858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else {
56868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
56878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    (net->error_count > net->pf_threshold)) {
56888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								net->dest_state |= SCTP_ADDR_PF;
56898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
56908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
56918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
56928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
56938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
56948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->dest_state & SCTP_ADDR_REACHABLE) {
56958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (net->error_count > paddrp->spp_pathmaxrxt) {
56968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    		net->dest_state &= ~SCTP_ADDR_REACHABLE;
569747674b651417d493ff4e0318113fd7beeef119dbtuexen								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
56988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
56998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else {
57008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (net->error_count <= paddrp->spp_pathmaxrxt) {
57018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								net->dest_state |= SCTP_ADDR_REACHABLE;
570247674b651417d493ff4e0318113fd7beeef119dbtuexen								sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
57038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
57048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
57058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->failure_threshold = paddrp->spp_pathmaxrxt;
57068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
57078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
57088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
57098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_ENABLE) {
57108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (paddrp->spp_hbinterval) {
57118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
57128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
57138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.heart_beat_delay = 0;
57148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
57158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Turn back on the timer */
57168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
57178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (paddrp->spp_hbinterval) {
57188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->heart_beat_delay = paddrp->spp_hbinterval;
57198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
57208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->heart_beat_delay = 0;
57218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
57228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->dest_state & SCTP_ADDR_NOHB) {
57238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state &= ~SCTP_ADDR_NOHB;
57248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
57258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
57268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
57278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
57288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
57298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
57308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
57318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_DISABLE) {
57328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
57338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (!(net->dest_state & SCTP_ADDR_NOHB)) {
57348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state |= SCTP_ADDR_NOHB;
57358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
57368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
57378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
57388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
57398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
57408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
57418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
57428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
57438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
57448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
57458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
57468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									SCTP_FROM_SCTP_USRREQ+SCTP_LOC_10);
57478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
57488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dest_state |= SCTP_ADDR_NO_PMTUD;
5749b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t						net->mtu = paddrp->spp_pathmtu + ovh;
5750b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t						if (net->mtu < stcb->asoc.smallest_mtu) {
5751b0ecb3b4b8b93d682b7175db3ac8711eb74e8502t							sctp_pathmtu_adjustment(stcb, net->mtu);
57528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
57538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
57548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
57558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
57568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
57578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
57588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
57598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
57608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
57618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
57628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
57638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
57648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
57658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_DSCP) {
57668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
57678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dscp = paddrp->spp_dscp & 0xfc;
57688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dscp |= 0x01;
57698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
57708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
57718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.default_dscp |= 0x01;
57728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
57738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
57748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
57758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
57768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->ro._l_addr.sa.sa_family == AF_INET6) {
57778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
57788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->flowlabel |= 0x80000000;
57798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
57808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
57818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
57828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.default_flowlabel |= 0x80000000;
57838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
57848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
57868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
57878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
57888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/************************NO TCB, SET TO default stuff ******************/
57898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
57908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
57918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
57928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
57938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
57948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * For the TOS/FLOWLABEL stuff you set it
57958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * with the options on the socket
57968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
57978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_pathmaxrxt) {
57988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
57998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
58028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
58038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else if (paddrp->spp_hbinterval) {
58048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
58058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						paddrp->spp_hbinterval= SCTP_MAX_HB_INTERVAL;
58068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
58078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_HB_ENABLE) {
58108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
58118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
58128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else if (paddrp->spp_hbinterval) {
58138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
58148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
58158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
58168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
58178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
58188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
58208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
58218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
58228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
58238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_DSCP) {
58258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
58268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.default_dscp |= 0x01;
58278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
58298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
58308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
58318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
58328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						inp->sctp_ep.default_flowlabel |= 0x80000000;
58338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
58348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
58368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
58378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
58388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
58398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
58408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
58418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
58428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
58438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
58448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RTOINFO:
58458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
58468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_rtoinfo *srto;
58478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t new_init, new_min, new_max;
58488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
58508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
58518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
58538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (srto->srto_initial)
58548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_init = srto->srto_initial;
58558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
58568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_init = stcb->asoc.initial_rto;
58578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (srto->srto_max)
58588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_max = srto->srto_max;
58598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
58608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_max = stcb->asoc.maxrto;
58618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (srto->srto_min)
58628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_min = srto->srto_min;
58638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
58648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				new_min = stcb->asoc.minrto;
58658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((new_min <= new_init) && (new_init <= new_max)) {
58668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.initial_rto = new_init;
58678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.maxrto = new_max;
58688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.minrto = new_min;
58698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
58708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
58718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
58728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
58738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
58748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
58758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
58768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
58778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
58788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
58798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (srto->srto_initial)
58808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_init = srto->srto_initial;
58818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
58828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_init = inp->sctp_ep.initial_rto;
58838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (srto->srto_max)
58848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_max = srto->srto_max;
58858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
58868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_max = inp->sctp_ep.sctp_maxrto;
58878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (srto->srto_min)
58888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_min = srto->srto_min;
58898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
58908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					new_min = inp->sctp_ep.sctp_minrto;
58918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((new_min <= new_init) && (new_init <= new_max)) {
58928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.initial_rto = new_init;
58938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_maxrto = new_max;
58948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.sctp_minrto = new_min;
58958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
58968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
58978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
58988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
59008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
59018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
59028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
5903000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			}
59048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
59058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
59068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
59078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ASSOCINFO:
59088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
59098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_assocparams *sasoc;
59108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
59118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
59128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
59138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sasoc->sasoc_cookie_life) {
59148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* boundary check the cookie life */
59158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sasoc->sasoc_cookie_life < 1000)
59168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_cookie_life = 1000;
59178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
59188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
59198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
59208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
59218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
59228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sasoc->sasoc_asocmaxrxt)
59238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
59248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sasoc->sasoc_cookie_life) {
59258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
59268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
59278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
59288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
59298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
59308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
59318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
59328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
59338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sasoc->sasoc_asocmaxrxt)
59348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
59358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sasoc->sasoc_cookie_life) {
59368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
59378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
59388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
59398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
59408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
59418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
5942000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			}
59438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
59448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
59458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
59468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_INITMSG:
59478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
59488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_initmsg *sinit;
59498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
59508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
59518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
59528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sinit->sinit_num_ostreams)
59538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
59548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
59558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sinit->sinit_max_instreams)
59568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
59578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
59588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sinit->sinit_max_attempts)
59598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
59608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
59618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sinit->sinit_max_init_timeo)
59628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
59638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
59648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
59658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
59668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PRIMARY_ADDR:
59678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
59688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_setprim *spa;
59698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
59708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
59718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
59728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
59738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
59748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
59758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
59768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
59778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
59788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
59798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
59808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
59818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
59828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
59838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp,
59848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    (struct sockaddr *)&spa->ssp_addr,
59858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    &net, NULL, NULL);
59868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
59878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
59888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
59898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
59908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
59918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb) && (net)) {
59928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((net != stcb->asoc.primary_destination) &&
59938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
59948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Ok we need to set it */
59958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5996000a5bac556b28e74e4e98c540f66b1743e9312dtuexen					if ((stcb->asoc.alternate) &&
59978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (!(net->dest_state & SCTP_ADDR_PF)) &&
59988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (net->dest_state & SCTP_ADDR_REACHABLE)) {
59998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_free_remote_addr(stcb->asoc.alternate);
60008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.alternate = NULL;
60018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
60028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
60048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
60058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
60068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
60078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
60088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
60098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
60108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
60118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
60128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
60138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SET_DYNAMIC_PRIMARY:
60148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
60158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		union sctp_sockstore *ss;
60168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
6017b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		int i, fnd = 0;
60188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
60198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__Windows__) && !defined(__Userspace__)
60208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
60218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct proc *proc;
60228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
60238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__
60248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version > 602000
60258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = priv_check(curthread,
60268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				   PRIV_NETINET_RESERVEDPORT);
60278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif __FreeBSD_version >= 500000
60288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = suser((struct thread *)p);
60298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
60308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = suser(p);
60318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
60328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__APPLE__)
60338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		proc = (struct proc *)p;
60348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (p) {
60358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = suser(proc->p_ucred, &proc->p_acflag);
60368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
60378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
60388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
60398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
60408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = suser(p, 0);
60418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
60428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
60438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error)
60448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
60458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
60468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
60478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* SUPER USER CHECK? */
60488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
60498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < inp->num_vrfs; i++) {
60508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (vrf_id == inp->m_vrf_ids[i]) {
60518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				fnd = 1;
60528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
60538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
60548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
60558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!fnd) {
60568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
60578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
60588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
60598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
60608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
60618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
60628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
60638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
60648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SET_PEER_PRIMARY_ADDR:
60658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
60668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_setpeerprim *sspp;
60678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
60688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
60698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
60708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb != NULL) {
60718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_ifa *ifa;
60728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
60738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
60748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (ifa == NULL) {
60758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
60768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
60778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto out_of_it;
60788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
60798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
60808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Must validate the ifa found is in our ep */
60818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_laddr *laddr;
6082b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				int found = 0;
60838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
60848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (laddr->ifa == NULL) {
60858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
60868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							__FUNCTION__);
60878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
60888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
60898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (laddr->ifa == ifa) {
60908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						found = 1;
60918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						break;
60928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
60938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!found) {
60958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
60968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
60978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto out_of_it;
60988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_set_primary_ip_address_sa(stcb,
61018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							   (struct sockaddr *)&sspp->sspp_addr) != 0) {
61028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
61038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
61048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		out_of_it:
61068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
61078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
61088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
61098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
61108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
61118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
61128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
61138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_BINDX_ADD_ADDR:
61148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
61158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_getaddresses *addrs;
61168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
61178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct thread *td;
61188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
61198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		td = (struct thread *)p;
61208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
61218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
61228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    optsize);
61238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
61248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addrs->addr->sa_family == AF_INET) {
6125c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
61268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
61278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
61288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
61298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
61318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
61328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
61338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
61348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
61368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else
61378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
61388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
61398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addrs->addr->sa_family == AF_INET6) {
6140c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
61418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
61428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
61438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
61448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
61468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
61478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen											   (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
61488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
61498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  break;
61508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
61528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else
61538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
61548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
61558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       error = EAFNOSUPPORT;
61568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  		       break;
61578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
61588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_bindx_add_address(so, inp, addrs->addr,
61598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       addrs->sget_assoc_id, vrf_id,
61608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       &error, p);
61618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
61628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
61638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_BINDX_REM_ADDR:
61648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
61658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_getaddresses *addrs;
61668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
61678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct thread *td;
61688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		td = (struct thread *)p;
61698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
61708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
61718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
61728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
61738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addrs->addr->sa_family == AF_INET) {
6174c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
61758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
61768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
61778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
61788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
61808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
61818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
61828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
61838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
61858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else
61868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
61878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
61888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addrs->addr->sa_family == AF_INET6) {
6189c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen			if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
61908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
61918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
61928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
61938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
61958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (td != NULL &&
61968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (error = prison_local_ip6(td->td_ucred,
61978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                              &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
61988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                              (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
61998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
62008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
62018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
62028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else
62048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
62068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EAFNOSUPPORT;
62078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
62088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
62090ac02f34d6041cd0018437596a5a9a94685e6919tuexen		sctp_bindx_delete_address(inp, addrs->addr,
62108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  addrs->sget_assoc_id, vrf_id,
62118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  &error);
62128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
62138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
62148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __APPLE__
62158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_LISTEN_FIX:
62168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* only applies to one-to-many sockets */
62178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
62188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* make sure the ACCEPTCONN flag is OFF */
62198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			so->so_options &= ~SO_ACCEPTCONN;
62208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
62218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* otherwise, not allowed */
62228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
62238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
62248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
62258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
62268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* __APPLE__ */
62278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_EVENT:
62288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
62298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_event *event;
62308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t event_type;
62318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
62328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
62338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
62348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (event->se_type) {
62358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ASSOC_CHANGE:
62368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
6237000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
62388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_PEER_ADDR_CHANGE:
62398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
6240000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
62418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_REMOTE_ERROR:
62428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVPEERERR;
6243000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
62448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SEND_FAILED:
62458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
6246000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
62478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SHUTDOWN_EVENT:
62488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
6249000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
62508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ADAPTATION_INDICATION:
62518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
6252000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
62538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_PARTIAL_DELIVERY_EVENT:
62548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
6255000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
62568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_AUTHENTICATION_EVENT:
62578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_AUTHEVNT;
6258000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
62598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_STREAM_RESET_EVENT:
62608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
6261000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
62628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SENDER_DRY_EVENT:
62638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = SCTP_PCB_FLAGS_DRYEVNT;
6264000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
62658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_NOTIFICATIONS_STOPPED_EVENT:
62668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = 0;
62678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
62688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ENOTSUP;
62698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
6270298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen		case SCTP_ASSOC_RESET_EVENT:
6271298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
6272298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			break;
6273298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen		case SCTP_STREAM_CHANGE_EVENT:
6274298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
6275298df7f2536ca4836a5f1909e4ea2f32f5a3ffcftuexen			break;
62765741e159bdf238ef4b61085d6fbfea2947386238tuexen		case SCTP_SEND_FAILED_EVENT:
62775741e159bdf238ef4b61085d6fbfea2947386238tuexen			event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
62785741e159bdf238ef4b61085d6fbfea2947386238tuexen			break;
62798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
62808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			event_type = 0;
62818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
62828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
62838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
62848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
62858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (event_type > 0) {
62868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb) {
62878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (event->se_on) {
62888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_on(inp, stcb, event_type);
62898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
62908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
62918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
62928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (stcb->asoc.stream_queue_cnt == 0)) {
62938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
62948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
62958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
62968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
62978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_stcb_feature_off(inp, stcb, event_type);
62988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
62998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
63008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
63018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
63028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * We don't want to send up a storm of events,
63038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * so return an error for sender dry events
63048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
63058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
63068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
63078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
6308000a5bac556b28e74e4e98c540f66b1743e9312dtuexen				    ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
63098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
63108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
63118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = ENOTSUP;
63128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
63138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
63148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
63158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
63168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
63178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
63188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_WLOCK(inp);
63198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (event->se_on) {
63208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_feature_on(inp, event_type);
63218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
63228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_feature_off(inp, event_type);
63238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
63248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_WUNLOCK(inp);
63258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
63268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
63278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (event->se_assoc_id == SCTP_ALL_ASSOC)) {
63288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RLOCK(inp);
63298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
63308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_TCB_LOCK(stcb);
63318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (event->se_on) {
63328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_stcb_feature_on(inp, stcb, event_type);
63338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						} else {
63348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_stcb_feature_off(inp, stcb, event_type);
63358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
63368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_TCB_UNLOCK(stcb);
63378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
63388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RUNLOCK(inp);
63398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
63408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
63418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
63428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
63438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
63448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RECVRCVINFO:
63458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
63468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int *onoff;
63478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
63488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
63498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
63508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*onoff != 0) {
63518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
63528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
63538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
63548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
63558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
63568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
63578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
63588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_RECVNXTINFO:
63598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
63608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int *onoff;
63618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
63628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
63638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
63648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*onoff != 0) {
63658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
63668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
63678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
63688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
63698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
63708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
63718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
63728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_SNDINFO:
63738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
63748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_sndinfo *info;
63758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint16_t policy;
63768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
63778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
63788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
63798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
63808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
63818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (info->snd_sid < stcb->asoc.streamoutcnt) {
63828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_send.sinfo_stream = info->snd_sid;
63838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
63848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_send.sinfo_flags = info->snd_flags;
63858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_send.sinfo_flags |= policy;
63868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
63878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_send.sinfo_context = info->snd_context;
63888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
63898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
63908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
63918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
63928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
63938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
63948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
63958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
63968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
63978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
63988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
63998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_stream = info->snd_sid;
64008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
64018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_flags = info->snd_flags;
64028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_flags |= policy;
64038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_ppid = info->snd_ppid;
64048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_context = info->snd_context;
64058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
64068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
64088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
64098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
64108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
64118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
64128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (info->snd_sid < stcb->asoc.streamoutcnt) {
64138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.def_send.sinfo_stream = info->snd_sid;
64148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
64158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.def_send.sinfo_flags = info->snd_flags;
64168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.def_send.sinfo_flags |= policy;
64178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
64188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.def_send.sinfo_context = info->snd_context;
64198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
64208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
64218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
64228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
64238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
64258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
64268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
64278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEFAULT_PRINFO:
64288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
64298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_default_prinfo *info;
64308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
64318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
64328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
64338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
64348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
64358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
64368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EINVAL;
64378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
64388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
64398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
64408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.def_send.sinfo_flags &= 0xfff0;
64418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
64428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
64438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
64448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
64458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
64468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
64478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
64488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
64498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
64508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_flags &= 0xfff0;
64518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_flags |= info->pr_policy;
64528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->def_send.sinfo_timetolive = info->pr_value;
64538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
64548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
64568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
64578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RLOCK(inp);
64588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
64598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_LOCK(stcb);
64608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.def_send.sinfo_flags &= 0xfff0;
64618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
64628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
64638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
64648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
64658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_RUNLOCK(inp);
64668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
64688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
64698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
64708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_PEER_ADDR_THLDS:
64718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Applies to the specific association */
64728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
64738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_paddrthlds *thlds;
64748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
64758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
64768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
64778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
64788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net = NULL;
64798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
64808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_assoc_id);
64818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
64828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We increment here since sctp_findassociation_ep_addr() wil
64838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * do a decrement if it finds the stcb as long as the locked
64848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
64858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
64868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(inp);
64878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = sctp_findassociation_ep_addr(&inp,
64888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    (struct sockaddr *)&thlds->spt_assoc_id,
64898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							    &net, NULL, NULL);
64908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
64918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
64928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6494b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (stcb && (net == NULL)) {
64958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr *sa;
64968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
64978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sa = (struct sockaddr *)&thlds->spt_assoc_id;
64988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
64998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET) {
65008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
65018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in *sin;
65028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin = (struct sockaddr_in *)sa;
65038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin->sin_addr.s_addr) {
65048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
65058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
65068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
65078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
65088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
65098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
65108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
65118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
65128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET6) {
65138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in6 *sin6;
65148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
65158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6 = (struct sockaddr_in6 *)sa;
65168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
65178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
65188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_TCB_UNLOCK(stcb);
65198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = EINVAL;
65208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
65218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
65228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else
65238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
652475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
652575cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
652675cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
652775cd23222c96d5ebe5a9082c57a263f917f1462btuexen
652875cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
652975cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
653075cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
653175cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
653275cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
653375cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
653475cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
653575cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
653675cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
65378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			{
65388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EAFNOSUPPORT;
65398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
65408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
65418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
65428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
65438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
65458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net) {
65468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dest_state & SCTP_ADDR_PF) {
65478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
65488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (net->failure_threshold <= thlds->spt_pathpfthld)) {
65498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dest_state &= ~SCTP_ADDR_PF;
65508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
65518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
65528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((net->failure_threshold > thlds->spt_pathpfthld) &&
65538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
65548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    	net->dest_state |= SCTP_ADDR_PF;
65558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
65568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
65578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
65588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
65598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
65608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->dest_state & SCTP_ADDR_REACHABLE) {
65618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->failure_threshold > thlds->spt_pathmaxrxt) {
65628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dest_state &= ~SCTP_ADDR_REACHABLE;
656347674b651417d493ff4e0318113fd7beeef119dbtuexen						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
65648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
65658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
65668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
65678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->dest_state |= SCTP_ADDR_REACHABLE;
656847674b651417d493ff4e0318113fd7beeef119dbtuexen						sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
65698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
65708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
65718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->failure_threshold = thlds->spt_pathmaxrxt;
65728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->pf_threshold = thlds->spt_pathpfthld;
65738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
65748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
65758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->dest_state & SCTP_ADDR_PF) {
65768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
65778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (net->failure_threshold <= thlds->spt_pathpfthld)) {
65788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state &= ~SCTP_ADDR_PF;
65798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
65808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
65818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((net->failure_threshold > thlds->spt_pathpfthld) &&
65828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
65838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    	net->dest_state |= SCTP_ADDR_PF;
65848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
65858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
65868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
65878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
65888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
65898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (net->dest_state & SCTP_ADDR_REACHABLE) {
65908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->failure_threshold > thlds->spt_pathmaxrxt) {
65918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state &= ~SCTP_ADDR_REACHABLE;
659247674b651417d493ff4e0318113fd7beeef119dbtuexen							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
65938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
65948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
65958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
65968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							net->dest_state |= SCTP_ADDR_REACHABLE;
659747674b651417d493ff4e0318113fd7beeef119dbtuexen							sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
65988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
65998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
66008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->failure_threshold = thlds->spt_pathmaxrxt;
66018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->pf_threshold = thlds->spt_pathpfthld;
66028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
66038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
66048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
66058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
66068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
66078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
66088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
66098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
66108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WLOCK(inp);
66118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
66128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
66138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_WUNLOCK(inp);
66148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
66158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
66168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = EINVAL;
66178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
66188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
66198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
66208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6621153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	case SCTP_REMOTE_UDP_ENCAPS_PORT:
6622153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	{
6623153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		struct sctp_udpencaps *encaps;
6624153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		struct sctp_nets *net;
662581616c6a3e184f46276632dd15aa489cd06d94dftuexen
6626153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
6627153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
6628153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (stcb) {
6629153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
6630153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		} else {
6631153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			/* We increment here since sctp_findassociation_ep_addr() wil
6632153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 * do a decrement if it finds the stcb as long as the locked
6633153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 * tcb (last argument) is NOT a TCB.. aka NULL.
6634153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			 */
6635153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			net = NULL;
6636153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			SCTP_INP_INCR_REF(inp);
6637153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
6638153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (stcb == NULL) {
6639153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_DECR_REF(inp);
6640153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
6641153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
6642b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (stcb && (net == NULL)) {
6643153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			struct sockaddr *sa;
6644000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
6645153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			sa = (struct sockaddr *)&encaps->sue_address;
6646153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#ifdef INET
6647153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (sa->sa_family == AF_INET) {
6648153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
6649153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				struct sockaddr_in *sin;
6650153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				sin = (struct sockaddr_in *)sa;
6651153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				if (sin->sin_addr.s_addr) {
6652153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6653153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_TCB_UNLOCK(stcb);
6654153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					error = EINVAL;
6655153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					break;
6656153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				}
6657153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else
6658153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#endif
6659153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#ifdef INET6
6660153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (sa->sa_family == AF_INET6) {
6661153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				struct sockaddr_in6 *sin6;
6662153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
6663153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				sin6 = (struct sockaddr_in6 *)sa;
6664153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6665153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6666153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_TCB_UNLOCK(stcb);
6667153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					error = EINVAL;
6668153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					break;
6669153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				}
6670153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else
6671153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen#endif
667275cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
667375cd23222c96d5ebe5a9082c57a263f917f1462btuexen			if (sa->sa_family == AF_CONN) {
667475cd23222c96d5ebe5a9082c57a263f917f1462btuexen				struct sockaddr_conn *sconn;
667575cd23222c96d5ebe5a9082c57a263f917f1462btuexen
667675cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sconn = (struct sockaddr_conn *)sa;
667775cd23222c96d5ebe5a9082c57a263f917f1462btuexen				if (sconn->sconn_addr != NULL) {
667875cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
667975cd23222c96d5ebe5a9082c57a263f917f1462btuexen					SCTP_TCB_UNLOCK(stcb);
668075cd23222c96d5ebe5a9082c57a263f917f1462btuexen					error = EINVAL;
668175cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
668275cd23222c96d5ebe5a9082c57a263f917f1462btuexen				}
668375cd23222c96d5ebe5a9082c57a263f917f1462btuexen			} else
668475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
6685153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			{
6686153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					error = EAFNOSUPPORT;
6687153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_TCB_UNLOCK(stcb);
6688153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6689153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen					break;
6690153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				}
6691153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
6692153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen
6693153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		if (stcb) {
6694153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if (net) {
6695153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				net->port = encaps->sue_port;
6696153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else {
6697153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				stcb->asoc.port = encaps->sue_port;
6698153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
6699153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			SCTP_TCB_UNLOCK(stcb);
6700153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		} else {
6701153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6702153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6703153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			    (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
6704153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_WLOCK(inp);
6705153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				inp->sctp_ep.port = encaps->sue_port;
6706153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_INP_WUNLOCK(inp);
6707153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			} else {
6708153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6709153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen				error = EINVAL;
6710153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen			}
6711153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		}
6712153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen		break;
6713153408b8be3c05b43cd0703fa015f6b3d7f2404btuexen	}
67148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
67158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
67168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = ENOPROTOOPT;
67178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
67188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end switch (opt) */
67198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
67208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
67218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
67228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
67238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
67248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_ctloutput(struct socket *so, struct sockopt *sopt)
67258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
67268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	void *optval = NULL;
67278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	size_t optsize = 0;
67288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	void *p;
67298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error = 0;
67308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
67318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sopt->sopt_level != IPPROTO_SCTP) {
67328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* wrong proto level... send back up to IP */
67338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
67348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (INP_CHECK_SOCKAF(so, AF_INET6))
67358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ip6_ctloutput(so, sopt);
67368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* INET6 */
67370612043f643c9b26245564c05defca64d472060etuexen#if defined(INET) && defined(INET6)
67388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
67398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
67418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = ip_ctloutput(so, sopt);
67428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (error);
67448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	optsize = sopt->sopt_valsize;
67468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (optsize) {
67478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
67488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (optval == NULL) {
67498a29867a84996e7ee31a638ab89256ca7d2dc9b0tuexen			SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
67508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (ENOBUFS);
67518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
67528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sooptcopyin(sopt, optval, optsize, optsize);
67538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
67548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE(optval, SCTP_M_SOCKOPT);
67558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out;
67568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
67578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__Windows__)
67598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	p = (void *)sopt->sopt_td;
67608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
67618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	p = (void *)sopt->sopt_p;
67628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sopt->sopt_dir == SOPT_SET) {
67648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
67658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (sopt->sopt_dir == SOPT_GET) {
67668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
67678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
67688a29867a84996e7ee31a638ab89256ca7d2dc9b0tuexen		SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
67698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
67708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((error == 0) && (optval != NULL)) {
67728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sooptcopyout(sopt, optval, optsize);
67738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(optval, SCTP_M_SOCKOPT);
67748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (optval != NULL) {
67758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(optval, SCTP_M_SOCKOPT);
67768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenout:
67788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
67798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
67808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
67828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
67838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
67848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
67858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
67868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
67878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
67888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__)
67898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
67908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
67918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
67928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__) || defined(__Userspace__)
67938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
67948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connect(struct socket *so, struct sockaddr *addr)
67958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
67968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	void *p = NULL;
67978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__)
67988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
67998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
68008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
68018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
68028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
68038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connect(struct socket *so, struct mbuf *nam, struct proc *p)
68048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
68058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *addr = mtod(nam, struct sockaddr *);
68068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
6810b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int i, fnd = 0;
68118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error = 0;
68138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int create_lock_on = 0;
68148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
68158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
6816b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	struct sctp_tcb *stcb = NULL;
68178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
68192fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
68208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* I made the same as TCP since we are not setup? */
68218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
68228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ECONNRESET);
68238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (addr == NULL) {
68258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
68268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return EINVAL;
68278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
68308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        /* TODO __Userspace__ falls into this code for IPv6 stuff at the moment... */
68318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
683223273859c39742f09cc5ec7c9bf32ff225661e82tuexen#if !defined(__Windows__) && !defined(__Userspace_os_Linux) && !defined(__Userspace_os_Windows)
68338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (addr->sa_family) {
68348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
68358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
68368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
68378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
68388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6p;
68398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
68428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
68438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
68448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
68458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
68468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6p = (struct sockaddr_in6 *)addr;
68478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
68488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
68498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (error);
68508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
68518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
68538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
68568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
68578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
68588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
68598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sinp;
68608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68620612043f643c9b26245564c05defca64d472060etuexen#if !defined(__Userspace_os_Windows)
68638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr->sa_len != sizeof(struct sockaddr_in)) {
68648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
68658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
68668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
686781616c6a3e184f46276632dd15aa489cd06d94dftuexen#endif
68688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
68698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinp = (struct sockaddr_in *)addr;
68708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
68718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
68728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (error);
68738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
68748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
68768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
68798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
68808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen 		return (EAFNOSUPPORT);
68818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_INCR_REF(inp);
68848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_ASOC_CREATE_LOCK(inp);
68858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	create_lock_on = 1;
68868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
68898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
68908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Should I really unlock ? */
68918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
68928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	        error = EFAULT;
68938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
68948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
68968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
68978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (addr->sa_family == AF_INET6)) {
68988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
68998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
69008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
69018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69027988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
69037988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
69047988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) &&
69057988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	    (addr->sa_family != AF_CONN)) {
69067988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
69077988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		error = EINVAL;
69087988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		goto out_now;
69097988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	}
69107988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
69118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
69128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_PCB_FLAGS_UNBOUND) {
69138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Bind a ephemeral port */
69148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_inpcb_bind(so, NULL, NULL, p);
69158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
69168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_now;
69178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
69188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now do we connect? */
69208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
69218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
69228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
69238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
69248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
69258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
69278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
69288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We are already connected AND the TCP model */
69298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
69308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EADDRINUSE;
69318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
69328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
69348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
69358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = LIST_FIRST(&inp->sctp_asoc_list);
69368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
69378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
69388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We increment here since sctp_findassociation_ep_addr() will
69398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * do a decrement if it finds the stcb as long as the locked
69408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * tcb (last argument) is NOT a TCB.. aka NULL.
69418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
69428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_INCR_REF(inp);
69438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
69448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
69458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_DECR_REF(inp);
69468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
69478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
69488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
69498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb != NULL) {
69518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Already have or am bring up an association */
69528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
69538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EALREADY;
69548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
69558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf_id = inp->def_vrf_id;
69588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
69598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < inp->num_vrfs; i++) {
69608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (vrf_id == inp->m_vrf_ids[i]) {
69618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			fnd = 1;
69628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
69638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
69648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!fnd) {
69668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
69678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EINVAL;
69688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
69698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
69718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* We are GOOD to go */
69728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
69738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
69748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Gak! no memory */
69758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_now;
69768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
69788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
69798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Set the connected flag so we can queue data */
69808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		soisconnecting(so);
69818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
69838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
69848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* initialize authentication parameters for the assoc */
69868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_initialize_auth_params(inp, stcb);
69878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
69898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
69908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out_now:
69918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (create_lock_on) {
69928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_ASOC_CREATE_UNLOCK(inp);
69938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_DECR_REF(inp);
6996b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (error);
69978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
69988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
69998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70007a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#if defined(__Userspace__)
70017a9f1edd34bf82c194a2f9d0c64394f431175138tuexenint
70027a9f1edd34bf82c194a2f9d0c64394f431175138tuexensctpconn_connect(struct socket *so, struct sockaddr *addr)
70037a9f1edd34bf82c194a2f9d0c64394f431175138tuexen{
70047a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#ifdef SCTP_MVRF
70057a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	int i, fnd = 0;
70067a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
70077a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	void *p = NULL;
70087a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	int error = 0;
70097a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	int create_lock_on = 0;
70107a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	uint32_t vrf_id;
70117a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	struct sctp_inpcb *inp;
70127a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	struct sctp_tcb *stcb = NULL;
70137a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
70147a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	inp = (struct sctp_inpcb *)so->so_pcb;
70157a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (inp == NULL) {
70167a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* I made the same as TCP since we are not setup? */
70177a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
70187a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		return (ECONNRESET);
70197a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
70207a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (addr == NULL) {
70217a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
70227a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		return EINVAL;
70237a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
70247a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	switch (addr->sa_family) {
7025f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef INET
7026f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t	case AF_INET:
7027f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
7028f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t		if (addr->sa_len != sizeof(struct sockaddr_in)) {
70297a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
70307a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			return (EINVAL);
70317a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
7032f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#endif
70337a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		break;
70347a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
7035f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef INET6
7036f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t	case AF_INET6:
7037f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
7038f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
70397a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
70407a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			return (EINVAL);
70417a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
7042f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#endif
70437a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		break;
70447a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
70457a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	case AF_CONN:
7046f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
70477a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		if (addr->sa_len != sizeof(struct sockaddr_conn)) {
70487a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
70497a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			return (EINVAL);
70507a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
7051f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#endif
70527a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		break;
70537a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	default:
70547a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
70557a9f1edd34bf82c194a2f9d0c64394f431175138tuexen 		return (EAFNOSUPPORT);
70567a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
70577a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	SCTP_INP_INCR_REF(inp);
70587a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	SCTP_ASOC_CREATE_LOCK(inp);
70597a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	create_lock_on = 1;
70607a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
70617a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
70627a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
70637a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
70647a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* Should I really unlock ? */
70657a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
70667a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	        error = EFAULT;
70677a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
70687a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
70697a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#ifdef INET6
70707a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
70717a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	    (addr->sa_family == AF_INET6)) {
70727a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
70737a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = EINVAL;
70747a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
70757a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
70767a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
70777a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == SCTP_PCB_FLAGS_UNBOUND) {
70787a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* Bind a ephemeral port */
70797a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = sctp_inpcb_bind(so, NULL, NULL, p);
70807a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		if (error) {
70817a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			goto out_now;
70827a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
70837a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
70847a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	/* Now do we connect? */
70857a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
70867a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	    (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
70877a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
70887a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = EINVAL;
70897a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
70907a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
70917a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
70927a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
70937a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* We are already connected AND the TCP model */
70947a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
70957a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = EADDRINUSE;
70967a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
70977a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
70987a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
70997a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_INP_RLOCK(inp);
71007a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		stcb = LIST_FIRST(&inp->sctp_asoc_list);
71017a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_INP_RUNLOCK(inp);
71027a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	} else {
71037a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* We increment here since sctp_findassociation_ep_addr() will
71047a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		 * do a decrement if it finds the stcb as long as the locked
71057a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		 * tcb (last argument) is NOT a TCB.. aka NULL.
71067a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		 */
71077a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_INP_INCR_REF(inp);
71087a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
71097a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		if (stcb == NULL) {
71107a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			SCTP_INP_DECR_REF(inp);
71117a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		} else {
71127a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			SCTP_TCB_UNLOCK(stcb);
71137a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
71147a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
71157a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (stcb != NULL) {
71167a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* Already have or am bring up an association */
71177a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
71187a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = EALREADY;
71197a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
71207a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
71217a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
71227a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	vrf_id = inp->def_vrf_id;
71237a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#ifdef SCTP_MVRF
71247a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	for (i = 0; i < inp->num_vrfs; i++) {
71257a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		if (vrf_id == inp->m_vrf_ids[i]) {
71267a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			fnd = 1;
71277a9f1edd34bf82c194a2f9d0c64394f431175138tuexen			break;
71287a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		}
71297a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
71307a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (!fnd) {
71317a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
71327a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		error = EINVAL;
71337a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
71347a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
71357a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
71367a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	/* We are GOOD to go */
71377a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
71387a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (stcb == NULL) {
71397a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* Gak! no memory */
71407a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		goto out_now;
71417a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
71427a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
71437a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
71447a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		/* Set the connected flag so we can queue data */
71457a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		soisconnecting(so);
71467a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
71477a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
71487a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
71497a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
71507a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	/* initialize authentication parameters for the assoc */
71517a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	sctp_initialize_auth_params(inp, stcb);
71527a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
71537a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
71547a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	SCTP_TCB_UNLOCK(stcb);
71557a9f1edd34bf82c194a2f9d0c64394f431175138tuexen out_now:
71567a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	if (create_lock_on) {
71577a9f1edd34bf82c194a2f9d0c64394f431175138tuexen		SCTP_ASOC_CREATE_UNLOCK(inp);
71587a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	}
71597a9f1edd34bf82c194a2f9d0c64394f431175138tuexen
71607a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	SCTP_INP_DECR_REF(inp);
71617a9f1edd34bf82c194a2f9d0c64394f431175138tuexen	return (error);
71627a9f1edd34bf82c194a2f9d0c64394f431175138tuexen}
71637a9f1edd34bf82c194a2f9d0c64394f431175138tuexen#endif
71648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
71658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 500000
71668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version >= 700000
71678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_listen(struct socket *so, int backlog, struct thread *p)
71688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
71698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_listen(struct socket *so, struct thread *p)
71708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
71718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__)
71728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_listen(struct socket *so, int backlog, PKTHREAD p)
71738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Userspace__)
71748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_listen(struct socket *so, int backlog, struct proc *p)
71758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
71768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_listen(struct socket *so, struct proc *p)
71778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
71788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
71798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
71808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Note this module depends on the protocol processing being called
71818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * AFTER any socket level flags and backlog are applied to the
71828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * socket. The traditional way that the socket flags are applied is
71838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * AFTER protocol processing. We have made a change to the
71848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
71858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * place if the socket API for SCTP is to work properly.
71868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
71878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
71888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error = 0;
71898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
7190000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
71918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
71922fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
71938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* I made the same as TCP since we are not setup? */
71948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
71958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ECONNRESET);
71968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
71978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
71988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* See if we have a listener */
71998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_inpcb *tinp;
72008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		union sctp_sockstore store, *sp;
72018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
72028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sp = &store;
72038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
72048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* not bound all */
72058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_laddr *laddr;
72068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
72078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
72088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				memcpy(&store, &laddr->ifa->address, sizeof(store));
72098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				switch (sp->sa.sa_family) {
72108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
72118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET:
72128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sp->sin.sin_port = inp->sctp_lport;
72138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
72148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
72168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET6:
72178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sp->sin6.sin6_port = inp->sctp_lport;
72188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
72198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
722075cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
722175cd23222c96d5ebe5a9082c57a263f917f1462btuexen				case AF_CONN:
722275cd23222c96d5ebe5a9082c57a263f917f1462btuexen					sp->sconn.sconn_port = inp->sctp_lport;
722375cd23222c96d5ebe5a9082c57a263f917f1462btuexen					break;
722475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
72258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				default:
72268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
72278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
72288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
72298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (tinp && (tinp != inp) &&
72308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
72318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
72328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (tinp->sctp_socket->so_qlimit)) {
72338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* we have a listener already and its not this inp. */
72348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_DECR_REF(tinp);
72358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (EADDRINUSE);
72368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if (tinp) {
72378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_DECR_REF(tinp);
72388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
72398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
72408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
72418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Setup a local addr bound all */
72428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memset(&store, 0, sizeof(store));
72438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			switch (sp->sa.sa_family) {
72448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
72458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET:
72468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				store.sin.sin_port = inp->sctp_lport;
72478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
72488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
72508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET6:
72518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sp->sin6.sin6_port = inp->sctp_lport;
72528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
72538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
725475cd23222c96d5ebe5a9082c57a263f917f1462btuexen#if defined(__Userspace__)
725575cd23222c96d5ebe5a9082c57a263f917f1462btuexen			case AF_CONN:
725675cd23222c96d5ebe5a9082c57a263f917f1462btuexen				sp->sconn.sconn_port = inp->sctp_lport;
725775cd23222c96d5ebe5a9082c57a263f917f1462btuexen				break;
725875cd23222c96d5ebe5a9082c57a263f917f1462btuexen#endif
72598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			default:
72608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
72618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
72628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
72638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
72648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				store.sa.sa_family = AF_INET6;
7265f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
72668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				store.sa.sa_len = sizeof(struct sockaddr_in6);
72678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
72698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
72718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
72728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				store.sa.sa_family = AF_INET;
7273f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
72748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				store.sa.sa_len = sizeof(struct sockaddr_in);
72758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
72778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tinp = sctp_pcb_findep(&sp->sa, 0, 0, inp->def_vrf_id);
72798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tinp && (tinp != inp) &&
72808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
72818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
72828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (tinp->sctp_socket->so_qlimit)) {
72838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* we have a listener already and its not this inp. */
72848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(tinp);
72858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EADDRINUSE);
72868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else if (tinp) {
72878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
72888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
72898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
72908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
72918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
72928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_LOCK_LOGGING
72938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
72948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
72958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
72968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCK_LOCK(so);
72988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Userspace__)
72998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = solisten_proto_check(so);
73008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error) {
73018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_UNLOCK(so);
73028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
73038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (error);
73048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
73078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
73088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* The unlucky case
73098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * - We are in the tcp pool with this guy.
73108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * - Someone else is in the main inp slot.
73118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * - We must move this guy (the listener) to the main slot
73128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * - We must then move the guy that was listener to the TCP Pool.
73138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
73148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_swap_inpcb_for_listen(inp)) {
73158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto in_use;
73168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
73208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
73218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We are already connected AND the TCP model */
73228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	in_use:
73238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
73248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_UNLOCK(so);
73258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
73268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EADDRINUSE);
73278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(inp);
73298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
73308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We must do a bind. */
73318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_UNLOCK(so);
73328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
73338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* bind error, probably perm */
73348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (error);
73358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCK_LOCK(so);
7337000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	}
73388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) || defined(__Userspace__)
73398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
73408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* It appears for 7.0 and on, we must always call this. */
73418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	solisten_proto(so, backlog);
73428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
73438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
73448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		solisten_proto(so);
73458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
73498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* remove the ACCEPTCONN flag for one-to-many sockets */
7350907b9e7d7c75f02c3d1f6c70016127990e8fe648t#if defined(__Userspace__)
73516435cc0024abc9f2dabba9feb634081e246d342bt		so->so_options &= ~SCTP_SO_ACCEPTCONN;
7352907b9e7d7c75f02c3d1f6c70016127990e8fe648t#else
73538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_options &= ~SO_ACCEPTCONN;
7354907b9e7d7c75f02c3d1f6c70016127990e8fe648t#endif
73558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version >= 700000 || defined(__Windows__) || defined(__Userspace__)
73588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (backlog == 0) {
73598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* turning off listen */
7360907b9e7d7c75f02c3d1f6c70016127990e8fe648t#if defined(__Userspace__)
7361907b9e7d7c75f02c3d1f6c70016127990e8fe648t		so->so_options &= ~SCTP_SO_ACCEPTCONN;
7362907b9e7d7c75f02c3d1f6c70016127990e8fe648t#else
73638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so->so_options &= ~SO_ACCEPTCONN;
7364907b9e7d7c75f02c3d1f6c70016127990e8fe648t#endif
73658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCK_UNLOCK(so);
73688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
73698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
73708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int sctp_defered_wakeup_cnt = 0;
73728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
73748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
73758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_accept(struct socket *so, struct sockaddr **addr)
73768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
73778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
73788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_accept(struct socket *so, struct sockaddr *addr, int *namelen,
73798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    void *accept_info, int *accept_info_len)
73808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
73818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
73828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_accept(struct socket *so, struct mbuf *nam)
73838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
73848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *addr = mtod(nam, struct sockaddr *);
73858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb;
73878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
73888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	union sctp_sockstore store;
73898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
73908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
73918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error;
73928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_KAME */
73938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
73958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73962fbec84cda9df157171087bab7b4a564107161eatuexen	if (inp == NULL) {
73978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
73988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ECONNRESET);
73998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
74018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
74028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
74038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
74048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EOPNOTSUPP);
74058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so->so_state & SS_ISDISCONNECTED) {
74078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
74088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
74098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ECONNABORTED);
74108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = LIST_FIRST(&inp->sctp_asoc_list);
74128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
74138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
74148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
74158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ECONNRESET);
74168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_LOCK(stcb);
74188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(inp);
74198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	store = stcb->asoc.primary_destination->ro._l_addr;
74208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
74218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
74228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (store.sa.sa_family) {
74238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
74248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
74258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
74268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sin;
74278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
74288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
74298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
74308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sin == NULL)
74318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (ENOMEM);
74328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
74338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin = (struct sockaddr_in *)addr;
74348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero((caddr_t)sin, sizeof(*sin));
74358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_family = AF_INET;
74377b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
74388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_len = sizeof(*sin);
74398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74407988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sin->sin_port = store.sin.sin_port;
74417988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sin->sin_addr = store.sin.sin_addr;
74428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
74438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*addr = (struct sockaddr *)sin;
74448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif !defined(__Panda__)
74458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_BUF_LEN(nam) = sizeof(*sin);
74468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
74488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
74518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
74528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
74538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6;
74548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
74558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
74568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
74578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sin6 == NULL)
74588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (ENOMEM);
74598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
74608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6 = (struct sockaddr_in6 *)addr;
74618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero((caddr_t)sin6, sizeof(*sin6));
74628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_family = AF_INET6;
74647b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
74658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_len = sizeof(*sin6);
74668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74677988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sin6->sin6_port = store.sin6.sin6_port;
74687988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sin6->sin6_addr = store.sin6.sin6_addr;
74698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE)
74708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
74718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((error = sa6_recoverscope(sin6)) != 0) {
74728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE_SONAME(sin6);
74738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (error);
74748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
74768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
74778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
74788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * sin6->sin6_scope_id =
74798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * ntohs(sin6->sin6_addr.s6_addr16[1]);
74808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
74818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			in6_recoverscope(sin6, &sin6->sin6_addr, NULL);	/* skip ifp check */
74828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
74838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin6->sin6_scope_id = 0;	/* XXX */
74848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_KAME */
74858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
74860612043f643c9b26245564c05defca64d472060etuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) || defined(__Userspace__)
74878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*addr = (struct sockaddr *)sin6;
74888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif !defined(__Panda__)
74898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_BUF_LEN(nam) = sizeof(*sin6);
74908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
74928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74947988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
74957988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	case AF_CONN:
74967988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	{
74977988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		struct sockaddr_conn *sconn;
74987988ea8f0c067cf3757e798b473b1ae4d34b6dfdt
74997988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		SCTP_MALLOC_SONAME(sconn, struct sockaddr_conn *, sizeof(struct sockaddr_conn));
75007988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		if (sconn == NULL) {
75017988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			return (ENOMEM);
75027988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		}
75037988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sconn->sconn_family = AF_CONN;
75047988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#ifdef HAVE_SCONN_LEN
75057988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sconn->sconn_len = sizeof(struct sockaddr_conn);
75067988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
75077988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sconn->sconn_port = store.sconn.sconn_port;
75087988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		sconn->sconn_addr = store.sconn.sconn_addr;
75097988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		*addr = (struct sockaddr *)sconn;
75107988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		break;
75117988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	}
75127988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
75138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
75148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* TSNH */
75158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
75168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
75178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Wake any delayed sleep action */
75188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
75198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WLOCK(inp);
75208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
75218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
75228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
75238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WUNLOCK(inp);
75248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
75258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sowriteable(inp->sctp_socket)) {
75268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
75278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                            /*__Userspace__ calling sowwakup_locked because of SOCKBUF_LOCK above. */
75288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
75298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
75308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sowwakeup_locked(inp->sctp_socket);
75318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
75328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
75338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* socket is locked */
75348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
75358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sowwakeup(inp->sctp_socket);
75368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
75378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
75388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
75398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
75408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WLOCK(inp);
75418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
75428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
75438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
75448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WUNLOCK(inp);
75458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
75468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (soreadable(inp->sctp_socket)) {
75478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_defered_wakeup_cnt++;
75488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
75498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                                /*__Userspace__ calling sorwakup_locked because of SOCKBUF_LOCK above */
75508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
75518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__Windows__) || defined(__Userspace__)
75528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sorwakeup_locked(inp->sctp_socket);
75538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
75548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
75558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* socket is locked */
75568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
75578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sorwakeup(inp->sctp_socket);
75588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
75598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
75608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
75618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
75628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WLOCK(inp);
75638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
75648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_WUNLOCK(inp);
75658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
75668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
75678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
75688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7);
75698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
75708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
75718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
75728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
75738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
75748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
75758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
75768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_ingetaddr(struct socket *so, struct sockaddr **addr)
75778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
75788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin;
75798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
75808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_ingetaddr(struct socket *so, struct sockaddr *addr)
75818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
75828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
75838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
75848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_ingetaddr(struct socket *so, struct mbuf *nam)
75858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
75868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
75878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
75888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
75898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
75908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *sctp_ifa;
75918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
75928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
75938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Do the malloc first in case it blocks.
75948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
75958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
75968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
75978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sin == NULL)
75988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOMEM);
75998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
76008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(sin, sizeof(*sin));
76018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
76028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(nam) = sizeof(*sin);
76038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(sin, 0, sizeof(*sin));
76048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
76058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin->sin_family = AF_INET;
76067b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
76078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin->sin_len = sizeof(*sin);
76088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
76098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
76108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!inp) {
76118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
76128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE_SONAME(sin);
76138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
76148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7615b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (ECONNRESET);
76168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
76178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
76188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin->sin_port = inp->sctp_lport;
76198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
76208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
76218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_tcb *stcb;
76228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr_in *sin_a;
76238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_nets *net;
76248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int fnd;
76258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
76268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb = LIST_FIRST(&inp->sctp_asoc_list);
76278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb == NULL) {
76288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto notConn;
76298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
76308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			fnd = 0;
76318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin_a = NULL;
76328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(stcb);
76338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
76348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin_a = (struct sockaddr_in *)&net->ro._l_addr;
76358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin_a == NULL)
76368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* this will make coverity happy */
76378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
76388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
76398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin_a->sin_family == AF_INET) {
76408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					fnd = 1;
76418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
76428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
76438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
76448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((!fnd) || (sin_a == NULL)) {
76458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* punt */
76468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_TCB_UNLOCK(stcb);
76478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto notConn;
76488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
76498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
76508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			vrf_id = inp->def_vrf_id;
76518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ifa = sctp_source_address_selection(inp,
76528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								 stcb,
76538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								 (sctp_route_t *)&net->ro,
76548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								 net, 0, vrf_id);
76558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_ifa) {
76568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin->sin_addr = sctp_ifa->address.sin.sin_addr;
76578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_ifa(sctp_ifa);
76588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
76598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
76608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
76618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* For the bound all case you get back 0 */
76628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	notConn:
76638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin->sin_addr.s_addr = 0;
76648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
76658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
76668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
76678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Take the first IPv4 address in the list */
76688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_laddr *laddr;
76698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int fnd = 0;
76708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
76718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
76728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (laddr->ifa->address.sa.sa_family == AF_INET) {
76738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sockaddr_in *sin_a;
76748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
76758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
76768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin->sin_addr = sin_a->sin_addr;
76778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				fnd = 1;
76788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
76798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
76808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
76818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!fnd) {
76828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
76838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE_SONAME(sin);
76848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
76858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(inp);
76868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7687b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			return (ENOENT);
76888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
76898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
76908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(inp);
76918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
76928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(*addr) = (struct sockaddr *)sin;
76938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
76948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
76958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
76968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
76978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
76988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
76998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_peeraddr(struct socket *so, struct sockaddr **addr)
77008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7701845436a72b5767f30403c3b77c457488703143a9tuexen	struct sockaddr_in *sin;
77028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
77038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_peeraddr(struct socket *so, struct sockaddr *addr)
77048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
77058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin = (struct sockaddr_in *)addr;
77068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
77078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_peeraddr(struct socket *so, struct mbuf *nam)
77088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
77098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
77108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int fnd;
77138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin_a;
77148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
77158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb;
77168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
77178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Do the malloc first in case it blocks. */
77198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
77208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
77218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sin == NULL)
77228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOMEM);
77238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Panda__)
77248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(sin, 0, sizeof(*sin));
77258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
77268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(nam) = sizeof(*sin);
77278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(sin, 0, sizeof(*sin));
77288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin->sin_family = AF_INET;
77307b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
77318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin->sin_len = sizeof(*sin);
77328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
7735b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((inp == NULL) ||
7736b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
7737b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		/* UDP type and listeners will drop out here */
77388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
77398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE_SONAME(sin);
77408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7741b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
7742b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (ENOTCONN);
77438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
77448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RLOCK(inp);
77458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = LIST_FIRST(&inp->sctp_asoc_list);
77468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
77478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
77488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
77498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(inp);
77508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
77518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
77528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE_SONAME(sin);
77538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7755b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (ECONNRESET);
77568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
77578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	fnd = 0;
77588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
77598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin_a = (struct sockaddr_in *)&net->ro._l_addr;
77608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sin_a->sin_family == AF_INET) {
77618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			fnd = 1;
77628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin->sin_port = stcb->rport;
77638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin->sin_addr = sin_a->sin_addr;
77648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
77658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
77668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
77678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_TCB_UNLOCK(stcb);
77688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!fnd) {
77698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* No IPv4 address */
77708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
77718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE_SONAME(sin);
77728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7774b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (ENOENT);
77758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
77768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
77778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(*addr) = (struct sockaddr *)sin;
77788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
77808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
77818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)
77838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct pr_usrreqs sctp_usrreqs = {
77847fbcb406549bdf370031d2ad5befb44e39b95ffft#if defined(__FreeBSD__)
77858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_abort = sctp_abort,
77868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_accept = sctp_accept,
77878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_attach = sctp_attach,
77888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_bind = sctp_bind,
77898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_connect = sctp_connect,
77908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_control = in_control,
77918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version >= 690000
77928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_close = sctp_close,
77938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_detach = sctp_close,
77948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_sopoll = sopoll_generic,
77958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_flush = sctp_flush,
77968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
77978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_detach = sctp_detach,
77988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_sopoll = sopoll,
77998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
78008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_disconnect = sctp_disconnect,
78018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_listen = sctp_listen,
78028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_peeraddr = sctp_peeraddr,
78038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_send = sctp_sendm,
78048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_shutdown = sctp_shutdown,
78058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_sockaddr = sctp_ingetaddr,
78068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_sosend = sctp_sosend,
78078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	.pru_soreceive = sctp_soreceive
78087fbcb406549bdf370031d2ad5befb44e39b95ffft#elif defined(__APPLE__)
78097fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_abort = sctp_abort,
78107fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_accept = sctp_accept,
78117fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_attach = sctp_attach,
78127fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_bind = sctp_bind,
78137fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_connect = sctp_connect,
78147fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_connect2 = pru_connect2_notsupp,
78157fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_control = in_control,
78167fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_detach = sctp_detach,
78177fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_disconnect = sctp_disconnect,
78187fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_listen = sctp_listen,
78197fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_peeraddr = sctp_peeraddr,
78207fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_rcvd = NULL,
78217fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_rcvoob = pru_rcvoob_notsupp,
78227fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_send = sctp_sendm,
78237fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sense = pru_sense_null,
78247fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_shutdown = sctp_shutdown,
78257fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sockaddr = sctp_ingetaddr,
78267fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sosend = sctp_sosend,
78277fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_soreceive = sctp_soreceive,
78287fbcb406549bdf370031d2ad5befb44e39b95ffft	.pru_sopoll = sopoll
78297fbcb406549bdf370031d2ad5befb44e39b95ffft#elif defined(__Windows__)
78308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_abort,
78318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_accept,
78328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_attach,
78338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_bind,
78348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_connect,
78358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pru_connect2_notsupp,
78368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	NULL,
78378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	NULL,
78388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_disconnect,
78398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_listen,
78408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_peeraddr,
78418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	NULL,
78428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pru_rcvoob_notsupp,
78438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	NULL,
78448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pru_sense_null,
78458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_shutdown,
78468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_flush,
78478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_ingetaddr,
78488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sosend,
78498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_soreceive,
78508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sopoll_generic,
78518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	NULL,
78528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_close
78538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
78548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen};
78558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif !defined(__Panda__) && !defined(__Userspace__)
78568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
78578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_usrreq(so, req, m, nam, control)
78588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *so;
78598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int req;
78608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m, *nam, *control;
78618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
78628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct proc *p = curproc;
78638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
78648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_vrf *vrf;
78658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error;
78668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int family;
78678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp = (struct sctp_inpcb *)so->so_pcb;
78688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
78698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = 0;
78708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	family = so->so_proto->pr_domain->dom_family;
78718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (req == PRU_CONTROL) {
78728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (family) {
78738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case PF_INET:
78748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = in_control(so, (long)m, (caddr_t)nam,
7875b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			    (struct ifnet *)control);
78768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
78778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
78788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case PF_INET6:
78798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = in6_control(so, (long)m, (caddr_t)nam,
78808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct ifnet *)control, p);
78818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
78828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
78838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
78848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
78858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EAFNOSUPPORT;
78868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
78878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (error);
78888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
78898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (req) {
78908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_ATTACH:
78918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_attach(so, family, p);
78928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
78938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_DETACH:
78948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_detach(so);
78958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
78968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_BIND:
78978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (nam == NULL) {
78988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
78998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
79008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
79018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_bind(so, nam, p);
79028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_LISTEN:
79048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_listen(so, p);
79058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_CONNECT:
79078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (nam == NULL) {
79088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
79098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
79108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
79118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_connect(so, nam, p);
79128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_DISCONNECT:
79148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_disconnect(so);
79158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_ACCEPT:
79178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (nam == NULL) {
79188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
79198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (EINVAL);
79208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
79218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_accept(so, nam);
79228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SHUTDOWN:
79248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_shutdown(so);
79258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_RCVD:
79288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
79298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * For Open and Net BSD, this is real ugly. The mbuf *nam
79308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * that is passed (by soreceive()) is the int flags c ast as
79318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * a (mbuf *) yuck!
79328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
79338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SEND:
79368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Flags are ignored */
79378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
79388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr *addr;
79398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (nam == NULL)
79418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr = NULL;
79428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
79438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr = mtod(nam, struct sockaddr *);
79448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = sctp_sendm(so, 0, m, addr, control, p);
79468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
79478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_ABORT:
79498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_abort(so);
79508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SENSE:
79538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = 0;
79548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_RCVOOB:
79568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
79578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EAFNOSUPPORT;
79588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SENDOOB:
79608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
79618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = EAFNOSUPPORT;
79628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_PEERADDR:
79648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_peeraddr(so, nam);
79658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SOCKADDR:
79678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_ingetaddr(so, nam);
79688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case PRU_SLOWTIMO:
79708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = 0;
79718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
79738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
79748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
79758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
79768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
79778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
79788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
79798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
798060416fb97d019e56677da96dbdac6d48048822d3tuexen
798132a191a90b5c914a02047389c5b3197e08fc9841tuexen#if defined(__Userspace__)
798260416fb97d019e56677da96dbdac6d48048822d3tuexenint
7983d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexenregister_recv_cb(struct socket *so,
7984d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen                 int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data,
7985d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen                 size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info))
798660416fb97d019e56677da96dbdac6d48048822d3tuexen{
7987d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	struct sctp_inpcb *inp;
798860416fb97d019e56677da96dbdac6d48048822d3tuexen
798960416fb97d019e56677da96dbdac6d48048822d3tuexen	inp = (struct sctp_inpcb *) so->so_pcb;
799032a191a90b5c914a02047389c5b3197e08fc9841tuexen	if (inp == NULL) {
799132a191a90b5c914a02047389c5b3197e08fc9841tuexen		return (0);
799232a191a90b5c914a02047389c5b3197e08fc9841tuexen	}
799332a191a90b5c914a02047389c5b3197e08fc9841tuexen	SCTP_INP_WLOCK(inp);
799460416fb97d019e56677da96dbdac6d48048822d3tuexen	inp->recv_callback = receive_cb;
799532a191a90b5c914a02047389c5b3197e08fc9841tuexen	SCTP_INP_WUNLOCK(inp);
7996f57cf83923be449d11806a31f62bcc17e58832d6t	return (1);
799760416fb97d019e56677da96dbdac6d48048822d3tuexen}
799860416fb97d019e56677da96dbdac6d48048822d3tuexen
799960416fb97d019e56677da96dbdac6d48048822d3tuexenint
8000d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexenregister_send_cb(struct socket *so, uint32_t sb_threshold, int (*send_cb)(struct socket *sock, uint32_t sb_free))
800160416fb97d019e56677da96dbdac6d48048822d3tuexen{
8002d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	struct sctp_inpcb *inp;
800360416fb97d019e56677da96dbdac6d48048822d3tuexen
800460416fb97d019e56677da96dbdac6d48048822d3tuexen	inp = (struct sctp_inpcb *) so->so_pcb;
800532a191a90b5c914a02047389c5b3197e08fc9841tuexen	if (inp == NULL) {
800632a191a90b5c914a02047389c5b3197e08fc9841tuexen		return (0);
800732a191a90b5c914a02047389c5b3197e08fc9841tuexen	}
800832a191a90b5c914a02047389c5b3197e08fc9841tuexen	SCTP_INP_WLOCK(inp);
800960416fb97d019e56677da96dbdac6d48048822d3tuexen	inp->send_callback = send_cb;
801060416fb97d019e56677da96dbdac6d48048822d3tuexen	inp->send_sb_threshold = sb_threshold;
801132a191a90b5c914a02047389c5b3197e08fc9841tuexen	SCTP_INP_WUNLOCK(inp);
801260416fb97d019e56677da96dbdac6d48048822d3tuexen	/* FIXME change to current amount free. This will be the full buffer
801360416fb97d019e56677da96dbdac6d48048822d3tuexen	 * the first time this is registered but it could be only a portion
801460416fb97d019e56677da96dbdac6d48048822d3tuexen	 * of the send buffer if this is called a second time e.g. if the
801560416fb97d019e56677da96dbdac6d48048822d3tuexen	 * threshold changes.
801660416fb97d019e56677da96dbdac6d48048822d3tuexen	 */
8017f57cf83923be449d11806a31f62bcc17e58832d6t	return (1);
801860416fb97d019e56677da96dbdac6d48048822d3tuexen}
8019d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen
8020d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexenint
8021d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexenregister_ulp_info (struct socket *so, void *ulp_info)
8022d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen{
8023d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	struct sctp_inpcb *inp;
8024d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen
8025d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	inp = (struct sctp_inpcb *) so->so_pcb;
8026d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	if (inp == NULL) {
8027d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen		return (0);
8028d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	}
8029d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	SCTP_INP_WLOCK(inp);
8030d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	inp->ulp_info = ulp_info;
8031d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen	SCTP_INP_WUNLOCK(inp);
8032f57cf83923be449d11806a31f62bcc17e58832d6t	return (1);
8033d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen}
803460416fb97d019e56677da96dbdac6d48048822d3tuexen#endif
8035